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* createComponent();
/**
- */
- Component* getAndReleaseComponent();
+ 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;
- /**
+ /** 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.
*/
virtual void updateComponentFromState (Component* component, const ValueTree& state) = 0;
- /**
- */
- ComponentBuilder* getBuilder() const throw();
-
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!
+ 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)
@@ -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; }
- /**
- */
- Component* getComponent();
+ /** 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* getAndReleaseComponent();
+ 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* 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;
- /**
+ /** 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.
*/
virtual void updateComponentFromState (Component* component, const ValueTree& state) = 0;
- /**
- */
- ComponentBuilder* getBuilder() const throw();
-
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,16 +209,27 @@ void Drawable::registerDrawableTypes (ComponentBuilder& builder)
builder.registerTypeHandler (new DrawableTypeHandler ());
}
+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 (const ValueTree& state_)
: state (state_)
{
}
-Drawable::ValueTreeWrapperBase::~ValueTreeWrapperBase()
-{
-}
-
const String Drawable::ValueTreeWrapperBase::getID() const
{
return state [ComponentBuilder::idProperty];
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;