From faecab9ca53943a07747ab52b4e3597b484f36b6 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Thu, 30 Dec 2010 18:07:29 +0000 Subject: [PATCH] Refactoring of Drawables with new class MarkerList. Fixes for Mac 10.5 SDK includes and minor change to win32 repainting. --- Builds/Linux/Makefile | 6 + Builds/MacOSX/Juce.xcodeproj/project.pbxproj | 6 + Builds/VisualStudio2005/Juce.vcproj | 2 + Builds/VisualStudio2008/Juce.vcproj | 2 + Builds/VisualStudio2008_DLL/Juce.vcproj | 2 + Builds/VisualStudio2010/Juce.vcxproj | 2 + Builds/VisualStudio2010/Juce.vcxproj.filters | 6 + Builds/iPhone/Juce.xcodeproj/project.pbxproj | 6 + Juce.jucer | 4 + amalgamation/juce_amalgamated_template.cpp | 1 + juce_amalgamated.cpp | 611 ++++++++++-------- juce_amalgamated.h | 311 ++++++--- src/core/juce_StandardHeader.h | 2 +- src/gui/components/juce_Component.cpp | 6 + src/gui/components/juce_Component.h | 9 + .../layout/juce_ComponentBuilder.cpp | 91 +-- .../components/layout/juce_ComponentBuilder.h | 140 ++-- src/gui/components/layout/juce_MarkerList.cpp | 262 ++++++++ src/gui/components/layout/juce_MarkerList.h | 141 ++++ src/gui/graphics/drawables/juce_Drawable.cpp | 40 +- src/gui/graphics/drawables/juce_Drawable.h | 12 +- .../drawables/juce_DrawableComposite.cpp | 237 ++----- .../drawables/juce_DrawableComposite.h | 41 +- src/juce_app_includes.h | 3 + src/native/mac/juce_mac_NativeIncludes.h | 4 +- src/native/windows/juce_win32_Windowing.cpp | 5 +- 26 files changed, 1265 insertions(+), 687 deletions(-) create mode 100644 src/gui/components/layout/juce_MarkerList.cpp create mode 100644 src/gui/components/layout/juce_MarkerList.h diff --git a/Builds/Linux/Makefile b/Builds/Linux/Makefile index 6de1c013b5..06001ac06a 100644 --- a/Builds/Linux/Makefile +++ b/Builds/Linux/Makefile @@ -174,6 +174,7 @@ OBJECTS := \ $(OBJDIR)/juce_ComponentBuilder_2aa6c5a.o \ $(OBJDIR)/juce_ComponentMovementWatcher_cbb3e7cc.o \ $(OBJDIR)/juce_GroupComponent_456e237a.o \ + $(OBJDIR)/juce_MarkerList_aea878b4.o \ $(OBJDIR)/juce_MultiDocumentPanel_50e05aac.o \ $(OBJDIR)/juce_ResizableBorderComponent_7f4f2182.o \ $(OBJDIR)/juce_ResizableCornerComponent_1cac2df9.o \ @@ -1038,6 +1039,11 @@ $(OBJDIR)/juce_GroupComponent_456e237a.o: ../../src/gui/components/layout/juce_G @echo "Compiling juce_GroupComponent.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/juce_MarkerList_aea878b4.o: ../../src/gui/components/layout/juce_MarkerList.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling juce_MarkerList.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/juce_MultiDocumentPanel_50e05aac.o: ../../src/gui/components/layout/juce_MultiDocumentPanel.cpp -@mkdir -p $(OBJDIR) @echo "Compiling juce_MultiDocumentPanel.cpp" diff --git a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj index 80452f8435..800016d767 100644 --- a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj @@ -143,6 +143,7 @@ 9AA76460DA7D34CE6A69E2B1 = { isa = PBXBuildFile; fileRef = 45E5EE9E0173683D721FABDA; }; 4E81BC4A50CF1883F529E152 = { isa = PBXBuildFile; fileRef = F8FCCCE06D31FEF697FCD80D; }; 8FBB6BF0C5406E1BA481CFEF = { isa = PBXBuildFile; fileRef = A6AD7357F905309D1B461EB7; }; + 260EF664D324038F9DC6C35B = { isa = PBXBuildFile; fileRef = F665A039C3A85EFDAA3E1245; }; F5F3F25D9F377128DC74D95B = { isa = PBXBuildFile; fileRef = FF046140CCF1EDB0DFF80178; }; C64A2BF05224582134872415 = { isa = PBXBuildFile; fileRef = A95F42C5CB0C2E5052B31568; }; 0A9C9486A6B31F21B1472D2B = { isa = PBXBuildFile; fileRef = A31221E2A50CCE9DF06B5F4B; }; @@ -666,6 +667,8 @@ 44CDA79090B115C3B62A2168 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ComponentMovementWatcher.h; path = ../../src/gui/components/layout/juce_ComponentMovementWatcher.h; sourceTree = SOURCE_ROOT; }; A6AD7357F905309D1B461EB7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_GroupComponent.cpp; path = ../../src/gui/components/layout/juce_GroupComponent.cpp; sourceTree = SOURCE_ROOT; }; E9242E8425497D889C764C66 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_GroupComponent.h; path = ../../src/gui/components/layout/juce_GroupComponent.h; sourceTree = SOURCE_ROOT; }; + F665A039C3A85EFDAA3E1245 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_MarkerList.cpp; path = ../../src/gui/components/layout/juce_MarkerList.cpp; sourceTree = SOURCE_ROOT; }; + 8A9F1A98C0C96BF655F606AB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_MarkerList.h; path = ../../src/gui/components/layout/juce_MarkerList.h; sourceTree = SOURCE_ROOT; }; FF046140CCF1EDB0DFF80178 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_MultiDocumentPanel.cpp; path = ../../src/gui/components/layout/juce_MultiDocumentPanel.cpp; sourceTree = SOURCE_ROOT; }; B6A223FB5B4A9388C83D6FC7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_MultiDocumentPanel.h; path = ../../src/gui/components/layout/juce_MultiDocumentPanel.h; sourceTree = SOURCE_ROOT; }; A95F42C5CB0C2E5052B31568 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ResizableBorderComponent.cpp; path = ../../src/gui/components/layout/juce_ResizableBorderComponent.cpp; sourceTree = SOURCE_ROOT; }; @@ -1397,6 +1400,8 @@ 44CDA79090B115C3B62A2168, A6AD7357F905309D1B461EB7, E9242E8425497D889C764C66, + F665A039C3A85EFDAA3E1245, + 8A9F1A98C0C96BF655F606AB, FF046140CCF1EDB0DFF80178, B6A223FB5B4A9388C83D6FC7, A95F42C5CB0C2E5052B31568, @@ -2077,6 +2082,7 @@ 9AA76460DA7D34CE6A69E2B1, 4E81BC4A50CF1883F529E152, 8FBB6BF0C5406E1BA481CFEF, + 260EF664D324038F9DC6C35B, F5F3F25D9F377128DC74D95B, C64A2BF05224582134872415, 0A9C9486A6B31F21B1472D2B, diff --git a/Builds/VisualStudio2005/Juce.vcproj b/Builds/VisualStudio2005/Juce.vcproj index 2c373303ea..777a348135 100644 --- a/Builds/VisualStudio2005/Juce.vcproj +++ b/Builds/VisualStudio2005/Juce.vcproj @@ -548,6 +548,8 @@ + + diff --git a/Builds/VisualStudio2008/Juce.vcproj b/Builds/VisualStudio2008/Juce.vcproj index c95082b1f1..3e667a2b01 100644 --- a/Builds/VisualStudio2008/Juce.vcproj +++ b/Builds/VisualStudio2008/Juce.vcproj @@ -548,6 +548,8 @@ + + diff --git a/Builds/VisualStudio2008_DLL/Juce.vcproj b/Builds/VisualStudio2008_DLL/Juce.vcproj index 241319cb67..45e4a4a7bb 100644 --- a/Builds/VisualStudio2008_DLL/Juce.vcproj +++ b/Builds/VisualStudio2008_DLL/Juce.vcproj @@ -550,6 +550,8 @@ + + diff --git a/Builds/VisualStudio2010/Juce.vcxproj b/Builds/VisualStudio2010/Juce.vcxproj index 7ed1943b4b..67e2ac3826 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj +++ b/Builds/VisualStudio2010/Juce.vcxproj @@ -257,6 +257,7 @@ + @@ -607,6 +608,7 @@ + diff --git a/Builds/VisualStudio2010/Juce.vcxproj.filters b/Builds/VisualStudio2010/Juce.vcxproj.filters index df1b24df2d..04f398f6d0 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj.filters +++ b/Builds/VisualStudio2010/Juce.vcxproj.filters @@ -625,6 +625,9 @@ Juce\Source\gui\components\layout + + Juce\Source\gui\components\layout + Juce\Source\gui\components\layout @@ -1749,6 +1752,9 @@ Juce\Source\gui\components\layout + + Juce\Source\gui\components\layout + Juce\Source\gui\components\layout diff --git a/Builds/iPhone/Juce.xcodeproj/project.pbxproj b/Builds/iPhone/Juce.xcodeproj/project.pbxproj index e7da403ef1..408c9dc847 100644 --- a/Builds/iPhone/Juce.xcodeproj/project.pbxproj +++ b/Builds/iPhone/Juce.xcodeproj/project.pbxproj @@ -143,6 +143,7 @@ 9AA76460DA7D34CE6A69E2B1 = { isa = PBXBuildFile; fileRef = 45E5EE9E0173683D721FABDA; }; 4E81BC4A50CF1883F529E152 = { isa = PBXBuildFile; fileRef = F8FCCCE06D31FEF697FCD80D; }; 8FBB6BF0C5406E1BA481CFEF = { isa = PBXBuildFile; fileRef = A6AD7357F905309D1B461EB7; }; + 260EF664D324038F9DC6C35B = { isa = PBXBuildFile; fileRef = F665A039C3A85EFDAA3E1245; }; F5F3F25D9F377128DC74D95B = { isa = PBXBuildFile; fileRef = FF046140CCF1EDB0DFF80178; }; C64A2BF05224582134872415 = { isa = PBXBuildFile; fileRef = A95F42C5CB0C2E5052B31568; }; 0A9C9486A6B31F21B1472D2B = { isa = PBXBuildFile; fileRef = A31221E2A50CCE9DF06B5F4B; }; @@ -666,6 +667,8 @@ 44CDA79090B115C3B62A2168 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ComponentMovementWatcher.h; path = ../../src/gui/components/layout/juce_ComponentMovementWatcher.h; sourceTree = SOURCE_ROOT; }; A6AD7357F905309D1B461EB7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_GroupComponent.cpp; path = ../../src/gui/components/layout/juce_GroupComponent.cpp; sourceTree = SOURCE_ROOT; }; E9242E8425497D889C764C66 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_GroupComponent.h; path = ../../src/gui/components/layout/juce_GroupComponent.h; sourceTree = SOURCE_ROOT; }; + F665A039C3A85EFDAA3E1245 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_MarkerList.cpp; path = ../../src/gui/components/layout/juce_MarkerList.cpp; sourceTree = SOURCE_ROOT; }; + 8A9F1A98C0C96BF655F606AB = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_MarkerList.h; path = ../../src/gui/components/layout/juce_MarkerList.h; sourceTree = SOURCE_ROOT; }; FF046140CCF1EDB0DFF80178 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_MultiDocumentPanel.cpp; path = ../../src/gui/components/layout/juce_MultiDocumentPanel.cpp; sourceTree = SOURCE_ROOT; }; B6A223FB5B4A9388C83D6FC7 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_MultiDocumentPanel.h; path = ../../src/gui/components/layout/juce_MultiDocumentPanel.h; sourceTree = SOURCE_ROOT; }; A95F42C5CB0C2E5052B31568 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ResizableBorderComponent.cpp; path = ../../src/gui/components/layout/juce_ResizableBorderComponent.cpp; sourceTree = SOURCE_ROOT; }; @@ -1397,6 +1400,8 @@ 44CDA79090B115C3B62A2168, A6AD7357F905309D1B461EB7, E9242E8425497D889C764C66, + F665A039C3A85EFDAA3E1245, + 8A9F1A98C0C96BF655F606AB, FF046140CCF1EDB0DFF80178, B6A223FB5B4A9388C83D6FC7, A95F42C5CB0C2E5052B31568, @@ -2077,6 +2082,7 @@ 9AA76460DA7D34CE6A69E2B1, 4E81BC4A50CF1883F529E152, 8FBB6BF0C5406E1BA481CFEF, + 260EF664D324038F9DC6C35B, F5F3F25D9F377128DC74D95B, C64A2BF05224582134872415, 0A9C9486A6B31F21B1472D2B, diff --git a/Juce.jucer b/Juce.jucer index 300ec3a2f4..6fdbeec275 100644 --- a/Juce.jucer +++ b/Juce.jucer @@ -728,6 +728,10 @@ file="src/gui/components/layout/juce_GroupComponent.cpp"/> + + #import #endif - #if JUCE_BUILD_MISC && (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_AU) \ - && ! (defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) + #if (JUCE_BUILD_MISC && (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_AU)) \ + || ! (defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) #include #endif #include @@ -41524,6 +41524,11 @@ void Component::colourChanged() { } +MarkerList* Component::getMarkers (bool /*xAxis*/) +{ + return 0; +} + const Rectangle Component::getLocalBounds() const throw() { return Rectangle (getWidth(), getHeight()); @@ -61337,6 +61342,35 @@ namespace ComponentBuilderHelpers c->setComponentID (getStateId (state)); return c; } + + void updateComponent (ComponentBuilder& builder, const ValueTree& state) + { + Component* topLevelComp = builder.getManagedComponent(); + + if (topLevelComp != 0) + { + const String compId (getStateId (state)); + + if (compId.isEmpty() && state.getParent().isValid()) + { + // ..handle the case where a child of the actual state node has changed. + updateComponent (builder, state.getParent()); + } + else + { + ComponentBuilder::TypeHandler* const type = builder.getHandlerForState (state); + + if (type != 0) + { + Component* const changedComp = findComponentWithID (topLevelComp, compId); + + if (changedComp != 0) + type->updateComponentFromState (changedComp, state); + } + } + } + } + } const Identifier ComponentBuilder::idProperty ("id"); @@ -61350,28 +61384,36 @@ ComponentBuilder::ComponentBuilder (const ValueTree& state_) ComponentBuilder::~ComponentBuilder() { state.removeListener (this); + + #if JUCE_DEBUG + // Don't delete the managed component!! The builder owns that component, and will delete + // it automatically when it gets deleted. + jassert (componentRef.get() == static_cast (component)); + #endif } -Component* ComponentBuilder::getComponent() +Component* ComponentBuilder::getManagedComponent() { if (component == 0) { - jassert (types.size() > 0); // You need to register all the necessary types before you can load a component! + component = createComponent(); - TypeHandler* const type = getHandlerForState (state); - jassert (type != 0); // trying to create a component from an unknown type of ValueTree - - if (type != 0) - component = ComponentBuilderHelpers::createNewComponent (*type, state, 0); + #if JUCE_DEBUG + componentRef = component; + #endif } return component; } -Component* ComponentBuilder::getAndReleaseComponent() +Component* ComponentBuilder::createComponent() { - getComponent(); - return component.release(); + jassert (types.size() > 0); // You need to register all the necessary types before you can load a component! + + TypeHandler* const type = getHandlerForState (state); + jassert (type != 0); // trying to create a component from an unknown type of ValueTree + + return type != 0 ? ComponentBuilderHelpers::createNewComponent (*type, state, 0) : 0; } void ComponentBuilder::registerTypeHandler (ComponentBuilder::TypeHandler* const type) @@ -61411,34 +61453,6 @@ ComponentBuilder::TypeHandler* ComponentBuilder::getHandler (const int index) co return types [index]; } -void ComponentBuilder::updateComponent (const ValueTree& state) -{ - using namespace ComponentBuilderHelpers; - - if (component != 0) - { - const String compId (getStateId (state)); - - if (compId.isEmpty() && state.getParent().isValid()) - { - // ..handle the case where a child of the actual state node has changed. - updateComponent (state.getParent()); - } - else - { - TypeHandler* const type = getHandlerForState (state); - - if (type != 0) - { - Component* const changedComp = findComponentWithID (component, compId); - - if (changedComp != 0) - type->updateComponentFromState (changedComp, state); - } - } - } -} - void ComponentBuilder::setImageProvider (ImageProvider* newImageProvider) throw() { imageProvider = newImageProvider; @@ -61451,17 +61465,17 @@ ComponentBuilder::ImageProvider* ComponentBuilder::getImageProvider() const thro void ComponentBuilder::valueTreePropertyChanged (ValueTree& tree, const Identifier&) { - updateComponent (tree); + ComponentBuilderHelpers::updateComponent (*this, tree); } void ComponentBuilder::valueTreeChildrenChanged (ValueTree& tree) { - updateComponent (tree); + ComponentBuilderHelpers::updateComponent (*this, tree); } void ComponentBuilder::valueTreeParentChanged (ValueTree& tree) { - updateComponent (tree); + ComponentBuilderHelpers::updateComponent (*this, tree); } ComponentBuilder::TypeHandler::TypeHandler (const Identifier& valueTreeType_) @@ -61995,6 +62009,238 @@ END_JUCE_NAMESPACE /*** End of inlined file: juce_GroupComponent.cpp ***/ +/*** Start of inlined file: juce_MarkerList.cpp ***/ +BEGIN_JUCE_NAMESPACE + +MarkerList::MarkerList() +{ +} + +MarkerList::MarkerList (const MarkerList& other) +{ + operator= (other); +} + +MarkerList& MarkerList::operator= (const MarkerList& other) +{ + if (other != *this) + { + markers.clear(); + markers.addCopiesOf (other.markers); + markersHaveChanged(); + } + + return *this; +} + +MarkerList::~MarkerList() +{ +} + +bool MarkerList::operator== (const MarkerList& other) const throw() +{ + if (other.markers.size() != markers.size()) + return false; + + for (int i = markers.size(); --i >= 0;) + { + const Marker* const m1 = markers.getUnchecked(i); + jassert (m1 != 0); + + const Marker* const m2 = other.getMarker (m1->name); + + if (m2 == 0 || *m1 != *m2) + return false; + } + + return true; +} + +bool MarkerList::operator!= (const MarkerList& other) const throw() +{ + return ! operator== (other); +} + +int MarkerList::getNumMarkers() const throw() +{ + return markers.size(); +} + +const MarkerList::Marker* MarkerList::getMarker (const int index) const throw() +{ + return markers [index]; +} + +const MarkerList::Marker* MarkerList::getMarker (const String& name) const throw() +{ + for (int i = 0; i < markers.size(); ++i) + { + const Marker* const m = markers.getUnchecked(i); + + if (m->name == name) + return m; + } + + return 0; +} + +void MarkerList::setMarker (const String& name, const RelativeCoordinate& position) +{ + Marker* const m = const_cast (getMarker (name)); + + if (m != 0) + { + if (m->position != position) + { + m->position = position; + markersHaveChanged(); + } + + return; + } + + markers.add (new Marker (name, position)); + markersHaveChanged(); +} + +void MarkerList::removeMarker (const int index) +{ + if (isPositiveAndBelow (index, markers.size())) + { + markers.remove (index); + markersHaveChanged(); + } +} + +void MarkerList::removeMarker (const String& name) +{ + for (int i = 0; i < markers.size(); ++i) + { + const Marker* const m = markers.getUnchecked(i); + + if (m->name == name) + { + markers.remove (i); + markersHaveChanged(); + } + } +} + +void MarkerList::markersHaveChanged() +{ + sendChangeMessage(); +} + +MarkerList::Marker::Marker (const Marker& other) + : name (other.name), position (other.position) +{ +} + +MarkerList::Marker::Marker (const String& name_, const RelativeCoordinate& position_) + : name (name_), position (position_) +{ +} + +bool MarkerList::Marker::operator== (const Marker& other) const throw() +{ + return name == other.name && position == other.position; +} + +bool MarkerList::Marker::operator!= (const Marker& other) const throw() +{ + return ! operator== (other); +} + +const Identifier MarkerList::ValueTreeWrapper::markerTag ("Marker"); +const Identifier MarkerList::ValueTreeWrapper::nameProperty ("name"); +const Identifier MarkerList::ValueTreeWrapper::posProperty ("position"); + +MarkerList::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_) + : state (state_) +{ +} + +int MarkerList::ValueTreeWrapper::getNumMarkers() const +{ + return state.getNumChildren(); +} + +const ValueTree MarkerList::ValueTreeWrapper::getMarkerState (int index) const +{ + return state.getChild (index); +} + +const ValueTree MarkerList::ValueTreeWrapper::getMarkerState (const String& name) const +{ + return state.getChildWithProperty (nameProperty, name); +} + +bool MarkerList::ValueTreeWrapper::containsMarker (const ValueTree& marker) const +{ + return marker.isAChildOf (state); +} + +const MarkerList::Marker MarkerList::ValueTreeWrapper::getMarker (const ValueTree& marker) const +{ + jassert (containsMarker (marker)); + + return MarkerList::Marker (marker [nameProperty], RelativeCoordinate (marker [posProperty].toString())); +} + +void MarkerList::ValueTreeWrapper::setMarker (const MarkerList::Marker& m, UndoManager* undoManager) +{ + ValueTree marker (state.getChildWithProperty (nameProperty, m.name)); + + if (marker.isValid()) + { + marker.setProperty (posProperty, m.position.toString(), undoManager); + } + else + { + marker = ValueTree (markerTag); + marker.setProperty (nameProperty, m.name, 0); + marker.setProperty (posProperty, m.position.toString(), 0); + state.addChild (marker, -1, undoManager); + } +} + +void MarkerList::ValueTreeWrapper::removeMarker (const ValueTree& marker, UndoManager* undoManager) +{ + state.removeChild (marker, undoManager); +} + +void MarkerList::ValueTreeWrapper::applyTo (MarkerList& markerList) +{ + const int numMarkers = getNumMarkers(); + + StringArray updatedMarkers; + + int i; + for (i = 0; i < numMarkers; ++i) + { + const ValueTree marker (state.getChild (i)); + const String name (marker [nameProperty].toString()); + markerList.setMarker (name, RelativeCoordinate (marker [posProperty].toString())); + updatedMarkers.add (name); + } + + for (i = markerList.getNumMarkers(); --i >= 0;) + if (! updatedMarkers.contains (markerList.getMarker (i)->name)) + markerList.removeMarker (i); +} + +void MarkerList::ValueTreeWrapper::readFrom (const MarkerList& markerList, UndoManager* undoManager) +{ + state.removeAllChildren (undoManager); + + for (int i = 0; i < markerList.getNumMarkers(); ++i) + setMarker (*markerList.getMarker(i), undoManager); +} + +END_JUCE_NAMESPACE +/*** End of inlined file: juce_MarkerList.cpp ***/ + + /*** Start of inlined file: juce_MultiDocumentPanel.cpp ***/ BEGIN_JUCE_NAMESPACE @@ -85738,10 +85984,6 @@ void Drawable::transformContextToCorrectOrigin (Graphics& g) originRelativeToComponent.getY()); } -void Drawable::markerHasMoved() -{ -} - void Drawable::parentHierarchyChanged() { setBoundsToEnclose (getDrawableBounds()); @@ -85816,20 +86058,6 @@ Drawable* Drawable::createFromImageFile (const File& file) return fin != 0 ? createFromImageDataStream (*fin) : 0; } -Drawable* Drawable::createFromValueTree (const ValueTree& tree, ComponentBuilder::ImageProvider* imageProvider) -{ - ComponentBuilder builder (tree); - builder.setImageProvider (imageProvider); - registerDrawableTypes (builder); - - Drawable* d = dynamic_cast (builder.getComponent()); - - if (d != 0) - return dynamic_cast (builder.getAndReleaseComponent()); - - return 0; -} - template class DrawableTypeHandler : public ComponentBuilder::TypeHandler { @@ -85858,7 +86086,7 @@ public: } }; -void Drawable::registerDrawableTypes (ComponentBuilder& builder) +void Drawable::registerDrawableTypeHandlers (ComponentBuilder& builder) { builder.registerTypeHandler (new DrawableTypeHandler ()); builder.registerTypeHandler (new DrawableTypeHandler ()); @@ -85867,12 +86095,23 @@ void Drawable::registerDrawableTypes (ComponentBuilder& builder) builder.registerTypeHandler (new DrawableTypeHandler ()); } -Drawable::ValueTreeWrapperBase::ValueTreeWrapperBase (const ValueTree& state_) - : state (state_) +Drawable* Drawable::createFromValueTree (const ValueTree& tree, ComponentBuilder::ImageProvider* imageProvider) { + ComponentBuilder builder (tree); + builder.setImageProvider (imageProvider); + registerDrawableTypeHandlers (builder); + + ScopedPointer comp (builder.createComponent()); + Drawable* const d = dynamic_cast (static_cast (comp)); + + if (d != 0) + comp.release(); + + return d; } -Drawable::ValueTreeWrapperBase::~ValueTreeWrapperBase() +Drawable::ValueTreeWrapperBase::ValueTreeWrapperBase (const ValueTree& state_) + : state (state_) { } @@ -86248,6 +86487,8 @@ DrawableComposite::DrawableComposite() DrawableComposite::DrawableComposite (const DrawableComposite& other) : bounds (other.bounds), + markersX (other.markersX), + markersY (other.markersY), updateBoundsReentrant (false) { for (int i = 0; i < other.getNumChildComponents(); ++i) @@ -86257,9 +86498,6 @@ DrawableComposite::DrawableComposite (const DrawableComposite& other) if (d != 0) addAndMakeVisible (d->createCopy()); } - - markersX.addCopiesOf (other.markersX); - markersY.addCopiesOf (other.markersY); } DrawableComposite::~DrawableComposite() @@ -86283,32 +86521,26 @@ const Rectangle DrawableComposite::getDrawableBounds() const return r; } -void DrawableComposite::markerHasMoved() +MarkerList* DrawableComposite::getMarkers (bool xAxis) { - for (int i = getNumChildComponents(); --i >= 0;) - { - Drawable* const d = dynamic_cast (getChildComponent(i)); - - if (d != 0) - d->markerHasMoved(); - } + return xAxis ? &markersX : &markersY; } const RelativeRectangle DrawableComposite::getContentArea() const { - jassert (markersX.size() >= 2 && getMarker (true, 0)->name == contentLeftMarkerName && getMarker (true, 1)->name == contentRightMarkerName); - jassert (markersY.size() >= 2 && getMarker (false, 0)->name == contentTopMarkerName && getMarker (false, 1)->name == contentBottomMarkerName); + jassert (markersX.getNumMarkers() >= 2 && markersX.getMarker (0)->name == contentLeftMarkerName && markersX.getMarker (1)->name == contentRightMarkerName); + jassert (markersY.getNumMarkers() >= 2 && markersY.getMarker (0)->name == contentTopMarkerName && markersY.getMarker (1)->name == contentBottomMarkerName); - return RelativeRectangle (markersX.getUnchecked(0)->position, markersX.getUnchecked(1)->position, - markersY.getUnchecked(0)->position, markersY.getUnchecked(1)->position); + return RelativeRectangle (markersX.getMarker(0)->position, markersX.getMarker(1)->position, + markersY.getMarker(0)->position, markersY.getMarker(1)->position); } void DrawableComposite::setContentArea (const RelativeRectangle& newArea) { - setMarker (contentLeftMarkerName, true, newArea.left); - setMarker (contentRightMarkerName, true, newArea.right); - setMarker (contentTopMarkerName, false, newArea.top); - setMarker (contentBottomMarkerName, false, newArea.bottom); + markersX.setMarker (contentLeftMarkerName, newArea.left); + markersX.setMarker (contentRightMarkerName, newArea.right); + markersY.setMarker (contentTopMarkerName, newArea.top); + markersY.setMarker (contentBottomMarkerName, newArea.bottom); refreshTransformFromBounds(); } @@ -86422,80 +86654,17 @@ const char* const DrawableComposite::contentRightMarkerName = "right"; const char* const DrawableComposite::contentTopMarkerName = "top"; const char* const DrawableComposite::contentBottomMarkerName = "bottom"; -DrawableComposite::Marker::Marker (const DrawableComposite::Marker& other) - : name (other.name), position (other.position) -{ -} - -DrawableComposite::Marker::Marker (const String& name_, const RelativeCoordinate& position_) - : name (name_), position (position_) -{ -} - -bool DrawableComposite::Marker::operator!= (const DrawableComposite::Marker& other) const throw() -{ - return name != other.name || position != other.position; -} - -int DrawableComposite::getNumMarkers (const bool xAxis) const throw() -{ - return (xAxis ? markersX : markersY).size(); -} - -const DrawableComposite::Marker* DrawableComposite::getMarker (const bool xAxis, const int index) const throw() -{ - return (xAxis ? markersX : markersY) [index]; -} - -void DrawableComposite::setMarker (const String& name, const bool xAxis, const RelativeCoordinate& position) -{ - OwnedArray & markers = (xAxis ? markersX : markersY); - - for (int i = 0; i < markers.size(); ++i) - { - Marker* const m = markers.getUnchecked(i); - if (m->name == name) - { - if (m->position != position) - { - m->position = position; - markerHasMoved(); - } - - return; - } - } - - (xAxis ? markersX : markersY).add (new Marker (name, position)); - markerHasMoved(); -} - -void DrawableComposite::removeMarker (const bool xAxis, const int index) -{ - jassert (index >= 2); - - if (index >= 2) - (xAxis ? markersX : markersY).remove (index); -} - const Expression DrawableComposite::getSymbolValue (const String& symbol, const String& member) const { jassert (member.isEmpty()) // the only symbols available in a Drawable are markers. - int i; - for (i = 0; i < markersX.size(); ++i) - { - Marker* const m = markersX.getUnchecked(i); - if (m->name == symbol) - return m->position.getExpression(); - } + const MarkerList::Marker* m = markersX.getMarker (symbol); - for (i = 0; i < markersY.size(); ++i) - { - Marker* const m = markersY.getUnchecked(i); - if (m->name == symbol) - return m->position.getExpression(); - } + if (m == 0) + m = markersY.getMarker (symbol); + + if (m != 0) + return m->position.getExpression(); throw Expression::EvaluationError (symbol, member); } @@ -86513,9 +86682,6 @@ const Identifier DrawableComposite::ValueTreeWrapper::bottomLeft ("bottomLeft"); const Identifier DrawableComposite::ValueTreeWrapper::childGroupTag ("Drawables"); const Identifier DrawableComposite::ValueTreeWrapper::markerGroupTagX ("MarkersX"); const Identifier DrawableComposite::ValueTreeWrapper::markerGroupTagY ("MarkersY"); -const Identifier DrawableComposite::ValueTreeWrapper::markerTag ("Marker"); -const Identifier DrawableComposite::ValueTreeWrapper::nameProperty ("name"); -const Identifier DrawableComposite::ValueTreeWrapper::posProperty ("position"); DrawableComposite::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_) : ValueTreeWrapperBase (state_) @@ -86558,85 +86724,36 @@ void DrawableComposite::ValueTreeWrapper::resetBoundingBoxToContentArea (UndoMan const RelativeRectangle DrawableComposite::ValueTreeWrapper::getContentArea() const { - return RelativeRectangle (getMarker (true, getMarkerState (true, 0)).position, - getMarker (true, getMarkerState (true, 1)).position, - getMarker (false, getMarkerState (false, 0)).position, - getMarker (false, getMarkerState (false, 1)).position); + MarkerList::ValueTreeWrapper markersX (getMarkerList (true)); + MarkerList::ValueTreeWrapper markersY (getMarkerList (false)); + + return RelativeRectangle (markersX.getMarker (markersX.getMarkerState (0)).position, + markersX.getMarker (markersX.getMarkerState (1)).position, + markersY.getMarker (markersY.getMarkerState (0)).position, + markersY.getMarker (markersY.getMarkerState (1)).position); } void DrawableComposite::ValueTreeWrapper::setContentArea (const RelativeRectangle& newArea, UndoManager* undoManager) { - setMarker (true, Marker (contentLeftMarkerName, newArea.left), undoManager); - setMarker (true, Marker (contentRightMarkerName, newArea.right), undoManager); - setMarker (false, Marker (contentTopMarkerName, newArea.top), undoManager); - setMarker (false, Marker (contentBottomMarkerName, newArea.bottom), undoManager); + MarkerList::ValueTreeWrapper markersX (getMarkerListCreating (true, 0)); + MarkerList::ValueTreeWrapper markersY (getMarkerListCreating (false, 0)); + + markersX.setMarker (MarkerList::Marker (contentLeftMarkerName, newArea.left), undoManager); + markersX.setMarker (MarkerList::Marker (contentRightMarkerName, newArea.right), undoManager); + markersY.setMarker (MarkerList::Marker (contentTopMarkerName, newArea.top), undoManager); + markersY.setMarker (MarkerList::Marker (contentBottomMarkerName, newArea.bottom), undoManager); } -ValueTree DrawableComposite::ValueTreeWrapper::getMarkerList (bool xAxis) const +MarkerList::ValueTreeWrapper DrawableComposite::ValueTreeWrapper::getMarkerList (bool xAxis) const { return state.getChildWithName (xAxis ? markerGroupTagX : markerGroupTagY); } -ValueTree DrawableComposite::ValueTreeWrapper::getMarkerListCreating (bool xAxis, UndoManager* undoManager) +MarkerList::ValueTreeWrapper DrawableComposite::ValueTreeWrapper::getMarkerListCreating (bool xAxis, UndoManager* undoManager) { return state.getOrCreateChildWithName (xAxis ? markerGroupTagX : markerGroupTagY, undoManager); } -int DrawableComposite::ValueTreeWrapper::getNumMarkers (bool xAxis) const -{ - return getMarkerList (xAxis).getNumChildren(); -} - -const ValueTree DrawableComposite::ValueTreeWrapper::getMarkerState (bool xAxis, int index) const -{ - return getMarkerList (xAxis).getChild (index); -} - -const ValueTree DrawableComposite::ValueTreeWrapper::getMarkerState (bool xAxis, const String& name) const -{ - return getMarkerList (xAxis).getChildWithProperty (nameProperty, name); -} - -bool DrawableComposite::ValueTreeWrapper::containsMarker (bool xAxis, const ValueTree& state) const -{ - return state.isAChildOf (getMarkerList (xAxis)); -} - -const DrawableComposite::Marker DrawableComposite::ValueTreeWrapper::getMarker (bool xAxis, const ValueTree& state) const -{ - (void) xAxis; - jassert (containsMarker (xAxis, state)); - - return Marker (state [nameProperty], RelativeCoordinate (state [posProperty].toString())); -} - -void DrawableComposite::ValueTreeWrapper::setMarker (bool xAxis, const Marker& m, UndoManager* undoManager) -{ - ValueTree markerList (getMarkerListCreating (xAxis, undoManager)); - ValueTree marker (markerList.getChildWithProperty (nameProperty, m.name)); - - if (marker.isValid()) - { - marker.setProperty (posProperty, m.position.toString(), undoManager); - } - else - { - marker = ValueTree (markerTag); - marker.setProperty (nameProperty, m.name, 0); - marker.setProperty (posProperty, m.position.toString(), 0); - markerList.addChild (marker, -1, undoManager); - } -} - -void DrawableComposite::ValueTreeWrapper::removeMarker (bool xAxis, const ValueTree& state, UndoManager* undoManager) -{ - if (state [nameProperty].toString() != contentLeftMarkerName - && state [nameProperty].toString() != contentRightMarkerName - && state [nameProperty].toString() != contentTopMarkerName - && state [nameProperty].toString() != contentBottomMarkerName) - getMarkerList (xAxis).removeChild (state, undoManager); -} - void DrawableComposite::refreshFromValueTree (const ValueTree& tree, ComponentBuilder& builder) { const ValueTreeWrapper wrapper (tree); @@ -86646,39 +86763,8 @@ void DrawableComposite::refreshFromValueTree (const ValueTree& tree, ComponentBu if (bounds != newBounds) bounds = newBounds; - const int numMarkersX = wrapper.getNumMarkers (true); - const int numMarkersY = wrapper.getNumMarkers (false); - - // Remove deleted markers... - if (markersX.size() > numMarkersX || markersY.size() > numMarkersY) - { - markersX.removeRange (jmax (2, numMarkersX), markersX.size()); - markersY.removeRange (jmax (2, numMarkersY), markersY.size()); - } - - // Update markers and add new ones.. - int i; - for (i = 0; i < numMarkersX; ++i) - { - const Marker newMarker (wrapper.getMarker (true, wrapper.getMarkerState (true, i))); - Marker* m = markersX[i]; - - if (m == 0) - markersX.add (new Marker (newMarker)); - else if (newMarker != *m) - *m = newMarker; - } - - for (i = 0; i < numMarkersY; ++i) - { - const Marker newMarker (wrapper.getMarker (false, wrapper.getMarkerState (false, i))); - Marker* m = markersY[i]; - - if (m == 0) - markersY.add (new Marker (newMarker)); - else if (newMarker != *m) - *m = newMarker; - } + wrapper.getMarkerList (true).applyTo (markersX); + wrapper.getMarkerList (false).applyTo (markersY); builder.updateChildComponents (*this, wrapper.getChildList()); @@ -86695,18 +86781,16 @@ const ValueTree DrawableComposite::createValueTree (ComponentBuilder::ImageProvi ValueTree childList (v.getChildListCreating (0)); - int i; - for (i = getNumChildComponents(); --i >= 0;) + for (int i = getNumChildComponents(); --i >= 0;) { const Drawable* const d = dynamic_cast (getChildComponent(i)); + jassert (d != 0); // You can't save a mix of Drawables and normal components! + childList.addChild (d->createValueTree (imageProvider), -1, 0); } - for (i = 0; i < markersX.size(); ++i) - v.setMarker (true, *markersX.getUnchecked(i), 0); - - for (i = 0; i < markersY.size(); ++i) - v.setMarker (false, *markersY.getUnchecked(i), 0); + v.getMarkerListCreating (true, 0).readFrom (markersX, 0); + v.getMarkerListCreating (false, 0).readFrom (markersY, 0); return tree; } @@ -243214,11 +243298,10 @@ private: return 0; case WM_NCPAINT: - if (wParam != 1) - handlePaintMessage(); - if (hasTitleBar()) break; + else if (wParam != 1) + handlePaintMessage(); return 0; diff --git a/juce_amalgamated.h b/juce_amalgamated.h index b3db2466bd..8a2e014a1a 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 2 +#define JUCE_BUILDNUMBER 3 /** Current Juce version number. @@ -26874,6 +26874,7 @@ class LookAndFeel; class MouseInputSource; class MouseInputSourceInternal; class ComponentPeer; +class MarkerList; /** The base class for all JUCE user-interface objects. @@ -28803,6 +28804,13 @@ public: */ virtual void colourChanged(); + /** Components can implement this method to provide a MarkerList. + The default implementation of this method returns 0, but you can override it to + return a pointer to the component's marker list. If xAxis is true, it should + return the X marker list; if false, it should return the Y markers. + */ + virtual MarkerList* getMarkers (bool xAxis); + /** Returns the underlying native window handle for this component. This is platform-dependent and strictly for power-users only! @@ -45704,58 +45712,97 @@ public: class JUCE_API ComponentBuilder : public ValueTree::Listener { public: - /** + /** Creates a ComponentBuilder that will use the given state. + Once you've created your builder, you should use registerTypeHandler() to register some + type handlers for it, and then you can call createComponent() or getManagedComponent() + to get the actual component. */ explicit ComponentBuilder (const ValueTree& state); /** Destructor. */ ~ComponentBuilder(); - /** - */ + /** Returns the ValueTree that this builder is working with. */ ValueTree& getState() throw() { return state; } - /** - */ + /** Returns the ValueTree that this builder is working with. */ const ValueTree& getState() const throw() { return state; } - /** + /** Returns the builder's component (creating it if necessary). + + The first time that this method is called, the builder will attempt to create a component + from the ValueTree, so you must have registered some suitable type handlers before calling + this. If there's a problem and the component can't be created, this method returns 0. + + The component that is returned is owned by this ComponentBuilder, so you can put it inside + your own parent components, but don't delete it! The ComponentBuilder will delete it automatically + when the builder is destroyed. If you want to get a component that you can delete yourself, + call createComponent() instead. + + The ComponentBuilder will update this component if any changes are made to the ValueTree, so if + there's a chance that the tree might change, be careful not to keep any pointers to sub-components, + as they may be changed or removed. */ - Component* getComponent(); + Component* getManagedComponent(); - /** + /** Creates and returns a new instance of the component that the ValueTree represents. + The caller is responsible for using and deleting the object that is returned. Unlike + getManagedComponent(), the component that is returned will not be updated by the builder. */ - Component* getAndReleaseComponent(); + Component* createComponent(); /** + The class is a base class for objects that manage the loading of a type of component + from a ValueTree. + + To store and re-load a tree of components as a ValueTree, each component type must have + a TypeHandler to represent it. + + @see ComponentBuilder::registerTypeHandler(), Drawable::registerDrawableTypeHandlers() */ class JUCE_API TypeHandler { public: - /** + + /** Creates a TypeHandler. + The valueTreeType must be the type name of the ValueTrees that this handler can parse. */ explicit TypeHandler (const Identifier& valueTreeType); /** Destructor. */ virtual ~TypeHandler(); - /** - */ + /** Returns the type of the ValueTrees that this handler can parse. */ const Identifier& getType() const throw() { return valueTreeType; } - /** + /** Returns the builder that this type is registered with. */ + ComponentBuilder* getBuilder() const throw(); + + /** This method must create a new component from the given state, add it to the specified + parent component (which may be null), and return it. + + The ValueTree will have been pre-checked to make sure that its type matches the type + that this handler supports. + + There's no need to set the new Component's ID to match that of the state - the builder + will take care of that itself. */ virtual Component* addNewComponentFromState (const ValueTree& state, Component* parent) = 0; - /** - */ - virtual void updateComponentFromState (Component* component, const ValueTree& state) = 0; + /** This method must update an existing component from a new ValueTree state. + + A component that has been created with addNewComponentFromState() may need to be updated + if the ValueTree changes, so this method is used to do that. Your implementation must do + whatever's necessary to update the component from the new state provided. - /** + The ValueTree will have been pre-checked to make sure that its type matches the type + that this handler supports, and the component will have been created by this type's + addNewComponentFromState() method. */ - ComponentBuilder* getBuilder() const throw(); + virtual void updateComponentFromState (Component* component, const ValueTree& state) = 0; private: + friend class ComponentBuilder; ComponentBuilder* builder; const Identifier valueTreeType; @@ -45763,25 +45810,35 @@ public: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TypeHandler); }; - /** + /** Adds a type handler that the builder can use when trying to load components. + @see Drawable::registerDrawableTypeHandlers() */ void registerTypeHandler (TypeHandler* type); - /** - */ + /** Tries to find a registered type handler that can load a component from the given ValueTree. */ TypeHandler* getHandlerForState (const ValueTree& state) const; - /** + /** Returns the number of registered type handlers. + @see getHandler, registerTypeHandler */ int getNumHandlers() const throw(); - /** + /** Returns one of the registered type handlers. + @see getNumHandlers, registerTypeHandler */ TypeHandler* getHandler (int index) const throw(); - /** This class is used when loading Drawables that contain images, and retrieves - the image for a stored identifier. - @see Drawable::createFromValueTree + /** This class is used when references to images need to be stored in ValueTrees. + + An instance of an ImageProvider provides a mechanism for converting an Image to/from + a reference, which may be a file, URL, ID string, or whatever system is appropriate in + your app. + + When you're loading components from a ValueTree that may need a way of loading images, you + should call ComponentBuilder::setImageProvider() to supply a suitable provider before + trying to load the component. + + @see ComponentBuilder::setImageProvider() */ class JUCE_API ImageProvider { @@ -45798,18 +45855,33 @@ public: virtual const Image getImageForIdentifier (const var& imageIdentifier) = 0; /** Returns an identifier to be used to refer to a given image. - This is used when converting a drawable into a ValueTree, so if you're - only loading drawables, you can just return a var::null here. + This is used when a reference to an image is stored in a ValueTree. */ virtual const var getIdentifierForImage (const Image& image) = 0; }; - /** */ + /** Gives the builder an ImageProvider object that the type handlers can use when + loading images from stored references. + + The object that is passed in is not owned by the builder, so the caller must delete + it when it is no longer needed, but not while the builder may still be using it. To + clear the image provider, just call setImageProvider (0). + */ void setImageProvider (ImageProvider* newImageProvider) throw(); - /** */ + /** Returns the current image provider that this builder is using, or 0 if none has been set. */ ImageProvider* getImageProvider() const throw(); + /** Updates the children of a parent component by updating them from the children of + a given ValueTree. + */ + void updateChildComponents (Component& parent, const ValueTree& children); + + /** An identifier for the property of the ValueTrees that is used to store a unique ID + for that component. + */ + static const Identifier idProperty; + /** @internal */ void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const Identifier& property); /** @internal */ @@ -45817,22 +45889,15 @@ public: /** @internal */ void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged); - /** - */ - void updateChildComponents (Component& parent, const ValueTree& children); - - /** - */ - static const Identifier idProperty; - private: ValueTree state; OwnedArray types; ScopedPointer component; ImageProvider* imageProvider; - - void updateComponent (const ValueTree& state); + #if JUCE_DEBUG + WeakReference componentRef; + #endif JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentBuilder); }; @@ -45964,6 +46029,7 @@ public: If there are any images used within the drawable, you'll need to provide a valid ImageProvider object that can be used to retrieve these images from whatever type of identifier is used to represent them. + Internally, this uses a ComponentBuilder, and registerDrawableTypeHandlers(). */ static Drawable* createFromValueTree (const ValueTree& tree, ComponentBuilder::ImageProvider* imageProvider); @@ -45985,7 +46051,6 @@ public: { public: ValueTreeWrapperBase (const ValueTree& state); - ~ValueTreeWrapperBase(); ValueTree& getState() throw() { return state; } @@ -45995,7 +46060,11 @@ public: ValueTree state; }; - static void registerDrawableTypes (ComponentBuilder& componentBuilder); + /** Registers a set of ComponentBuilder::TypeHandler objects that can be used to + load all the different Drawable types from a saved state. + @see ComponentBuilder::registerTypeHandler() + */ + static void registerDrawableTypeHandlers (ComponentBuilder& componentBuilder); protected: @@ -46005,8 +46074,6 @@ protected: /** @internal */ void transformContextToCorrectOrigin (Graphics& g); /** @internal */ - void markerHasMoved(); - /** @internal */ void parentHierarchyChanged(); /** @internal */ void setBoundsToEnclose (const Rectangle& area); @@ -53890,6 +53957,120 @@ private: /*** End of inlined file: juce_GroupComponent.h ***/ +#endif +#ifndef __JUCE_MARKERLIST_JUCEHEADER__ + +/*** Start of inlined file: juce_MarkerList.h ***/ +#ifndef __JUCE_MARKERLIST_JUCEHEADER__ +#define __JUCE_MARKERLIST_JUCEHEADER__ + +/** + Holds a set of named marker points along a one-dimensional axis. + + This class is used to store sets of X and Y marker points in components. + @see Component::getMarkers(). + + The MarkerList is also a ChangeBroadcaster, so that listeners can register to receive + a callback when a marker is moved, +*/ +class JUCE_API MarkerList : public ChangeBroadcaster +{ +public: + + /** Creates an empty marker list. */ + MarkerList(); + /** Creates a copy of another marker list. */ + MarkerList (const MarkerList& other); + /** Copies another marker list to this one. */ + MarkerList& operator= (const MarkerList& other); + /** Destructor. */ + ~MarkerList(); + + /** Represents a marker in a MarkerList. */ + class JUCE_API Marker + { + public: + /** Creates a copy of another Marker. */ + Marker (const Marker& other); + /** Creates a Marker with a given name and position. */ + Marker (const String& name, const RelativeCoordinate& position); + + /** The marker's name. */ + String name; + + /** The marker's position. */ + RelativeCoordinate position; + + /** Returns true if both the names and positions of these two markers match. */ + bool operator== (const Marker&) const throw(); + /** Returns true if either the name or position of these two markers differ. */ + bool operator!= (const Marker&) const throw(); + }; + + /** Returns the number of markers in the list. */ + int getNumMarkers() const throw(); + + /** Returns one of the markers in the list, by its index. */ + const Marker* getMarker (int index) const throw(); + + /** Returns a named marker, or 0 if no such name is found. + Note that name comparisons are case-sensitive. + */ + const Marker* getMarker (const String& name) const throw(); + + /** Sets the position of a marker. + + If the name already exists, then the existing marker is moved; if it doesn't exist, then a + new marker is added. + */ + void setMarker (const String& name, const RelativeCoordinate& position); + + /** Deletes the marker at the given list index. */ + void removeMarker (int index); + + /** Deletes the marker with the given name. */ + void removeMarker (const String& name); + + /** Returns true if all the markers in these two lists match exactly. */ + bool operator== (const MarkerList& other) const throw(); + /** Returns true if not all the markers in these two lists match exactly. */ + bool operator!= (const MarkerList& other) const throw(); + + /** Forms a wrapper around a ValueTree that can be used for storing a MarkerList. */ + class ValueTreeWrapper + { + public: + ValueTreeWrapper (const ValueTree& state); + + int getNumMarkers() const; + const ValueTree getMarkerState (int index) const; + const ValueTree getMarkerState (const String& name) const; + bool containsMarker (const ValueTree& state) const; + const MarkerList::Marker getMarker (const ValueTree& state) const; + void setMarker (const MarkerList::Marker& marker, UndoManager* undoManager); + void removeMarker (const ValueTree& state, UndoManager* undoManager); + + void applyTo (MarkerList& markerList); + void readFrom (const MarkerList& markerList, UndoManager* undoManager); + + private: + ValueTree state; + + static const Identifier markerTag, nameProperty, posProperty; + }; + +private: + + OwnedArray markers; + void markersHaveChanged(); + + JUCE_LEAK_DETECTOR (MarkerList); +}; + +#endif // __JUCE_MARKERLIST_JUCEHEADER__ +/*** End of inlined file: juce_MarkerList.h ***/ + + #endif #ifndef __JUCE_MULTIDOCUMENTPANEL_JUCEHEADER__ @@ -61398,24 +61579,6 @@ public: */ void resetContentAreaAndBoundingBoxToFitChildren(); - /** Represents a named marker position. - @see DrawableComposite::getMarker - */ - struct Marker - { - Marker (const Marker&); - Marker (const String& name, const RelativeCoordinate& position); - bool operator!= (const Marker&) const throw(); - - String name; - RelativeCoordinate position; - }; - - int getNumMarkers (bool xAxis) const throw(); - const Marker* getMarker (bool xAxis, int index) const throw(); - void setMarker (const String& name, bool xAxis, const RelativeCoordinate& position); - void removeMarker (bool xAxis, int index); - /** The name of the marker that defines the left edge of the content area. */ static const char* const contentLeftMarkerName; /** The name of the marker that defines the right edge of the content area. */ @@ -61438,13 +61601,13 @@ public: /** @internal */ const Rectangle getDrawableBounds() const; /** @internal */ - void markerHasMoved(); - /** @internal */ void childBoundsChanged (Component*); /** @internal */ void childrenChanged(); /** @internal */ void parentHierarchyChanged(); + /** @internal */ + MarkerList* getMarkers (bool xAxis); /** Internally-used class for wrapping a DrawableComposite's state into a ValueTree. */ class ValueTreeWrapper : public Drawable::ValueTreeWrapperBase @@ -61462,27 +61625,19 @@ public: const RelativeRectangle getContentArea() const; void setContentArea (const RelativeRectangle& newArea, UndoManager* undoManager); - int getNumMarkers (bool xAxis) const; - const ValueTree getMarkerState (bool xAxis, int index) const; - const ValueTree getMarkerState (bool xAxis, const String& name) const; - bool containsMarker (bool xAxis, const ValueTree& state) const; - const Marker getMarker (bool xAxis, const ValueTree& state) const; - void setMarker (bool xAxis, const Marker& marker, UndoManager* undoManager); - void removeMarker (bool xAxis, const ValueTree& state, UndoManager* undoManager); + MarkerList::ValueTreeWrapper getMarkerList (bool xAxis) const; + MarkerList::ValueTreeWrapper getMarkerListCreating (bool xAxis, UndoManager* undoManager); - static const Identifier nameProperty, posProperty, topLeft, topRight, bottomLeft; + static const Identifier topLeft, topRight, bottomLeft; private: - static const Identifier childGroupTag, markerGroupTagX, markerGroupTagY, markerTag; - - ValueTree getMarkerList (bool xAxis) const; - ValueTree getMarkerListCreating (bool xAxis, UndoManager* undoManager); + static const Identifier childGroupTag, markerGroupTagX, markerGroupTagY; }; private: RelativeParallelogram bounds; - OwnedArray markersX, markersY; + MarkerList markersX, markersY; bool updateBoundsReentrant; void refreshTransformFromBounds(); diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 6653845508..b2b5aa236c 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.h @@ -33,7 +33,7 @@ */ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 53 -#define JUCE_BUILDNUMBER 2 +#define JUCE_BUILDNUMBER 3 /** Current Juce version number. diff --git a/src/gui/components/juce_Component.cpp b/src/gui/components/juce_Component.cpp index a6b2a74685..99dc9e0d94 100644 --- a/src/gui/components/juce_Component.cpp +++ b/src/gui/components/juce_Component.cpp @@ -2049,6 +2049,12 @@ void Component::colourChanged() { } +//============================================================================== +MarkerList* Component::getMarkers (bool /*xAxis*/) +{ + return 0; +} + //============================================================================== const Rectangle Component::getLocalBounds() const throw() { diff --git a/src/gui/components/juce_Component.h b/src/gui/components/juce_Component.h index 686a165560..98858a5528 100644 --- a/src/gui/components/juce_Component.h +++ b/src/gui/components/juce_Component.h @@ -47,6 +47,7 @@ class LookAndFeel; class MouseInputSource; class MouseInputSourceInternal; class ComponentPeer; +class MarkerList; //============================================================================== @@ -2016,6 +2017,14 @@ public: */ virtual void colourChanged(); + //============================================================================== + /** Components can implement this method to provide a MarkerList. + The default implementation of this method returns 0, but you can override it to + return a pointer to the component's marker list. If xAxis is true, it should + return the X marker list; if false, it should return the Y markers. + */ + virtual MarkerList* getMarkers (bool xAxis); + //============================================================================== /** Returns the underlying native window handle for this component. diff --git a/src/gui/components/layout/juce_ComponentBuilder.cpp b/src/gui/components/layout/juce_ComponentBuilder.cpp index 8b0b200620..d76ea7cf11 100644 --- a/src/gui/components/layout/juce_ComponentBuilder.cpp +++ b/src/gui/components/layout/juce_ComponentBuilder.cpp @@ -78,6 +78,35 @@ namespace ComponentBuilderHelpers c->setComponentID (getStateId (state)); return c; } + + void updateComponent (ComponentBuilder& builder, const ValueTree& state) + { + Component* topLevelComp = builder.getManagedComponent(); + + if (topLevelComp != 0) + { + const String compId (getStateId (state)); + + if (compId.isEmpty() && state.getParent().isValid()) + { + // ..handle the case where a child of the actual state node has changed. + updateComponent (builder, state.getParent()); + } + else + { + ComponentBuilder::TypeHandler* const type = builder.getHandlerForState (state); + + if (type != 0) + { + Component* const changedComp = findComponentWithID (topLevelComp, compId); + + if (changedComp != 0) + type->updateComponentFromState (changedComp, state); + } + } + } + } + } //============================================================================= @@ -92,28 +121,36 @@ ComponentBuilder::ComponentBuilder (const ValueTree& state_) ComponentBuilder::~ComponentBuilder() { state.removeListener (this); + + #if JUCE_DEBUG + // Don't delete the managed component!! The builder owns that component, and will delete + // it automatically when it gets deleted. + jassert (componentRef.get() == static_cast (component)); + #endif } -Component* ComponentBuilder::getComponent() +Component* ComponentBuilder::getManagedComponent() { if (component == 0) { - jassert (types.size() > 0); // You need to register all the necessary types before you can load a component! - - TypeHandler* const type = getHandlerForState (state); - jassert (type != 0); // trying to create a component from an unknown type of ValueTree + component = createComponent(); - if (type != 0) - component = ComponentBuilderHelpers::createNewComponent (*type, state, 0); + #if JUCE_DEBUG + componentRef = component; + #endif } return component; } -Component* ComponentBuilder::getAndReleaseComponent() +Component* ComponentBuilder::createComponent() { - getComponent(); - return component.release(); + jassert (types.size() > 0); // You need to register all the necessary types before you can load a component! + + TypeHandler* const type = getHandlerForState (state); + jassert (type != 0); // trying to create a component from an unknown type of ValueTree + + return type != 0 ? ComponentBuilderHelpers::createNewComponent (*type, state, 0) : 0; } void ComponentBuilder::registerTypeHandler (ComponentBuilder::TypeHandler* const type) @@ -153,34 +190,6 @@ ComponentBuilder::TypeHandler* ComponentBuilder::getHandler (const int index) co return types [index]; } -void ComponentBuilder::updateComponent (const ValueTree& state) -{ - using namespace ComponentBuilderHelpers; - - if (component != 0) - { - const String compId (getStateId (state)); - - if (compId.isEmpty() && state.getParent().isValid()) - { - // ..handle the case where a child of the actual state node has changed. - updateComponent (state.getParent()); - } - else - { - TypeHandler* const type = getHandlerForState (state); - - if (type != 0) - { - Component* const changedComp = findComponentWithID (component, compId); - - if (changedComp != 0) - type->updateComponentFromState (changedComp, state); - } - } - } -} - void ComponentBuilder::setImageProvider (ImageProvider* newImageProvider) throw() { imageProvider = newImageProvider; @@ -193,17 +202,17 @@ ComponentBuilder::ImageProvider* ComponentBuilder::getImageProvider() const thro void ComponentBuilder::valueTreePropertyChanged (ValueTree& tree, const Identifier&) { - updateComponent (tree); + ComponentBuilderHelpers::updateComponent (*this, tree); } void ComponentBuilder::valueTreeChildrenChanged (ValueTree& tree) { - updateComponent (tree); + ComponentBuilderHelpers::updateComponent (*this, tree); } void ComponentBuilder::valueTreeParentChanged (ValueTree& tree) { - updateComponent (tree); + ComponentBuilderHelpers::updateComponent (*this, tree); } //============================================================================== diff --git a/src/gui/components/layout/juce_ComponentBuilder.h b/src/gui/components/layout/juce_ComponentBuilder.h index c776129bc7..17acbf34f9 100644 --- a/src/gui/components/layout/juce_ComponentBuilder.h +++ b/src/gui/components/layout/juce_ComponentBuilder.h @@ -49,7 +49,10 @@ class JUCE_API ComponentBuilder : public ValueTree::Listener { public: - /** + /** Creates a ComponentBuilder that will use the given state. + Once you've created your builder, you should use registerTypeHandler() to register some + type handlers for it, and then you can call createComponent() or getManagedComponent() + to get the actual component. */ explicit ComponentBuilder (const ValueTree& state); @@ -57,52 +60,89 @@ public: ~ComponentBuilder(); //============================================================================== - /** - */ + /** Returns the ValueTree that this builder is working with. */ ValueTree& getState() throw() { return state; } - /** - */ + /** Returns the ValueTree that this builder is working with. */ const ValueTree& getState() const throw() { return state; } - /** + /** Returns the builder's component (creating it if necessary). + + The first time that this method is called, the builder will attempt to create a component + from the ValueTree, so you must have registered some suitable type handlers before calling + this. If there's a problem and the component can't be created, this method returns 0. + + The component that is returned is owned by this ComponentBuilder, so you can put it inside + your own parent components, but don't delete it! The ComponentBuilder will delete it automatically + when the builder is destroyed. If you want to get a component that you can delete yourself, + call createComponent() instead. + + The ComponentBuilder will update this component if any changes are made to the ValueTree, so if + there's a chance that the tree might change, be careful not to keep any pointers to sub-components, + as they may be changed or removed. */ - Component* getComponent(); + Component* getManagedComponent(); - /** + /** Creates and returns a new instance of the component that the ValueTree represents. + The caller is responsible for using and deleting the object that is returned. Unlike + getManagedComponent(), the component that is returned will not be updated by the builder. */ - Component* getAndReleaseComponent(); + Component* createComponent(); //============================================================================== /** + The class is a base class for objects that manage the loading of a type of component + from a ValueTree. + + To store and re-load a tree of components as a ValueTree, each component type must have + a TypeHandler to represent it. + + @see ComponentBuilder::registerTypeHandler(), Drawable::registerDrawableTypeHandlers() */ class JUCE_API TypeHandler { public: - /** + //============================================================================== + /** Creates a TypeHandler. + The valueTreeType must be the type name of the ValueTrees that this handler can parse. */ explicit TypeHandler (const Identifier& valueTreeType); /** Destructor. */ virtual ~TypeHandler(); - /** - */ + /** Returns the type of the ValueTrees that this handler can parse. */ const Identifier& getType() const throw() { return valueTreeType; } - /** + /** Returns the builder that this type is registered with. */ + ComponentBuilder* getBuilder() const throw(); + + //============================================================================== + /** This method must create a new component from the given state, add it to the specified + parent component (which may be null), and return it. + + The ValueTree will have been pre-checked to make sure that its type matches the type + that this handler supports. + + There's no need to set the new Component's ID to match that of the state - the builder + will take care of that itself. */ virtual Component* addNewComponentFromState (const ValueTree& state, Component* parent) = 0; - /** - */ - virtual void updateComponentFromState (Component* component, const ValueTree& state) = 0; + /** This method must update an existing component from a new ValueTree state. - /** + A component that has been created with addNewComponentFromState() may need to be updated + if the ValueTree changes, so this method is used to do that. Your implementation must do + whatever's necessary to update the component from the new state provided. + + The ValueTree will have been pre-checked to make sure that its type matches the type + that this handler supports, and the component will have been created by this type's + addNewComponentFromState() method. */ - ComponentBuilder* getBuilder() const throw(); + virtual void updateComponentFromState (Component* component, const ValueTree& state) = 0; private: + //============================================================================== friend class ComponentBuilder; ComponentBuilder* builder; const Identifier valueTreeType; @@ -110,26 +150,37 @@ public: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TypeHandler); }; - /** + //============================================================================== + /** Adds a type handler that the builder can use when trying to load components. + @see Drawable::registerDrawableTypeHandlers() */ void registerTypeHandler (TypeHandler* type); - /** - */ + /** Tries to find a registered type handler that can load a component from the given ValueTree. */ TypeHandler* getHandlerForState (const ValueTree& state) const; - /** + /** Returns the number of registered type handlers. + @see getHandler, registerTypeHandler */ int getNumHandlers() const throw(); - /** + /** Returns one of the registered type handlers. + @see getNumHandlers, registerTypeHandler */ TypeHandler* getHandler (int index) const throw(); //============================================================================= - /** This class is used when loading Drawables that contain images, and retrieves - the image for a stored identifier. - @see Drawable::createFromValueTree + /** This class is used when references to images need to be stored in ValueTrees. + + An instance of an ImageProvider provides a mechanism for converting an Image to/from + a reference, which may be a file, URL, ID string, or whatever system is appropriate in + your app. + + When you're loading components from a ValueTree that may need a way of loading images, you + should call ComponentBuilder::setImageProvider() to supply a suitable provider before + trying to load the component. + + @see ComponentBuilder::setImageProvider() */ class JUCE_API ImageProvider { @@ -146,19 +197,35 @@ public: virtual const Image getImageForIdentifier (const var& imageIdentifier) = 0; /** Returns an identifier to be used to refer to a given image. - This is used when converting a drawable into a ValueTree, so if you're - only loading drawables, you can just return a var::null here. + This is used when a reference to an image is stored in a ValueTree. */ virtual const var getIdentifierForImage (const Image& image) = 0; }; - /** */ + //============================================================================== + /** Gives the builder an ImageProvider object that the type handlers can use when + loading images from stored references. + + The object that is passed in is not owned by the builder, so the caller must delete + it when it is no longer needed, but not while the builder may still be using it. To + clear the image provider, just call setImageProvider (0). + */ void setImageProvider (ImageProvider* newImageProvider) throw(); - /** */ + /** Returns the current image provider that this builder is using, or 0 if none has been set. */ ImageProvider* getImageProvider() const throw(); //============================================================================= + /** Updates the children of a parent component by updating them from the children of + a given ValueTree. + */ + void updateChildComponents (Component& parent, const ValueTree& children); + + /** An identifier for the property of the ValueTrees that is used to store a unique ID + for that component. + */ + static const Identifier idProperty; + /** @internal */ void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const Identifier& property); /** @internal */ @@ -166,22 +233,15 @@ public: /** @internal */ void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged); - /** - */ - void updateChildComponents (Component& parent, const ValueTree& children); - - /** - */ - static const Identifier idProperty; - private: //============================================================================= ValueTree state; OwnedArray types; ScopedPointer component; ImageProvider* imageProvider; - - void updateComponent (const ValueTree& state); + #if JUCE_DEBUG + WeakReference componentRef; + #endif JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentBuilder); }; diff --git a/src/gui/components/layout/juce_MarkerList.cpp b/src/gui/components/layout/juce_MarkerList.cpp new file mode 100644 index 0000000000..1cb64c36c3 --- /dev/null +++ b/src/gui/components/layout/juce_MarkerList.cpp @@ -0,0 +1,262 @@ +/* + ============================================================================== + + 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 "../../../core/juce_StandardHeader.h" + +BEGIN_JUCE_NAMESPACE + +#include "juce_MarkerList.h" + + +//============================================================================== +MarkerList::MarkerList() +{ +} + +MarkerList::MarkerList (const MarkerList& other) +{ + operator= (other); +} + +MarkerList& MarkerList::operator= (const MarkerList& other) +{ + if (other != *this) + { + markers.clear(); + markers.addCopiesOf (other.markers); + markersHaveChanged(); + } + + return *this; +} + +MarkerList::~MarkerList() +{ +} + +bool MarkerList::operator== (const MarkerList& other) const throw() +{ + if (other.markers.size() != markers.size()) + return false; + + for (int i = markers.size(); --i >= 0;) + { + const Marker* const m1 = markers.getUnchecked(i); + jassert (m1 != 0); + + const Marker* const m2 = other.getMarker (m1->name); + + if (m2 == 0 || *m1 != *m2) + return false; + } + + return true; +} + +bool MarkerList::operator!= (const MarkerList& other) const throw() +{ + return ! operator== (other); +} + +//============================================================================== +int MarkerList::getNumMarkers() const throw() +{ + return markers.size(); +} + +const MarkerList::Marker* MarkerList::getMarker (const int index) const throw() +{ + return markers [index]; +} + +const MarkerList::Marker* MarkerList::getMarker (const String& name) const throw() +{ + for (int i = 0; i < markers.size(); ++i) + { + const Marker* const m = markers.getUnchecked(i); + + if (m->name == name) + return m; + } + + return 0; +} + +void MarkerList::setMarker (const String& name, const RelativeCoordinate& position) +{ + Marker* const m = const_cast (getMarker (name)); + + if (m != 0) + { + if (m->position != position) + { + m->position = position; + markersHaveChanged(); + } + + return; + } + + markers.add (new Marker (name, position)); + markersHaveChanged(); +} + +void MarkerList::removeMarker (const int index) +{ + if (isPositiveAndBelow (index, markers.size())) + { + markers.remove (index); + markersHaveChanged(); + } +} + +void MarkerList::removeMarker (const String& name) +{ + for (int i = 0; i < markers.size(); ++i) + { + const Marker* const m = markers.getUnchecked(i); + + if (m->name == name) + { + markers.remove (i); + markersHaveChanged(); + } + } +} + +void MarkerList::markersHaveChanged() +{ + sendChangeMessage(); +} + +//============================================================================== +MarkerList::Marker::Marker (const Marker& other) + : name (other.name), position (other.position) +{ +} + +MarkerList::Marker::Marker (const String& name_, const RelativeCoordinate& position_) + : name (name_), position (position_) +{ +} + +bool MarkerList::Marker::operator== (const Marker& other) const throw() +{ + return name == other.name && position == other.position; +} + +bool MarkerList::Marker::operator!= (const Marker& other) const throw() +{ + return ! operator== (other); +} + +//============================================================================== +const Identifier MarkerList::ValueTreeWrapper::markerTag ("Marker"); +const Identifier MarkerList::ValueTreeWrapper::nameProperty ("name"); +const Identifier MarkerList::ValueTreeWrapper::posProperty ("position"); + +MarkerList::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_) + : state (state_) +{ +} + +int MarkerList::ValueTreeWrapper::getNumMarkers() const +{ + return state.getNumChildren(); +} + +const ValueTree MarkerList::ValueTreeWrapper::getMarkerState (int index) const +{ + return state.getChild (index); +} + +const ValueTree MarkerList::ValueTreeWrapper::getMarkerState (const String& name) const +{ + return state.getChildWithProperty (nameProperty, name); +} + +bool MarkerList::ValueTreeWrapper::containsMarker (const ValueTree& marker) const +{ + return marker.isAChildOf (state); +} + +const MarkerList::Marker MarkerList::ValueTreeWrapper::getMarker (const ValueTree& marker) const +{ + jassert (containsMarker (marker)); + + return MarkerList::Marker (marker [nameProperty], RelativeCoordinate (marker [posProperty].toString())); +} + +void MarkerList::ValueTreeWrapper::setMarker (const MarkerList::Marker& m, UndoManager* undoManager) +{ + ValueTree marker (state.getChildWithProperty (nameProperty, m.name)); + + if (marker.isValid()) + { + marker.setProperty (posProperty, m.position.toString(), undoManager); + } + else + { + marker = ValueTree (markerTag); + marker.setProperty (nameProperty, m.name, 0); + marker.setProperty (posProperty, m.position.toString(), 0); + state.addChild (marker, -1, undoManager); + } +} + +void MarkerList::ValueTreeWrapper::removeMarker (const ValueTree& marker, UndoManager* undoManager) +{ + state.removeChild (marker, undoManager); +} + +void MarkerList::ValueTreeWrapper::applyTo (MarkerList& markerList) +{ + const int numMarkers = getNumMarkers(); + + StringArray updatedMarkers; + + int i; + for (i = 0; i < numMarkers; ++i) + { + const ValueTree marker (state.getChild (i)); + const String name (marker [nameProperty].toString()); + markerList.setMarker (name, RelativeCoordinate (marker [posProperty].toString())); + updatedMarkers.add (name); + } + + for (i = markerList.getNumMarkers(); --i >= 0;) + if (! updatedMarkers.contains (markerList.getMarker (i)->name)) + markerList.removeMarker (i); +} + +void MarkerList::ValueTreeWrapper::readFrom (const MarkerList& markerList, UndoManager* undoManager) +{ + state.removeAllChildren (undoManager); + + for (int i = 0; i < markerList.getNumMarkers(); ++i) + setMarker (*markerList.getMarker(i), undoManager); +} + +END_JUCE_NAMESPACE diff --git a/src/gui/components/layout/juce_MarkerList.h b/src/gui/components/layout/juce_MarkerList.h new file mode 100644 index 0000000000..6082840883 --- /dev/null +++ b/src/gui/components/layout/juce_MarkerList.h @@ -0,0 +1,141 @@ +/* + ============================================================================== + + 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 __JUCE_MARKERLIST_JUCEHEADER__ +#define __JUCE_MARKERLIST_JUCEHEADER__ + +#include "../../../containers/juce_ValueTree.h" +#include "../../graphics/geometry/juce_RelativeCoordinate.h" + + +//============================================================================== +/** + Holds a set of named marker points along a one-dimensional axis. + + This class is used to store sets of X and Y marker points in components. + @see Component::getMarkers(). + + The MarkerList is also a ChangeBroadcaster, so that listeners can register to receive + a callback when a marker is moved, +*/ +class JUCE_API MarkerList : public ChangeBroadcaster +{ +public: + //============================================================================== + /** Creates an empty marker list. */ + MarkerList(); + /** Creates a copy of another marker list. */ + MarkerList (const MarkerList& other); + /** Copies another marker list to this one. */ + MarkerList& operator= (const MarkerList& other); + /** Destructor. */ + ~MarkerList(); + + //============================================================================== + /** Represents a marker in a MarkerList. */ + class JUCE_API Marker + { + public: + /** Creates a copy of another Marker. */ + Marker (const Marker& other); + /** Creates a Marker with a given name and position. */ + Marker (const String& name, const RelativeCoordinate& position); + + /** The marker's name. */ + String name; + + /** The marker's position. */ + RelativeCoordinate position; + + /** Returns true if both the names and positions of these two markers match. */ + bool operator== (const Marker&) const throw(); + /** Returns true if either the name or position of these two markers differ. */ + bool operator!= (const Marker&) const throw(); + }; + + //============================================================================== + /** Returns the number of markers in the list. */ + int getNumMarkers() const throw(); + + /** Returns one of the markers in the list, by its index. */ + const Marker* getMarker (int index) const throw(); + + /** Returns a named marker, or 0 if no such name is found. + Note that name comparisons are case-sensitive. + */ + const Marker* getMarker (const String& name) const throw(); + + /** Sets the position of a marker. + + If the name already exists, then the existing marker is moved; if it doesn't exist, then a + new marker is added. + */ + void setMarker (const String& name, const RelativeCoordinate& position); + + /** Deletes the marker at the given list index. */ + void removeMarker (int index); + + /** Deletes the marker with the given name. */ + void removeMarker (const String& name); + + /** Returns true if all the markers in these two lists match exactly. */ + bool operator== (const MarkerList& other) const throw(); + /** Returns true if not all the markers in these two lists match exactly. */ + bool operator!= (const MarkerList& other) const throw(); + + //============================================================================== + /** Forms a wrapper around a ValueTree that can be used for storing a MarkerList. */ + class ValueTreeWrapper + { + public: + ValueTreeWrapper (const ValueTree& state); + + int getNumMarkers() const; + const ValueTree getMarkerState (int index) const; + const ValueTree getMarkerState (const String& name) const; + bool containsMarker (const ValueTree& state) const; + const MarkerList::Marker getMarker (const ValueTree& state) const; + void setMarker (const MarkerList::Marker& marker, UndoManager* undoManager); + void removeMarker (const ValueTree& state, UndoManager* undoManager); + + void applyTo (MarkerList& markerList); + void readFrom (const MarkerList& markerList, UndoManager* undoManager); + + private: + ValueTree state; + + static const Identifier markerTag, nameProperty, posProperty; + }; + +private: + //============================================================================== + OwnedArray markers; + void markersHaveChanged(); + + JUCE_LEAK_DETECTOR (MarkerList); +}; + + +#endif // __JUCE_MARKERLIST_JUCEHEADER__ diff --git a/src/gui/graphics/drawables/juce_Drawable.cpp b/src/gui/graphics/drawables/juce_Drawable.cpp index c5b5f8fbbb..b6d573978e 100644 --- a/src/gui/graphics/drawables/juce_Drawable.cpp +++ b/src/gui/graphics/drawables/juce_Drawable.cpp @@ -95,10 +95,6 @@ void Drawable::transformContextToCorrectOrigin (Graphics& g) originRelativeToComponent.getY()); } -void Drawable::markerHasMoved() -{ -} - void Drawable::parentHierarchyChanged() { setBoundsToEnclose (getDrawableBounds()); @@ -175,21 +171,6 @@ Drawable* Drawable::createFromImageFile (const File& file) return fin != 0 ? createFromImageDataStream (*fin) : 0; } -//============================================================================== -Drawable* Drawable::createFromValueTree (const ValueTree& tree, ComponentBuilder::ImageProvider* imageProvider) -{ - ComponentBuilder builder (tree); - builder.setImageProvider (imageProvider); - registerDrawableTypes (builder); - - Drawable* d = dynamic_cast (builder.getComponent()); - - if (d != 0) - return dynamic_cast (builder.getAndReleaseComponent()); - - return 0; -} - //============================================================================== template class DrawableTypeHandler : public ComponentBuilder::TypeHandler @@ -219,7 +200,7 @@ public: } }; -void Drawable::registerDrawableTypes (ComponentBuilder& builder) +void Drawable::registerDrawableTypeHandlers (ComponentBuilder& builder) { builder.registerTypeHandler (new DrawableTypeHandler ()); builder.registerTypeHandler (new DrawableTypeHandler ()); @@ -228,13 +209,24 @@ void Drawable::registerDrawableTypes (ComponentBuilder& builder) builder.registerTypeHandler (new DrawableTypeHandler ()); } -//============================================================================== -Drawable::ValueTreeWrapperBase::ValueTreeWrapperBase (const ValueTree& state_) - : state (state_) +Drawable* Drawable::createFromValueTree (const ValueTree& tree, ComponentBuilder::ImageProvider* imageProvider) { + ComponentBuilder builder (tree); + builder.setImageProvider (imageProvider); + registerDrawableTypeHandlers (builder); + + ScopedPointer comp (builder.createComponent()); + Drawable* const d = dynamic_cast (static_cast (comp)); + + if (d != 0) + comp.release(); + + return d; } -Drawable::ValueTreeWrapperBase::~ValueTreeWrapperBase() +//============================================================================== +Drawable::ValueTreeWrapperBase::ValueTreeWrapperBase (const ValueTree& state_) + : state (state_) { } diff --git a/src/gui/graphics/drawables/juce_Drawable.h b/src/gui/graphics/drawables/juce_Drawable.h index fb816fd03a..ada330f38a 100644 --- a/src/gui/graphics/drawables/juce_Drawable.h +++ b/src/gui/graphics/drawables/juce_Drawable.h @@ -28,7 +28,6 @@ #include "../../components/juce_Component.h" #include "../geometry/juce_RelativeCoordinate.h" -#include "../../../text/juce_XmlElement.h" #include "../../../containers/juce_ValueTree.h" #include "../../components/layout/juce_ComponentBuilder.h" class DrawableComposite; @@ -163,6 +162,7 @@ public: If there are any images used within the drawable, you'll need to provide a valid ImageProvider object that can be used to retrieve these images from whatever type of identifier is used to represent them. + Internally, this uses a ComponentBuilder, and registerDrawableTypeHandlers(). */ static Drawable* createFromValueTree (const ValueTree& tree, ComponentBuilder::ImageProvider* imageProvider); @@ -185,7 +185,6 @@ public: { public: ValueTreeWrapperBase (const ValueTree& state); - ~ValueTreeWrapperBase(); ValueTree& getState() throw() { return state; } @@ -195,7 +194,12 @@ public: ValueTree state; }; - static void registerDrawableTypes (ComponentBuilder& componentBuilder); + //============================================================================== + /** Registers a set of ComponentBuilder::TypeHandler objects that can be used to + load all the different Drawable types from a saved state. + @see ComponentBuilder::registerTypeHandler() + */ + static void registerDrawableTypeHandlers (ComponentBuilder& componentBuilder); protected: //============================================================================== @@ -205,8 +209,6 @@ protected: /** @internal */ void transformContextToCorrectOrigin (Graphics& g); /** @internal */ - void markerHasMoved(); - /** @internal */ void parentHierarchyChanged(); /** @internal */ void setBoundsToEnclose (const Rectangle& area); diff --git a/src/gui/graphics/drawables/juce_DrawableComposite.cpp b/src/gui/graphics/drawables/juce_DrawableComposite.cpp index eccd7978cf..ec07e85cfb 100644 --- a/src/gui/graphics/drawables/juce_DrawableComposite.cpp +++ b/src/gui/graphics/drawables/juce_DrawableComposite.cpp @@ -43,6 +43,8 @@ DrawableComposite::DrawableComposite() DrawableComposite::DrawableComposite (const DrawableComposite& other) : bounds (other.bounds), + markersX (other.markersX), + markersY (other.markersY), updateBoundsReentrant (false) { for (int i = 0; i < other.getNumChildComponents(); ++i) @@ -52,9 +54,6 @@ DrawableComposite::DrawableComposite (const DrawableComposite& other) if (d != 0) addAndMakeVisible (d->createCopy()); } - - markersX.addCopiesOf (other.markersX); - markersY.addCopiesOf (other.markersY); } DrawableComposite::~DrawableComposite() @@ -79,32 +78,26 @@ const Rectangle DrawableComposite::getDrawableBounds() const return r; } -void DrawableComposite::markerHasMoved() +MarkerList* DrawableComposite::getMarkers (bool xAxis) { - for (int i = getNumChildComponents(); --i >= 0;) - { - Drawable* const d = dynamic_cast (getChildComponent(i)); - - if (d != 0) - d->markerHasMoved(); - } + return xAxis ? &markersX : &markersY; } const RelativeRectangle DrawableComposite::getContentArea() const { - jassert (markersX.size() >= 2 && getMarker (true, 0)->name == contentLeftMarkerName && getMarker (true, 1)->name == contentRightMarkerName); - jassert (markersY.size() >= 2 && getMarker (false, 0)->name == contentTopMarkerName && getMarker (false, 1)->name == contentBottomMarkerName); + jassert (markersX.getNumMarkers() >= 2 && markersX.getMarker (0)->name == contentLeftMarkerName && markersX.getMarker (1)->name == contentRightMarkerName); + jassert (markersY.getNumMarkers() >= 2 && markersY.getMarker (0)->name == contentTopMarkerName && markersY.getMarker (1)->name == contentBottomMarkerName); - return RelativeRectangle (markersX.getUnchecked(0)->position, markersX.getUnchecked(1)->position, - markersY.getUnchecked(0)->position, markersY.getUnchecked(1)->position); + return RelativeRectangle (markersX.getMarker(0)->position, markersX.getMarker(1)->position, + markersY.getMarker(0)->position, markersY.getMarker(1)->position); } void DrawableComposite::setContentArea (const RelativeRectangle& newArea) { - setMarker (contentLeftMarkerName, true, newArea.left); - setMarker (contentRightMarkerName, true, newArea.right); - setMarker (contentTopMarkerName, false, newArea.top); - setMarker (contentBottomMarkerName, false, newArea.bottom); + markersX.setMarker (contentLeftMarkerName, newArea.left); + markersX.setMarker (contentRightMarkerName, newArea.right); + markersY.setMarker (contentTopMarkerName, newArea.top); + markersY.setMarker (contentBottomMarkerName, newArea.bottom); refreshTransformFromBounds(); } @@ -219,81 +212,18 @@ const char* const DrawableComposite::contentRightMarkerName = "right"; const char* const DrawableComposite::contentTopMarkerName = "top"; const char* const DrawableComposite::contentBottomMarkerName = "bottom"; -DrawableComposite::Marker::Marker (const DrawableComposite::Marker& other) - : name (other.name), position (other.position) -{ -} - -DrawableComposite::Marker::Marker (const String& name_, const RelativeCoordinate& position_) - : name (name_), position (position_) -{ -} - -bool DrawableComposite::Marker::operator!= (const DrawableComposite::Marker& other) const throw() -{ - return name != other.name || position != other.position; -} - -int DrawableComposite::getNumMarkers (const bool xAxis) const throw() -{ - return (xAxis ? markersX : markersY).size(); -} - -const DrawableComposite::Marker* DrawableComposite::getMarker (const bool xAxis, const int index) const throw() -{ - return (xAxis ? markersX : markersY) [index]; -} - -void DrawableComposite::setMarker (const String& name, const bool xAxis, const RelativeCoordinate& position) -{ - OwnedArray & markers = (xAxis ? markersX : markersY); - - for (int i = 0; i < markers.size(); ++i) - { - Marker* const m = markers.getUnchecked(i); - if (m->name == name) - { - if (m->position != position) - { - m->position = position; - markerHasMoved(); - } - - return; - } - } - - (xAxis ? markersX : markersY).add (new Marker (name, position)); - markerHasMoved(); -} - -void DrawableComposite::removeMarker (const bool xAxis, const int index) -{ - jassert (index >= 2); - - if (index >= 2) - (xAxis ? markersX : markersY).remove (index); -} - //============================================================================== const Expression DrawableComposite::getSymbolValue (const String& symbol, const String& member) const { jassert (member.isEmpty()) // the only symbols available in a Drawable are markers. - int i; - for (i = 0; i < markersX.size(); ++i) - { - Marker* const m = markersX.getUnchecked(i); - if (m->name == symbol) - return m->position.getExpression(); - } + const MarkerList::Marker* m = markersX.getMarker (symbol); - for (i = 0; i < markersY.size(); ++i) - { - Marker* const m = markersY.getUnchecked(i); - if (m->name == symbol) - return m->position.getExpression(); - } + if (m == 0) + m = markersY.getMarker (symbol); + + if (m != 0) + return m->position.getExpression(); throw Expression::EvaluationError (symbol, member); } @@ -312,9 +242,6 @@ const Identifier DrawableComposite::ValueTreeWrapper::bottomLeft ("bottomLeft"); const Identifier DrawableComposite::ValueTreeWrapper::childGroupTag ("Drawables"); const Identifier DrawableComposite::ValueTreeWrapper::markerGroupTagX ("MarkersX"); const Identifier DrawableComposite::ValueTreeWrapper::markerGroupTagY ("MarkersY"); -const Identifier DrawableComposite::ValueTreeWrapper::markerTag ("Marker"); -const Identifier DrawableComposite::ValueTreeWrapper::nameProperty ("name"); -const Identifier DrawableComposite::ValueTreeWrapper::posProperty ("position"); //============================================================================== DrawableComposite::ValueTreeWrapper::ValueTreeWrapper (const ValueTree& state_) @@ -358,85 +285,36 @@ void DrawableComposite::ValueTreeWrapper::resetBoundingBoxToContentArea (UndoMan const RelativeRectangle DrawableComposite::ValueTreeWrapper::getContentArea() const { - return RelativeRectangle (getMarker (true, getMarkerState (true, 0)).position, - getMarker (true, getMarkerState (true, 1)).position, - getMarker (false, getMarkerState (false, 0)).position, - getMarker (false, getMarkerState (false, 1)).position); + MarkerList::ValueTreeWrapper markersX (getMarkerList (true)); + MarkerList::ValueTreeWrapper markersY (getMarkerList (false)); + + return RelativeRectangle (markersX.getMarker (markersX.getMarkerState (0)).position, + markersX.getMarker (markersX.getMarkerState (1)).position, + markersY.getMarker (markersY.getMarkerState (0)).position, + markersY.getMarker (markersY.getMarkerState (1)).position); } void DrawableComposite::ValueTreeWrapper::setContentArea (const RelativeRectangle& newArea, UndoManager* undoManager) { - setMarker (true, Marker (contentLeftMarkerName, newArea.left), undoManager); - setMarker (true, Marker (contentRightMarkerName, newArea.right), undoManager); - setMarker (false, Marker (contentTopMarkerName, newArea.top), undoManager); - setMarker (false, Marker (contentBottomMarkerName, newArea.bottom), undoManager); + MarkerList::ValueTreeWrapper markersX (getMarkerListCreating (true, 0)); + MarkerList::ValueTreeWrapper markersY (getMarkerListCreating (false, 0)); + + markersX.setMarker (MarkerList::Marker (contentLeftMarkerName, newArea.left), undoManager); + markersX.setMarker (MarkerList::Marker (contentRightMarkerName, newArea.right), undoManager); + markersY.setMarker (MarkerList::Marker (contentTopMarkerName, newArea.top), undoManager); + markersY.setMarker (MarkerList::Marker (contentBottomMarkerName, newArea.bottom), undoManager); } -ValueTree DrawableComposite::ValueTreeWrapper::getMarkerList (bool xAxis) const +MarkerList::ValueTreeWrapper DrawableComposite::ValueTreeWrapper::getMarkerList (bool xAxis) const { return state.getChildWithName (xAxis ? markerGroupTagX : markerGroupTagY); } -ValueTree DrawableComposite::ValueTreeWrapper::getMarkerListCreating (bool xAxis, UndoManager* undoManager) +MarkerList::ValueTreeWrapper DrawableComposite::ValueTreeWrapper::getMarkerListCreating (bool xAxis, UndoManager* undoManager) { return state.getOrCreateChildWithName (xAxis ? markerGroupTagX : markerGroupTagY, undoManager); } -int DrawableComposite::ValueTreeWrapper::getNumMarkers (bool xAxis) const -{ - return getMarkerList (xAxis).getNumChildren(); -} - -const ValueTree DrawableComposite::ValueTreeWrapper::getMarkerState (bool xAxis, int index) const -{ - return getMarkerList (xAxis).getChild (index); -} - -const ValueTree DrawableComposite::ValueTreeWrapper::getMarkerState (bool xAxis, const String& name) const -{ - return getMarkerList (xAxis).getChildWithProperty (nameProperty, name); -} - -bool DrawableComposite::ValueTreeWrapper::containsMarker (bool xAxis, const ValueTree& state) const -{ - return state.isAChildOf (getMarkerList (xAxis)); -} - -const DrawableComposite::Marker DrawableComposite::ValueTreeWrapper::getMarker (bool xAxis, const ValueTree& state) const -{ - (void) xAxis; - jassert (containsMarker (xAxis, state)); - - return Marker (state [nameProperty], RelativeCoordinate (state [posProperty].toString())); -} - -void DrawableComposite::ValueTreeWrapper::setMarker (bool xAxis, const Marker& m, UndoManager* undoManager) -{ - ValueTree markerList (getMarkerListCreating (xAxis, undoManager)); - ValueTree marker (markerList.getChildWithProperty (nameProperty, m.name)); - - if (marker.isValid()) - { - marker.setProperty (posProperty, m.position.toString(), undoManager); - } - else - { - marker = ValueTree (markerTag); - marker.setProperty (nameProperty, m.name, 0); - marker.setProperty (posProperty, m.position.toString(), 0); - markerList.addChild (marker, -1, undoManager); - } -} - -void DrawableComposite::ValueTreeWrapper::removeMarker (bool xAxis, const ValueTree& state, UndoManager* undoManager) -{ - if (state [nameProperty].toString() != contentLeftMarkerName - && state [nameProperty].toString() != contentRightMarkerName - && state [nameProperty].toString() != contentTopMarkerName - && state [nameProperty].toString() != contentBottomMarkerName) - getMarkerList (xAxis).removeChild (state, undoManager); -} - //============================================================================== void DrawableComposite::refreshFromValueTree (const ValueTree& tree, ComponentBuilder& builder) { @@ -447,39 +325,8 @@ void DrawableComposite::refreshFromValueTree (const ValueTree& tree, ComponentBu if (bounds != newBounds) bounds = newBounds; - const int numMarkersX = wrapper.getNumMarkers (true); - const int numMarkersY = wrapper.getNumMarkers (false); - - // Remove deleted markers... - if (markersX.size() > numMarkersX || markersY.size() > numMarkersY) - { - markersX.removeRange (jmax (2, numMarkersX), markersX.size()); - markersY.removeRange (jmax (2, numMarkersY), markersY.size()); - } - - // Update markers and add new ones.. - int i; - for (i = 0; i < numMarkersX; ++i) - { - const Marker newMarker (wrapper.getMarker (true, wrapper.getMarkerState (true, i))); - Marker* m = markersX[i]; - - if (m == 0) - markersX.add (new Marker (newMarker)); - else if (newMarker != *m) - *m = newMarker; - } - - for (i = 0; i < numMarkersY; ++i) - { - const Marker newMarker (wrapper.getMarker (false, wrapper.getMarkerState (false, i))); - Marker* m = markersY[i]; - - if (m == 0) - markersY.add (new Marker (newMarker)); - else if (newMarker != *m) - *m = newMarker; - } + wrapper.getMarkerList (true).applyTo (markersX); + wrapper.getMarkerList (false).applyTo (markersY); builder.updateChildComponents (*this, wrapper.getChildList()); @@ -496,18 +343,16 @@ const ValueTree DrawableComposite::createValueTree (ComponentBuilder::ImageProvi ValueTree childList (v.getChildListCreating (0)); - int i; - for (i = getNumChildComponents(); --i >= 0;) + for (int i = getNumChildComponents(); --i >= 0;) { const Drawable* const d = dynamic_cast (getChildComponent(i)); + jassert (d != 0); // You can't save a mix of Drawables and normal components! + childList.addChild (d->createValueTree (imageProvider), -1, 0); } - for (i = 0; i < markersX.size(); ++i) - v.setMarker (true, *markersX.getUnchecked(i), 0); - - for (i = 0; i < markersY.size(); ++i) - v.setMarker (false, *markersY.getUnchecked(i), 0); + v.getMarkerListCreating (true, 0).readFrom (markersX, 0); + v.getMarkerListCreating (false, 0).readFrom (markersY, 0); return tree; } diff --git a/src/gui/graphics/drawables/juce_DrawableComposite.h b/src/gui/graphics/drawables/juce_DrawableComposite.h index 62dcccbfae..bc3efd2148 100644 --- a/src/gui/graphics/drawables/juce_DrawableComposite.h +++ b/src/gui/graphics/drawables/juce_DrawableComposite.h @@ -27,6 +27,7 @@ #define __JUCE_DRAWABLECOMPOSITE_JUCEHEADER__ #include "juce_Drawable.h" +#include "../../components/layout/juce_MarkerList.h" //============================================================================== @@ -85,24 +86,6 @@ public: void resetContentAreaAndBoundingBoxToFitChildren(); //============================================================================== - /** Represents a named marker position. - @see DrawableComposite::getMarker - */ - struct Marker - { - Marker (const Marker&); - Marker (const String& name, const RelativeCoordinate& position); - bool operator!= (const Marker&) const throw(); - - String name; - RelativeCoordinate position; - }; - - int getNumMarkers (bool xAxis) const throw(); - const Marker* getMarker (bool xAxis, int index) const throw(); - void setMarker (const String& name, bool xAxis, const RelativeCoordinate& position); - void removeMarker (bool xAxis, int index); - /** The name of the marker that defines the left edge of the content area. */ static const char* const contentLeftMarkerName; /** The name of the marker that defines the right edge of the content area. */ @@ -126,13 +109,13 @@ public: /** @internal */ const Rectangle getDrawableBounds() const; /** @internal */ - void markerHasMoved(); - /** @internal */ void childBoundsChanged (Component*); /** @internal */ void childrenChanged(); /** @internal */ void parentHierarchyChanged(); + /** @internal */ + MarkerList* getMarkers (bool xAxis); //============================================================================== /** Internally-used class for wrapping a DrawableComposite's state into a ValueTree. */ @@ -151,27 +134,19 @@ public: const RelativeRectangle getContentArea() const; void setContentArea (const RelativeRectangle& newArea, UndoManager* undoManager); - int getNumMarkers (bool xAxis) const; - const ValueTree getMarkerState (bool xAxis, int index) const; - const ValueTree getMarkerState (bool xAxis, const String& name) const; - bool containsMarker (bool xAxis, const ValueTree& state) const; - const Marker getMarker (bool xAxis, const ValueTree& state) const; - void setMarker (bool xAxis, const Marker& marker, UndoManager* undoManager); - void removeMarker (bool xAxis, const ValueTree& state, UndoManager* undoManager); + MarkerList::ValueTreeWrapper getMarkerList (bool xAxis) const; + MarkerList::ValueTreeWrapper getMarkerListCreating (bool xAxis, UndoManager* undoManager); - static const Identifier nameProperty, posProperty, topLeft, topRight, bottomLeft; + static const Identifier topLeft, topRight, bottomLeft; private: - static const Identifier childGroupTag, markerGroupTagX, markerGroupTagY, markerTag; - - ValueTree getMarkerList (bool xAxis) const; - ValueTree getMarkerListCreating (bool xAxis, UndoManager* undoManager); + static const Identifier childGroupTag, markerGroupTagX, markerGroupTagY; }; private: //============================================================================== RelativeParallelogram bounds; - OwnedArray markersX, markersY; + MarkerList markersX, markersY; bool updateBoundsReentrant; void refreshTransformFromBounds(); diff --git a/src/juce_app_includes.h b/src/juce_app_includes.h index 5381a0caa8..89f0b7362b 100644 --- a/src/juce_app_includes.h +++ b/src/juce_app_includes.h @@ -437,6 +437,9 @@ #ifndef __JUCE_GROUPCOMPONENT_JUCEHEADER__ #include "gui/components/layout/juce_GroupComponent.h" #endif +#ifndef __JUCE_MARKERLIST_JUCEHEADER__ + #include "gui/components/layout/juce_MarkerList.h" +#endif #ifndef __JUCE_MULTIDOCUMENTPANEL_JUCEHEADER__ #include "gui/components/layout/juce_MultiDocumentPanel.h" #endif diff --git a/src/native/mac/juce_mac_NativeIncludes.h b/src/native/mac/juce_mac_NativeIncludes.h index 215e20c829..e20982f859 100644 --- a/src/native/mac/juce_mac_NativeIncludes.h +++ b/src/native/mac/juce_mac_NativeIncludes.h @@ -65,8 +65,8 @@ #import #import #endif - #if JUCE_BUILD_MISC && (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_AU) \ - && ! (defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) + #if (JUCE_BUILD_MISC && (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_AU)) \ + || ! (defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) #include #endif #include diff --git a/src/native/windows/juce_win32_Windowing.cpp b/src/native/windows/juce_win32_Windowing.cpp index 3f743e9331..d6f60c7b09 100644 --- a/src/native/windows/juce_win32_Windowing.cpp +++ b/src/native/windows/juce_win32_Windowing.cpp @@ -2003,11 +2003,10 @@ private: return 0; case WM_NCPAINT: - if (wParam != 1) - handlePaintMessage(); - if (hasTitleBar()) break; + else if (wParam != 1) + handlePaintMessage(); return 0;