diff --git a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp index 325382c06e..c990a265bf 100644 --- a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp +++ b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp @@ -27,13 +27,146 @@ //============================================================================== -static const char* const componentDocumentTag = "COMPONENT"; +static const char* const componentDocumentTag = "COMPONENT"; +static const char* const componentGroupTag = "COMPONENTS"; + +static const char* const idProperty = "id"; +static const char* const compBoundsProperty = "position"; + +//============================================================================== +static const String componentBoundsToString (const Rectangle& bounds) +{ + return bounds.toString(); +} + +static const Rectangle stringToComponentBounds (const String& s) +{ + return Rectangle::fromString (s); +} + +//============================================================================== +class ComponentTypeHandler +{ +public: + //============================================================================== + ComponentTypeHandler (const String& name_, const String& tag_) + : name (name_), tag (tag_) + { + } + + virtual ~ComponentTypeHandler() + { + } + + const String& getName() const { return name; } + const String& getTag() const { return tag; } + + virtual Component* createComponent() = 0; + virtual const Rectangle getDefaultSize() = 0; + + virtual void updateComponent (Component* comp, const ValueTree& state) + { + comp->setBounds (stringToComponentBounds (state [compBoundsProperty])); + } + + virtual const ValueTree createNewItem() + { + ValueTree v (tag); + v.setProperty (idProperty, createAlphaNumericUID(), 0); + v.setProperty (compBoundsProperty, + componentBoundsToString (getDefaultSize().withPosition (Point (Random::getSystemRandom().nextInt (100) + 100, + Random::getSystemRandom().nextInt (100) + 100))), 0); + return v; + } + + //============================================================================== +protected: + const String name, tag; +}; + +//============================================================================== +class TextButtonHandler : public ComponentTypeHandler +{ +public: + TextButtonHandler() : ComponentTypeHandler ("TextButton", "TEXTBUTTON") {} + ~TextButtonHandler() {} + + Component* createComponent() { return new TextButton (String::empty); } + const Rectangle getDefaultSize() { return Rectangle (0, 0, 150, 24); } + + void updateComponent (Component* comp, const ValueTree& state) + { + ComponentTypeHandler::updateComponent (comp, state); + } + + const ValueTree createNewItem() + { + ValueTree v (ComponentTypeHandler::createNewItem()); + return v; + } +}; + +//============================================================================== +class ComponentTypeManager : public DeletedAtShutdown +{ +public: + ComponentTypeManager() + { + handlers.add (new TextButtonHandler()); + } + + ~ComponentTypeManager() + { + } + + juce_DeclareSingleton_SingleThreaded_Minimal (ComponentTypeManager); + + Component* createFromStoredType (const ValueTree& value) + { + ComponentTypeHandler* handler = getHandlerFor (value.getType()); + if (handler == 0) + return 0; + + Component* c = handler->createComponent(); + if (c != 0) + handler->updateComponent (c, value); + + return c; + } + + ComponentTypeHandler* getHandlerFor (const String& type) + { + for (int i = handlers.size(); --i >= 0;) + if (handlers.getUnchecked(i)->getTag() == type) + return handlers.getUnchecked(i); + + return 0; + } + + const StringArray getTypeNames() const + { + StringArray s; + for (int i = 0; i < handlers.size(); ++i) + s.add (handlers.getUnchecked(i)->getName()); + + return s; + } + + int getNumHandlers() const { return handlers.size(); } + ComponentTypeHandler* getHandler (const int index) const { return handlers[index]; } + +private: + OwnedArray handlers; +}; + +juce_ImplementSingleton_SingleThreaded (ComponentTypeManager); //============================================================================== ComponentDocument::ComponentDocument (Project* project_, const File& cppFile_) : project (project_), cppFile (cppFile_), root (componentDocumentTag) { + checkRootObject(); } ComponentDocument::~ComponentDocument() @@ -61,5 +194,201 @@ bool ComponentDocument::isComponentFile (const File& file) bool ComponentDocument::save() { + + //XXX + return false; +} + +bool ComponentDocument::reload() +{ + + //XXX + return true; +} + +bool ComponentDocument::hasChangedSinceLastSave() +{ + + //XXX + return false; +} + +void ComponentDocument::checkRootObject() +{ + jassert (root.hasType (componentDocumentTag)); + + if (! getComponentGroup().isValid()) + root.addChild (ValueTree (componentGroupTag), -1, 0); +} + +//============================================================================== +const int menuItemOffset = 0x63451fa4; + +void ComponentDocument::addNewComponentMenuItems (PopupMenu& menu) const +{ + const StringArray typeNames (ComponentTypeManager::getInstance()->getTypeNames()); + + for (int i = 0; i < typeNames.size(); ++i) + menu.addItem (i + menuItemOffset, "New " + typeNames[i]); +} + +void ComponentDocument::performNewComponentMenuItem (int menuResultCode) +{ + const StringArray typeNames (ComponentTypeManager::getInstance()->getTypeNames()); + + if (menuResultCode >= menuItemOffset && menuResultCode < menuItemOffset + typeNames.size()) + { + ComponentTypeHandler* handler = ComponentTypeManager::getInstance()->getHandler (menuResultCode - menuItemOffset); + jassert (handler != 0); + + if (handler != 0) + getComponentGroup().addChild (handler->createNewItem(), -1, getUndoManager()); + } +} + +//============================================================================== +ValueTree ComponentDocument::getComponentGroup() const +{ + return root.getChildWithName (componentGroupTag); +} + +int ComponentDocument::getNumComponents() const +{ + return getComponentGroup().getNumChildren(); +} + +const ValueTree ComponentDocument::getComponent (int index) const +{ + return getComponentGroup().getChild (index); +} + +Component* ComponentDocument::createComponent (int index) const +{ + const ValueTree v (getComponentGroup().getChild (index)); + + if (v.isValid()) + { + Component* c = ComponentTypeManager::getInstance()->createFromStoredType (v); + c->getProperties().set (idProperty, v[idProperty]); + jassert (c->getProperties()[idProperty].toString().isNotEmpty()); + return c; + } + + return 0; +} + +void ComponentDocument::updateComponent (Component* comp) const +{ + const ValueTree v (getComponentState (comp)); + + if (v.isValid()) + { + ComponentTypeHandler* handler = ComponentTypeManager::getInstance()->getHandlerFor (v.getType()); + jassert (handler != 0); + + if (handler != 0) + handler->updateComponent (comp, v); + } +} + +bool ComponentDocument::containsComponent (Component* comp) const +{ + const ValueTree comps (getComponentGroup()); + + for (int i = 0; i < comps.getNumChildren(); ++i) + if (isStateForComponent (comps.getChild(i), comp)) + return true; + return false; } + +const ValueTree ComponentDocument::getComponentState (Component* comp) const +{ + jassert (comp != 0); + const ValueTree comps (getComponentGroup()); + + for (int i = 0; i < comps.getNumChildren(); ++i) + if (isStateForComponent (comps.getChild(i), comp)) + return comps.getChild(i); + + jassertfalse; + return ValueTree::invalid; +} + +bool ComponentDocument::isStateForComponent (const ValueTree& storedState, Component* comp) const +{ + jassert (comp != 0); + jassert (! storedState [idProperty].isVoid()); + return storedState [idProperty] == comp->getProperties() [idProperty]; +} + +//============================================================================== +class ComponentDocument::DragHandler +{ +public: + DragHandler (ComponentDocument& document_, + const Array& items, + const MouseEvent& e, + int zones_) + : document (document_), + zones (zones_) + { + for (int i = 0; i < items.size(); ++i) + { + jassert (items.getUnchecked(i) != 0); + const ValueTree v (document.getComponentState (items.getUnchecked(i))); + draggedComponents.add (v); + originalPositions.add (stringToComponentBounds (v [compBoundsProperty])); + } + } + + ~DragHandler() + { + } + + void drag (const MouseEvent& e) + { + for (int i = 0; i < draggedComponents.size(); ++i) + { + if (zones == 0) + move (draggedComponents.getReference(i), e.getOffsetFromDragStart(), originalPositions.getReference(i)); + else + resize (draggedComponents.getReference(i), e.getOffsetFromDragStart(), originalPositions.getReference(i)); + } + } + + void move (ValueTree& v, const Point& distance, const Rectangle& originalPos) + { + v.setProperty (compBoundsProperty, componentBoundsToString (originalPos + distance), document.getUndoManager()); + } + + void resize (ValueTree& v, const Point& distance, const Rectangle& originalPos) + { + } + +private: + ComponentDocument& document; + Array draggedComponents; + Array > originalPositions; + const int zones; +}; + +void ComponentDocument::beginDrag (const Array& items, const MouseEvent& e, int zones) +{ + dragger = new DragHandler (*this, items, e, zones); +} + +void ComponentDocument::continueDrag (const MouseEvent& e) +{ + if (dragger != 0) + dragger->drag (e); +} + +void ComponentDocument::endDrag (const MouseEvent& e) +{ + if (dragger != 0) + { + dragger->drag (e); + dragger = 0; + } +} diff --git a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h index bec4736d67..a172ccb091 100644 --- a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h +++ b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h @@ -41,8 +41,38 @@ public: static bool isComponentFile (const File& file); bool save(); + bool reload(); + bool hasChangedSinceLastSave(); + + typedef SelectedItemSet SelectedItems; + + //============================================================================== + int getNumComponents() const; + const ValueTree getComponent (int index) const; + Component* createComponent (int index) const; + void updateComponent (Component* comp) const; + bool containsComponent (Component* comp) const; + const ValueTree getComponentState (Component* comp) const; + bool isStateForComponent (const ValueTree& storedState, Component* comp) const; + + void addNewComponentMenuItems (PopupMenu& menu) const; + void performNewComponentMenuItem (int menuResultCode); //============================================================================== + enum ResizeZones + { + zoneL = 1, + zoneR = 2, + zoneT = 4, + zoneB = 8 + }; + + void beginDrag (const Array& items, const MouseEvent& e, int zones); + void continueDrag (const MouseEvent& e); + void endDrag (const MouseEvent& e); + + //============================================================================== + ValueTree& getRoot() { return root; } UndoManager* getUndoManager() throw() { return &undoManager; } private: @@ -50,6 +80,12 @@ private: File cppFile; ValueTree root; UndoManager undoManager; + + class DragHandler; + ScopedPointer dragger; + + void checkRootObject(); + ValueTree getComponentGroup() const; }; diff --git a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp index 9b203d4a85..7a79b73192 100644 --- a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp +++ b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp @@ -27,6 +27,416 @@ #include "jucer_ComponentEditor.h" +//============================================================================== +class ComponentCanvas : public Component, + public ValueTree::Listener +{ +public: + ComponentCanvas (ComponentEditor& editor_) + : editor (editor_) + { + setOpaque (true); + addAndMakeVisible (componentHolder = new Component()); + addAndMakeVisible (overlay = new OverlayComponent (*this)); + + setSize (500, 500); + + getDocument().getRoot().addListener (this); + updateComponents(); + } + + ~ComponentCanvas() + { + getDocument().getRoot().removeListener (this); + deleteAllChildren(); + } + + void paint (Graphics& g) + { + g.fillAll (Colours::white); + } + + void resized() + { + componentHolder->setSize (getWidth(), getHeight()); + overlay->setSize (getWidth(), getHeight()); + } + + void zoom (float newScale, const Point& centre) + { + } + + ComponentEditor& getEditor() { return editor; } + ComponentDocument& getDocument() { return editor.getDocument(); } + ComponentDocument::SelectedItems& getSelection() { return selection; } + + Component* findComponentFor (const ValueTree& state) + { + ComponentDocument& doc = getDocument(); + + for (int i = componentHolder->getNumChildComponents(); --i >= 0;) + { + Component* c = componentHolder->getChildComponent (i); + + if (doc.isStateForComponent (state, c)) + return c; + } + + return 0; + } + + void updateComponents() + { + ComponentDocument& doc = getDocument(); + + int i; + for (i = componentHolder->getNumChildComponents(); --i >= 0;) + { + Component* c = componentHolder->getChildComponent (i); + + if (! doc.containsComponent (c)) + { + selection.deselect (c->getComponentUID()); + delete c; + } + } + + const int num = doc.getNumComponents(); + for (i = 0; i < num; ++i) + { + const ValueTree v (doc.getComponent (i)); + Component* c = findComponentFor (v); + + if (c == 0) + { + c = doc.createComponent (i); + componentHolder->addAndMakeVisible (c); + } + else + { + doc.updateComponent (c); + } + } + } + + void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const var::identifier& property) + { + updateComponents(); + } + + void valueTreeChildrenChanged (ValueTree& treeWhoseChildHasChanged) + { + updateComponents(); + } + + void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) + { + } + + Component* getComponentHolder() const { return componentHolder; } + + const Array getSelectedComps() const + { + Array comps; + for (int i = 0; i < selection.getNumSelected(); ++i) + { + Component* c = getComponentForUID (selection.getSelectedItem (i)); + jassert (c != 0); + if (c != 0) + comps.add (c); + } + + return comps; + } + +private: + ComponentEditor& editor; + + //============================================================================== + class ComponentSelectorFrame : public Component, + public ComponentListener + { + public: + ComponentSelectorFrame (ComponentCanvas& canvas_, + Component* componentToAttachTo) + : canvas (canvas_), + component (componentToAttachTo), + borderThickness (4) + { + componentMovedOrResized (*componentToAttachTo, true, true); + componentToAttachTo->addComponentListener (this); + } + + ~ComponentSelectorFrame() + { + if (component != 0) + component->removeComponentListener (this); + } + + void paint (Graphics& g) + { + g.setColour (Colours::red.withAlpha (0.1f)); + g.drawRect (0, 0, getWidth(), getHeight(), borderThickness); + } + + void mouseEnter (const MouseEvent& e) + { + repaint(); + updateDragZone (e.getPosition()); + } + + void mouseExit (const MouseEvent& e) + { + repaint(); + updateDragZone (e.getPosition()); + } + + void mouseMove (const MouseEvent& e) + { + updateDragZone (e.getPosition()); + } + + void mouseDown (const MouseEvent& e) + { + jassert (component != 0); + + if (component != 0) + { + updateDragZone (e.getPosition()); + canvas.getDocument().beginDrag (canvas.getSelectedComps(), e, dragZone); + } + } + + void mouseDrag (const MouseEvent& e) + { + if (component != 0) + canvas.getDocument().continueDrag (e); + } + + void mouseUp (const MouseEvent& e) + { + if (component != 0) + canvas.getDocument().endDrag (e); + + updateDragZone (e.getPosition()); + } + + void componentMovedOrResized (Component&, bool wasMoved, bool wasResized) + { + if (component != 0) + setBounds (component->getBounds().expanded (borderThickness, borderThickness)); + } + + void resized() + { + } + + uint32 getTargetComponentUID() const { return component == 0 ? 0 : component->getComponentUID(); } + + private: + ComponentCanvas& canvas; + Component::SafePointer component; + int dragZone; + const int borderThickness; + + void updateDragZone (const Point& p) + { + int newZone = 0; + + Rectangle r (0, 0, getWidth(), getHeight()); + r = r.reduced (borderThickness, borderThickness); + + if (! r.contains (p)) + { + const int bw = jmax (borderThickness, proportionOfWidth (0.1f), jmin (10, proportionOfWidth (0.33f))); + const int bh = jmax (borderThickness, proportionOfHeight (0.1f), jmin (10, proportionOfHeight (0.33f))); + + if (p.getX() < bw) + newZone |= ComponentDocument::zoneL; + else if (p.getX() >= getWidth() - bw) + newZone |= ComponentDocument::zoneR; + + if (p.getY() < bh) + newZone |= ComponentDocument::zoneT; + else if (p.getY() >= getHeight() - bh) + newZone |= ComponentDocument::zoneB; + } + + if (dragZone != newZone) + { + dragZone = newZone; + + MouseCursor::StandardCursorType mc = MouseCursor::NormalCursor; + + switch (newZone) + { + case (ComponentDocument::zoneL | ComponentDocument::zoneT): mc = MouseCursor::TopLeftCornerResizeCursor; break; + case ComponentDocument::zoneT: mc = MouseCursor::TopEdgeResizeCursor; break; + case (ComponentDocument::zoneR | ComponentDocument::zoneT): mc = MouseCursor::TopRightCornerResizeCursor; break; + case ComponentDocument::zoneL: mc = MouseCursor::LeftEdgeResizeCursor; break; + case ComponentDocument::zoneR: mc = MouseCursor::RightEdgeResizeCursor; break; + case (ComponentDocument::zoneL | ComponentDocument::zoneB): mc = MouseCursor::BottomLeftCornerResizeCursor; break; + case ComponentDocument::zoneB: mc = MouseCursor::BottomEdgeResizeCursor; break; + case (ComponentDocument::zoneR | ComponentDocument::zoneB): mc = MouseCursor::BottomRightCornerResizeCursor; break; + default: mc = MouseCursor::NormalCursor; break; + } + + setMouseCursor (mc); + } + } + }; + + //============================================================================== + class OverlayComponent : public Component, + public LassoSource , + public ChangeListener + { + public: + OverlayComponent (ComponentCanvas& canvas_) + : canvas (canvas_) + { + setAlwaysOnTop (true); + setWantsKeyboardFocus (true); + canvas.getSelection().addChangeListener (this); + } + + ~OverlayComponent() + { + canvas.getSelection().removeChangeListener (this); + + lasso = 0; + deleteAllChildren(); + } + + void mouseDown (const MouseEvent& e) + { + lasso = 0; + + if (e.mods.isPopupMenu()) + { + PopupMenu m; + canvas.getDocument().addNewComponentMenuItems (m); + + const int r = m.show(); + canvas.getDocument().performNewComponentMenuItem (r); + } + else + { + Component* underMouse = canvas.getComponentHolder()->getComponentAt (e.x, e.y); + + if (underMouse == canvas.getComponentHolder()) + underMouse = 0; + + if (underMouse == 0 || e.mods.isAltDown()) + { + addAndMakeVisible (lasso = new LassoComponent ()); + lasso->beginLasso (e, this); + } + else + { + mouseDownCompUID = underMouse->getComponentUID(); + mouseDownResult = canvas.getSelection().addToSelectionOnMouseDown (mouseDownCompUID, e.mods); + } + } + } + + void mouseDrag (const MouseEvent& e) + { + if (lasso != 0) + lasso->dragLasso (e); + } + + void mouseUp (const MouseEvent& e) + { + if (lasso != 0) + { + lasso->endLasso(); + lasso = 0; + + if (e.mouseWasClicked()) + canvas.getSelection().deselectAll(); + } + else + { + canvas.getSelection().addToSelectionOnMouseUp (mouseDownCompUID, e.mods, ! e.mouseWasClicked(), mouseDownResult); + } + } + + void findLassoItemsInArea (Array & itemsFound, int x, int y, int width, int height) + { + const Rectangle lassoArea (x, y, width, height); + + for (int i = canvas.getComponentHolder()->getNumChildComponents(); --i >= 0;) + { + Component* c = canvas.getComponentHolder()->getChildComponent(i); + if (c != this && c->getBounds().intersects (lassoArea)) + itemsFound.add (c->getComponentUID()); + } + } + + ComponentDocument::SelectedItems& getLassoSelection() { return canvas.getSelection(); } + + void changeListenerCallback (void*) + { + updateSelectedComponentOverlays(); + } + + private: + ComponentCanvas& canvas; + ScopedPointer > lasso; + bool mouseDownResult; + uint32 mouseDownCompUID; + + ComponentSelectorFrame* getSelectorFrameFor (Component* c) const + { + for (int i = getNumChildComponents(); --i >= 0;) + { + ComponentSelectorFrame* overlay = dynamic_cast (getChildComponent(i)); + if (overlay != 0 && overlay->getTargetComponentUID() == c->getComponentUID()) + return overlay; + } + + return 0; + } + + void updateSelectedComponentOverlays() + { + ComponentDocument::SelectedItems& selection = canvas.getSelection(); + + int i; + for (i = getNumChildComponents(); --i >= 0;) + { + ComponentSelectorFrame* overlay = dynamic_cast (getChildComponent(i)); + + if (overlay != 0 && ! selection.isSelected (overlay->getTargetComponentUID())) + delete overlay; + } + + for (i = canvas.getComponentHolder()->getNumChildComponents(); --i >= 0;) + { + Component* c = canvas.getComponentHolder()->getChildComponent(i); + + if (c != this && selection.isSelected (c->getComponentUID()) && getSelectorFrameFor (c) == 0) + addAndMakeVisible (new ComponentSelectorFrame (canvas, c)); + } + } + }; + + Component* componentHolder; + OverlayComponent* overlay; + ComponentDocument::SelectedItems selection; + + Component* getComponentForUID (const uint32 uid) const + { + for (int i = getNumChildComponents(); --i >= 0;) + if (componentHolder->getChildComponent (i)->getComponentUID() == uid) + return componentHolder->getChildComponent (i); + + return 0; + } +}; + + //============================================================================== ComponentEditor::ComponentEditor (OpenDocumentManager::Document* document, Project* project_, ComponentDocument* componentDocument_) @@ -37,6 +447,9 @@ ComponentEditor::ComponentEditor (OpenDocumentManager::Document* document, jassert (componentDocument != 0); setOpaque (true); + + addAndMakeVisible (viewport = new Viewport()); + viewport->setViewedComponent (new ComponentCanvas (*this)); } ComponentEditor::~ComponentEditor() @@ -51,4 +464,5 @@ void ComponentEditor::paint (Graphics& g) void ComponentEditor::resized() { + viewport->setBounds (0, 0, getWidth(), getHeight()); } diff --git a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.h b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.h index b84bfc3efe..9aaf5cb369 100644 --- a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.h +++ b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.h @@ -52,6 +52,8 @@ public: private: Project* project; ComponentDocument* componentDocument; + + Viewport* viewport; }; diff --git a/extras/Jucer (experimental)/Source/ui/jucer_OpenDocumentManager.cpp b/extras/Jucer (experimental)/Source/ui/jucer_OpenDocumentManager.cpp index bd40f80e03..1c1d08d37e 100644 --- a/extras/Jucer (experimental)/Source/ui/jucer_OpenDocumentManager.cpp +++ b/extras/Jucer (experimental)/Source/ui/jucer_OpenDocumentManager.cpp @@ -27,6 +27,7 @@ #include "jucer_SourceCodeEditor.h" #include "Drawable Editor/jucer_DrawableEditor.h" #include "jucer_ItemPreviewComponent.h" +#include "Component Editor/jucer_ComponentEditor.h" //============================================================================== @@ -47,7 +48,7 @@ public: bool loadedOk() const { return true; } bool isForFile (const File& file) const { return modDetector.getFile() == file; } bool isForNode (const ValueTree& node) const { return false; } - bool refersToProject (Project& project) const { return false; } + bool refersToProject (Project& project) const { return false; } const String getName() const { return modDetector.getFile().getFileName(); } const String getType() const { return modDetector.getFile().getFileExtension() + " file"; } bool needsSaving() const { return codeDoc != 0 && codeDoc->hasChangedSinceSavePoint(); } @@ -91,6 +92,66 @@ private: CPlusPlusCodeTokeniser cppTokeniser; }; +//============================================================================== +class ComponentDocumentType : public OpenDocumentManager::Document +{ +public: + ComponentDocumentType (Project* project_, const File& file_) + : project (project_), + modDetector (file_) + { + reloadFromFile(); + } + + ~ComponentDocumentType() + { + componentDoc = 0; + } + + static bool isComponentFile (const File& file) { return ComponentDocument::isComponentFile (file); } + + bool loadedOk() const { return componentDoc != 0; } + bool isForFile (const File& file) const { return modDetector.getFile() == file; } + bool isForNode (const ValueTree& node) const { return false; } + bool refersToProject (Project& p) const { return project == &p; } + const String getType() const { return "Jucer Component"; } + const String getName() const { return modDetector.getFile().getFileName(); } + bool needsSaving() const { return componentDoc != 0 && componentDoc->hasChangedSinceLastSave(); } + bool hasFileBeenModifiedExternally() { return modDetector.hasBeenModified(); } + + void reloadFromFile() + { + modDetector.updateHash(); + + if (componentDoc == 0) + componentDoc = new ComponentDocument (project, modDetector.getFile()); + + if (! componentDoc->reload()) + componentDoc = 0; + } + + bool save() + { + return componentDoc->save(); + } + + Component* createEditor() + { + if (componentDoc == 0) + { + jassertfalse; + return 0; + } + + return new ComponentEditor (this, project, componentDoc); + } + +private: + Project* project; + FileModificationDetector modDetector; + ScopedPointer componentDoc; +}; + //============================================================================== class DrawableDocumentType : public OpenDocumentManager::Document { @@ -112,7 +173,7 @@ public: bool loadedOk() const { return drawableDoc != 0; } bool isForFile (const File& file) const { return modDetector.getFile() == file; } bool isForNode (const ValueTree& node) const { return false; } - bool refersToProject (Project& p) const { return project == &p; } + bool refersToProject (Project& p) const { return project == &p; } const String getType() const { return "Drawable"; } const String getName() const { return modDetector.getFile().getFileName(); } bool needsSaving() const { return drawableDoc != 0 && drawableDoc->hasChangedSinceLastSave(); } @@ -165,7 +226,7 @@ public: bool loadedOk() const { return true; } bool isForFile (const File& file_) const { return file == file_; } bool isForNode (const ValueTree& node_) const { return false; } - bool refersToProject (Project& p) const { return project == &p; } + bool refersToProject (Project& p) const { return project == &p; } bool needsSaving() const { return false; } bool save() { return true; } bool hasFileBeenModifiedExternally() { return fileModificationTime != file.getLastModificationTime(); } @@ -227,7 +288,9 @@ OpenDocumentManager::Document* OpenDocumentManager::getDocumentForFile (Project* Document* d = 0; - if (DrawableDocumentType::isDrawableFile (file)) + if (ComponentDocumentType::isComponentFile (file)) + d = new ComponentDocumentType (project, file); + else if (DrawableDocumentType::isDrawableFile (file)) d = new DrawableDocumentType (project, file); else if (SourceCodeEditor::isTextFile (file)) d = new SourceCodeDocument (file); diff --git a/extras/audio plugin host/Source/MainHostWindow.h b/extras/audio plugin host/Source/MainHostWindow.h index f40b79f3e8..4afd1a6fa1 100644 --- a/extras/audio plugin host/Source/MainHostWindow.h +++ b/extras/audio plugin host/Source/MainHostWindow.h @@ -73,7 +73,7 @@ public: void menuItemSelected (int menuItemID, int topLevelMenuIndex); ApplicationCommandTarget* getNextCommandTarget(); void getAllCommands (Array & commands); - void getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result); + void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result); bool perform (const InvocationInfo& info); bool tryToQuitApplication(); diff --git a/extras/the jucer/src/ui/jucer_JucerDocumentHolder.h b/extras/the jucer/src/ui/jucer_JucerDocumentHolder.h index f24ad342df..6d55135a57 100644 --- a/extras/the jucer/src/ui/jucer_JucerDocumentHolder.h +++ b/extras/the jucer/src/ui/jucer_JucerDocumentHolder.h @@ -67,7 +67,7 @@ public: //============================================================================== ApplicationCommandTarget* getNextCommandTarget(); void getAllCommands (Array & commands); - void getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result); + void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result); bool perform (const InvocationInfo& info); static JucerDocumentHolder* getActiveDocumentHolder(); diff --git a/extras/the jucer/src/ui/jucer_MainWindow.h b/extras/the jucer/src/ui/jucer_MainWindow.h index e7e878442c..91e6ac21c7 100644 --- a/extras/the jucer/src/ui/jucer_MainWindow.h +++ b/extras/the jucer/src/ui/jucer_MainWindow.h @@ -67,7 +67,7 @@ public: //============================================================================== ApplicationCommandTarget* getNextCommandTarget(); void getAllCommands (Array & commands); - void getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result); + void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result); bool isCommandActive (const CommandID commandID); bool perform (const InvocationInfo& info); diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 35de06a512..9c36125b88 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -15965,18 +15965,18 @@ ValueTree ValueTree::SharedObject::getChildWithName (const String& typeToMatch) { for (int i = 0; i < children.size(); ++i) if (children.getUnchecked(i)->type == typeToMatch) - return (SharedObject*) children.getUnchecked(i); + return ValueTree (static_cast (children.getUnchecked(i))); - return (SharedObject*) 0; + return ValueTree::invalid; } ValueTree ValueTree::SharedObject::getChildWithProperty (const var::identifier& propertyName, const var& propertyValue) const { for (int i = 0; i < children.size(); ++i) if (children.getUnchecked(i)->getProperty (propertyName) == propertyValue) - return (SharedObject*) children.getUnchecked(i); + return ValueTree (static_cast (children.getUnchecked(i))); - return (SharedObject*) 0; + return ValueTree::invalid; } bool ValueTree::SharedObject::isAChildOf (const SharedObject* const possibleParent) const @@ -16058,6 +16058,8 @@ void ValueTree::SharedObject::removeAllChildren (UndoManager* const undoManager) removeChild (children.size() - 1, undoManager); } +ValueTree ValueTree::invalid ((ValueTree::SharedObject*) 0); + ValueTree::ValueTree (const String& type_) : object (new ValueTree::SharedObject (type_)) { @@ -16123,7 +16125,7 @@ const String ValueTree::getType() const ValueTree ValueTree::getParent() const { - return object != 0 ? ValueTree (object->parent) : ValueTree ((SharedObject*) 0); + return ValueTree (object != 0 ? object->parent : (SharedObject*) 0); } const var& ValueTree::operator[] (const var::identifier& name) const @@ -16230,17 +16232,17 @@ int ValueTree::getNumChildren() const ValueTree ValueTree::getChild (int index) const { - return object != 0 ? (SharedObject*) object->children [index] : ValueTree ((SharedObject*) 0); + return ValueTree (object != 0 ? (SharedObject*) object->children [index] : (SharedObject*) 0); } ValueTree ValueTree::getChildWithName (const String& type) const { - return object != 0 ? object->getChildWithName (type) : ValueTree ((SharedObject*) 0); + return object != 0 ? object->getChildWithName (type) : ValueTree::invalid; } ValueTree ValueTree::getChildWithProperty (const var::identifier& propertyName, const var& propertyValue) const { - return object != 0 ? object->getChildWithProperty (propertyName, propertyValue) : ValueTree ((SharedObject*) 0); + return object != 0 ? object->getChildWithProperty (propertyName, propertyValue) : ValueTree::invalid; } bool ValueTree::isAChildOf (const ValueTree& possibleParent) const @@ -16361,7 +16363,7 @@ ValueTree ValueTree::readFromStream (InputStream& input) String type (input.readString()); if (type.isEmpty()) - return ValueTree ((SharedObject*) 0); + return ValueTree::invalid; ValueTree v (type); @@ -39322,14 +39324,14 @@ Component* Component::removeChildComponent (const int index) void Component::removeAllChildren() { - for (int i = childComponentList_.size(); --i >= 0;) - removeChildComponent (i); + while (childComponentList_.size() > 0) + removeChildComponent (childComponentList_.size() - 1); } void Component::deleteAllChildren() { - for (int i = childComponentList_.size(); --i >= 0;) - delete (removeChildComponent (i)); + while (childComponentList_.size() > 0) + delete (removeChildComponent (childComponentList_.size() - 1)); } int Component::getNumChildComponents() const throw() @@ -92220,6 +92222,10 @@ namespace zlibNamespace # define inflateInit_ z_inflateInit_ # define inflate z_inflate # define inflateEnd z_inflateEnd +# define inflatePrime z_inflatePrime +# define inflateGetHeader z_inflateGetHeader +# define adler32_combine z_adler32_combine +# define crc32_combine z_crc32_combine # define deflateInit2_ z_deflateInit2_ # define deflateSetDictionary z_deflateSetDictionary # define deflateCopy z_deflateCopy diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 24d2612390..5abc1dfcfa 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -43,7 +43,7 @@ #define JUCE_MAJOR_VERSION 1 #define JUCE_MINOR_VERSION 51 -#define JUCE_BUILDNUMBER 13 +#define JUCE_BUILDNUMBER 14 #define JUCE_VERSION ((JUCE_MAJOR_VERSION << 16) + (JUCE_MINOR_VERSION << 8) + JUCE_BUILDNUMBER) @@ -6772,6 +6772,8 @@ public: } } + static ValueTree invalid; + juce_UseDebuggingNewOperator private: @@ -6838,7 +6840,7 @@ private: ListenerList listeners; public: - ValueTree (SharedObject* const object_); // (can be made private when VC6 support is finally dropped) + explicit ValueTree (SharedObject* const object_); // (can be made private when VC6 support is finally dropped) }; #endif // __JUCE_VALUETREE_JUCEHEADER__ @@ -25411,6 +25413,8 @@ class JUCE_API SelectedItemSet : public ChangeBroadcaster { public: + typedef SelectableItemType ItemType; + SelectedItemSet() { } diff --git a/src/containers/juce_ValueTree.cpp b/src/containers/juce_ValueTree.cpp index 6f939e9c08..7a7881adb6 100644 --- a/src/containers/juce_ValueTree.cpp +++ b/src/containers/juce_ValueTree.cpp @@ -296,18 +296,18 @@ ValueTree ValueTree::SharedObject::getChildWithName (const String& typeToMatch) { for (int i = 0; i < children.size(); ++i) if (children.getUnchecked(i)->type == typeToMatch) - return (SharedObject*) children.getUnchecked(i); + return ValueTree (static_cast (children.getUnchecked(i))); - return (SharedObject*) 0; + return ValueTree::invalid; } ValueTree ValueTree::SharedObject::getChildWithProperty (const var::identifier& propertyName, const var& propertyValue) const { for (int i = 0; i < children.size(); ++i) if (children.getUnchecked(i)->getProperty (propertyName) == propertyValue) - return (SharedObject*) children.getUnchecked(i); + return ValueTree (static_cast (children.getUnchecked(i))); - return (SharedObject*) 0; + return ValueTree::invalid; } bool ValueTree::SharedObject::isAChildOf (const SharedObject* const possibleParent) const @@ -391,6 +391,8 @@ void ValueTree::SharedObject::removeAllChildren (UndoManager* const undoManager) //============================================================================== +ValueTree ValueTree::invalid ((ValueTree::SharedObject*) 0); + ValueTree::ValueTree (const String& type_) : object (new ValueTree::SharedObject (type_)) { @@ -456,7 +458,7 @@ const String ValueTree::getType() const ValueTree ValueTree::getParent() const { - return object != 0 ? ValueTree (object->parent) : ValueTree ((SharedObject*) 0); + return ValueTree (object != 0 ? object->parent : (SharedObject*) 0); } const var& ValueTree::operator[] (const var::identifier& name) const @@ -565,17 +567,17 @@ int ValueTree::getNumChildren() const ValueTree ValueTree::getChild (int index) const { - return object != 0 ? (SharedObject*) object->children [index] : ValueTree ((SharedObject*) 0); + return ValueTree (object != 0 ? (SharedObject*) object->children [index] : (SharedObject*) 0); } ValueTree ValueTree::getChildWithName (const String& type) const { - return object != 0 ? object->getChildWithName (type) : ValueTree ((SharedObject*) 0); + return object != 0 ? object->getChildWithName (type) : ValueTree::invalid; } ValueTree ValueTree::getChildWithProperty (const var::identifier& propertyName, const var& propertyValue) const { - return object != 0 ? object->getChildWithProperty (propertyName, propertyValue) : ValueTree ((SharedObject*) 0); + return object != 0 ? object->getChildWithProperty (propertyName, propertyValue) : ValueTree::invalid; } bool ValueTree::isAChildOf (const ValueTree& possibleParent) const @@ -699,7 +701,7 @@ ValueTree ValueTree::readFromStream (InputStream& input) String type (input.readString()); if (type.isEmpty()) - return ValueTree ((SharedObject*) 0); + return ValueTree::invalid; ValueTree v (type); diff --git a/src/containers/juce_ValueTree.h b/src/containers/juce_ValueTree.h index eeff68e5c1..9df2e5ff0d 100644 --- a/src/containers/juce_ValueTree.h +++ b/src/containers/juce_ValueTree.h @@ -377,6 +377,9 @@ public: } } + /** An invalid ValueTree that can be used if you need to return one as an error condition, etc. */ + static ValueTree invalid; + //============================================================================== juce_UseDebuggingNewOperator @@ -445,7 +448,7 @@ private: public: /** @internal */ - ValueTree (SharedObject* const object_); // (can be made private when VC6 support is finally dropped) + explicit ValueTree (SharedObject* const object_); // (can be made private when VC6 support is finally dropped) }; diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index c18cefd292..2f07f90544 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 51 -#define JUCE_BUILDNUMBER 13 +#define JUCE_BUILDNUMBER 14 /** Current Juce version number. diff --git a/src/gui/components/juce_Component.cpp b/src/gui/components/juce_Component.cpp index b170b12918..2359a1fe9d 100644 --- a/src/gui/components/juce_Component.cpp +++ b/src/gui/components/juce_Component.cpp @@ -1207,14 +1207,14 @@ Component* Component::removeChildComponent (const int index) //============================================================================== void Component::removeAllChildren() { - for (int i = childComponentList_.size(); --i >= 0;) - removeChildComponent (i); + while (childComponentList_.size() > 0) + removeChildComponent (childComponentList_.size() - 1); } void Component::deleteAllChildren() { - for (int i = childComponentList_.size(); --i >= 0;) - delete (removeChildComponent (i)); + while (childComponentList_.size() > 0) + delete (removeChildComponent (childComponentList_.size() - 1)); } //============================================================================== diff --git a/src/io/streams/zlib/zconf.h b/src/io/streams/zlib/zconf.h index 008c22fdf0..f1e9e870b7 100644 --- a/src/io/streams/zlib/zconf.h +++ b/src/io/streams/zlib/zconf.h @@ -28,6 +28,10 @@ # define inflateInit_ z_inflateInit_ # define inflate z_inflate # define inflateEnd z_inflateEnd +# define inflatePrime z_inflatePrime +# define inflateGetHeader z_inflateGetHeader +# define adler32_combine z_adler32_combine +# define crc32_combine z_crc32_combine # define deflateInit2_ z_deflateInit2_ # define deflateSetDictionary z_deflateSetDictionary # define deflateCopy z_deflateCopy diff --git a/src/utilities/juce_SelectedItemSet.h b/src/utilities/juce_SelectedItemSet.h index e149a7f6c2..67d2ffa97a 100644 --- a/src/utilities/juce_SelectedItemSet.h +++ b/src/utilities/juce_SelectedItemSet.h @@ -48,6 +48,9 @@ template class JUCE_API SelectedItemSet : public ChangeBroadcaster { public: + //============================================================================== + typedef SelectableItemType ItemType; + //============================================================================== /** Creates an empty set. */ SelectedItemSet()