From 671dde2ffa068b257fdc41127870de5ce602fc71 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Wed, 7 Apr 2010 21:44:20 +0200 Subject: [PATCH] Jucer development. --- .../model/Component Types/jucer_TextButton.h | 14 ++- .../Component Types/jucer_ToggleButton.h | 14 ++- .../Source/model/jucer_ComponentDocument.cpp | 113 +++++++++++++----- .../Source/model/jucer_ComponentDocument.h | 8 +- .../jucer_ComponentEditor.cpp | 113 +++++++++++++++--- .../Component Editor/jucer_ComponentEditor.h | 8 ++ juce_amalgamated.cpp | 4 +- 7 files changed, 215 insertions(+), 59 deletions(-) diff --git a/extras/Jucer (experimental)/Source/model/Component Types/jucer_TextButton.h b/extras/Jucer (experimental)/Source/model/Component Types/jucer_TextButton.h index 20e54c99e6..1d1a067550 100644 --- a/extras/Jucer (experimental)/Source/model/Component Types/jucer_TextButton.h +++ b/extras/Jucer (experimental)/Source/model/Component Types/jucer_TextButton.h @@ -45,10 +45,16 @@ public: tb->setButtonText (state ["text"].toString()); } - const ValueTree createNewItem (ComponentDocument& document) + void initialiseNewItem (ValueTree& state, ComponentDocument& document) { - ValueTree v (ComponentTypeHandler::createNewItem (document)); - v.setProperty ("text", "New Toggle Button", 0); - return v; + ComponentTypeHandler::initialiseNewItem (state, document); + state.setProperty ("text", "New Toggle Button", 0); + } + + void createPropertyEditors (ValueTree& state, ComponentDocument& document, Array & props) + { + ComponentTypeHandler::createPropertyEditors (state, document, props); + props.add (new TextPropertyComponent (getValue ("text", state, document), "Button Text", 1024, false)); + props.getLast()->setTooltip ("The button's text."); } }; diff --git a/extras/Jucer (experimental)/Source/model/Component Types/jucer_ToggleButton.h b/extras/Jucer (experimental)/Source/model/Component Types/jucer_ToggleButton.h index c298471c6f..263c8513a4 100644 --- a/extras/Jucer (experimental)/Source/model/Component Types/jucer_ToggleButton.h +++ b/extras/Jucer (experimental)/Source/model/Component Types/jucer_ToggleButton.h @@ -45,10 +45,16 @@ public: tb->setButtonText (state ["text"].toString()); } - const ValueTree createNewItem (ComponentDocument& document) + void initialiseNewItem (ValueTree& state, ComponentDocument& document) { - ValueTree v (ComponentTypeHandler::createNewItem (document)); - v.setProperty ("text", "New Toggle Button", 0); - return v; + ComponentTypeHandler::initialiseNewItem (state, document); + state.setProperty ("text", "New Toggle Button", 0); + } + + void createPropertyEditors (ValueTree& state, ComponentDocument& document, Array & props) + { + ComponentTypeHandler::createPropertyEditors (state, document, props); + props.add (new TextPropertyComponent (getValue ("text", state, document), "Button Text", 1024, false)); + props.getLast()->setTooltip ("The button's text."); } }; diff --git a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp index 6134e03ac3..d206237eaa 100644 --- a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp +++ b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.cpp @@ -40,17 +40,6 @@ static const char* const compNameProperty = "name"; static const char* const metadataTagStart = "JUCER_" "COMPONENT_METADATA_START"; // written like this to avoid thinking this file is a component! static const char* const metadataTagEnd = "JUCER_" "COMPONENT_METADATA_END"; -//============================================================================== -static const String componentBoundsToString (const Rectangle& bounds) -{ - return bounds.toString(); -} - -static const Rectangle stringToComponentBounds (const String& s) -{ - return Rectangle::fromString (s); -} - //============================================================================== ComponentTypeHandler::ComponentTypeHandler (const String& name_, const String& xmlTag_, const String& memberNameRoot_) @@ -63,24 +52,37 @@ ComponentTypeHandler::~ComponentTypeHandler() { } +Value ComponentTypeHandler::getValue (const var::identifier& name, ValueTree& state, ComponentDocument& document) const +{ + return state.getPropertyAsValue (name, document.getUndoManager()); +} + void ComponentTypeHandler::updateComponent (Component* comp, const ValueTree& state) { - comp->setBounds (stringToComponentBounds (state [compBoundsProperty])); + if (comp->getParentComponent() != 0) + { + PositionedRectangle pos (state [compBoundsProperty].toString()); + comp->setBounds (pos.getRectangle (comp->getParentComponent()->getLocalBounds())); + } + comp->setName (state [compNameProperty]); } -const ValueTree ComponentTypeHandler::createNewItem (ComponentDocument& document) +void ComponentTypeHandler::initialiseNewItem (ValueTree& state, ComponentDocument& document) { - ValueTree v (getXmlTag()); - v.setProperty (idProperty, createAlphaNumericUID(), 0); - v.setProperty (compNameProperty, String::empty, 0); - v.setProperty (memberNameProperty, document.getNonExistentMemberName (getMemberNameRoot()), 0); - v.setProperty (compBoundsProperty, - componentBoundsToString (getDefaultSize().withPosition (Point (Random::getSystemRandom().nextInt (100) + 100, - Random::getSystemRandom().nextInt (100) + 100))), 0); - return v; + state.setProperty (compNameProperty, String::empty, 0); + state.setProperty (memberNameProperty, document.getNonExistentMemberName (getMemberNameRoot()), 0); + state.setProperty (compBoundsProperty, + getDefaultSize().withPosition (Point (Random::getSystemRandom().nextInt (100) + 100, + Random::getSystemRandom().nextInt (100) + 100)).toString(), 0); } +void ComponentTypeHandler::createPropertyEditors (ValueTree& state, ComponentDocument& document, + Array & props) +{ + props.add (new TextPropertyComponent (getValue (compBoundsProperty, state, document), "Bounds", 512, false)); + props.getLast()->setTooltip ("The component's position."); +} //============================================================================== class ComponentTypeManager : public DeletedAtShutdown @@ -326,7 +328,13 @@ void ComponentDocument::performNewComponentMenuItem (int menuResultCode) jassert (handler != 0); if (handler != 0) - getComponentGroup().addChild (handler->createNewItem (*this), -1, getUndoManager()); + { + ValueTree state (handler->getXmlTag()); + state.setProperty (idProperty, createAlphaNumericUID(), 0); + handler->initialiseNewItem (state, *this); + + getComponentGroup().addChild (state, -1, getUndoManager()); + } } } @@ -413,6 +421,20 @@ const ValueTree ComponentDocument::getComponentState (Component* comp) const return ValueTree::invalid; } +void ComponentDocument::getComponentProperties (Array & props, Component* comp) +{ + ValueTree v (getComponentState (comp)); + + if (v.isValid()) + { + ComponentTypeHandler* handler = ComponentTypeManager::getInstance()->getHandlerFor (v.getType()); + jassert (handler != 0); + + if (handler != 0) + handler->createPropertyEditors (v, *this, props); + } +} + bool ComponentDocument::isStateForComponent (const ValueTree& storedState, Component* comp) const { jassert (comp != 0); @@ -438,6 +460,12 @@ const String ComponentDocument::getNonExistentMemberName (String suggestedName) return suggestedName; } +//============================================================================== +UndoManager* ComponentDocument::getUndoManager() +{ + return &undoManager; +} + //============================================================================== class ComponentDocument::DragHandler { @@ -452,21 +480,37 @@ public: for (int i = 0; i < items.size(); ++i) { Component* comp = items.getUnchecked(i); - jassert (items.getUnchecked(i) != 0); + jassert (comp != 0); + + parentComponentSize.setSize (comp->getParentWidth(), comp->getParentHeight()); + jassert (! parentComponentSize.isEmpty()); + const ValueTree v (document.getComponentState (comp)); draggedComponents.add (v); - const Rectangle pos (stringToComponentBounds (v [compBoundsProperty])); - originalPositions.add (pos); + PositionedRectangle pos (v [compBoundsProperty].toString()); + originalPositions.add (pos.getRectangle (parentComponentSize)); const Rectangle floatPos ((float) pos.getX(), (float) pos.getY(), (float) pos.getWidth(), (float) pos.getHeight()); - verticalSnapPositions.add (floatPos.getX()); - verticalSnapPositions.add (floatPos.getCentreX()); - verticalSnapPositions.add (floatPos.getRight()); - horizontalSnapPositions.add (floatPos.getY()); - verticalSnapPositions.add (floatPos.getCentreY()); - horizontalSnapPositions.add (floatPos.getBottom()); + + if (zone.isDraggingWholeObject() || zone.isDraggingLeftEdge()) + verticalSnapPositions.add (floatPos.getX()); + + if (zone.isDraggingWholeObject() || zone.isDraggingLeftEdge() || zone.isDraggingRightEdge()) + verticalSnapPositions.add (floatPos.getCentreX()); + + if (zone.isDraggingWholeObject() || zone.isDraggingRightEdge()) + verticalSnapPositions.add (floatPos.getRight()); + + if (zone.isDraggingWholeObject() || zone.isDraggingTopEdge()) + horizontalSnapPositions.add (floatPos.getY()); + + if (zone.isDraggingWholeObject() || zone.isDraggingTopEdge() || zone.isDraggingBottomEdge()) + verticalSnapPositions.add (floatPos.getCentreY()); + + if (zone.isDraggingWholeObject() || zone.isDraggingBottomEdge()) + horizontalSnapPositions.add (floatPos.getBottom()); } document.beginNewTransaction(); @@ -488,7 +532,11 @@ public: void move (ValueTree& v, const Point& distance, const Rectangle& originalPos) { Rectangle newBounds (zone.resizeRectangleBy (originalPos, distance)); - v.setProperty (compBoundsProperty, componentBoundsToString (newBounds), document.getUndoManager()); + + PositionedRectangle pr (v [compBoundsProperty].toString()); + pr.updateFrom (newBounds, parentComponentSize); + + v.setProperty (compBoundsProperty, pr.toString(), document.getUndoManager()); } const Array getVerticalSnapPositions (const Point& distance) const @@ -510,6 +558,7 @@ public: } private: + Rectangle parentComponentSize; ComponentDocument& document; Array draggedComponents; Array > originalPositions; diff --git a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h index 1b4e41c283..b72e661237 100644 --- a/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h +++ b/extras/Jucer (experimental)/Source/model/jucer_ComponentDocument.h @@ -59,6 +59,7 @@ public: void updateComponent (Component* comp) const; bool containsComponent (Component* comp) const; const ValueTree getComponentState (Component* comp) const; + void getComponentProperties (Array & props, Component* comp); bool isStateForComponent (const ValueTree& storedState, Component* comp) const; void addNewComponentMenuItems (PopupMenu& menu) const; @@ -72,7 +73,7 @@ public: //============================================================================== ValueTree& getRoot() { return root; } - UndoManager* getUndoManager() throw() { return &undoManager; } + UndoManager* getUndoManager(); void beginNewTransaction(); void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const var::identifier& property); @@ -114,7 +115,10 @@ public: virtual const Rectangle getDefaultSize() = 0; virtual void updateComponent (Component* comp, const ValueTree& state); - virtual const ValueTree createNewItem (ComponentDocument& document); + virtual void initialiseNewItem (ValueTree& state, ComponentDocument& document); + virtual void createPropertyEditors (ValueTree& state, ComponentDocument& document, Array & props); + + Value getValue (const var::identifier& name, ValueTree& state, ComponentDocument& document) const; //============================================================================== protected: 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 ee3e40bdaa..963563b183 100644 --- a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp +++ b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.cpp @@ -28,11 +28,12 @@ //============================================================================== -class ComponentCanvas : public Component, - public ValueTree::Listener +class ComponentEditor::Canvas : public Component, + public ValueTree::Listener, + public Timer { public: - ComponentCanvas (ComponentEditor& editor_) + Canvas (ComponentEditor& editor_) : editor (editor_), borderThickness (4) { setOpaque (true); @@ -45,7 +46,7 @@ public: updateComponents(); } - ~ComponentCanvas() + ~Canvas() { getDocument().getRoot().removeListener (this); deleteAllChildren(); @@ -60,10 +61,9 @@ public: void resized() { - componentHolder->setBounds (borderThickness, borderThickness, - getWidth() - borderThickness * 2, getHeight() - borderThickness * 2); - + componentHolder->setBounds (getLocalBounds().reduced (borderThickness, borderThickness)); overlay->setBounds (componentHolder->getBounds()); + updateComponents(); } void zoom (float newScale, const Point& centre) @@ -121,6 +121,8 @@ public: doc.updateComponent (c); } } + + startTimer (500); } void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const var::identifier& property) @@ -141,7 +143,8 @@ public: const Array getSelectedComps() const { - Array comps; + Array comps; + for (int i = 0; i < selection.getNumSelected(); ++i) { Component* c = getComponentForUID (selection.getSelectedItem (i)); @@ -153,6 +156,25 @@ public: return comps; } + void getSelectedItemProperties (Array & props) + { + //xxx needs to handle multiple selections.. + + if (selection.getNumSelected() == 1) + { + Component* c = getComponentForUID (selection.getSelectedItem (0)); + getDocument().getComponentProperties (props, c); + } + } + + void timerCallback() + { + stopTimer(); + + if (! Component::isMouseButtonDownAnywhere()) + getDocument().beginNewTransaction(); + } + private: ComponentEditor& editor; const int borderThickness; @@ -162,7 +184,7 @@ private: public ComponentListener { public: - ComponentResizeFrame (ComponentCanvas& canvas_, + ComponentResizeFrame (Canvas& canvas_, Component* componentToAttachTo) : canvas (canvas_), component (componentToAttachTo), @@ -240,7 +262,7 @@ private: uint32 getTargetComponentUID() const { return component == 0 ? 0 : component->getComponentUID(); } private: - ComponentCanvas& canvas; + Canvas& canvas; Component::SafePointer component; ResizableBorderComponent::Zone dragZone; const int borderThickness; @@ -270,7 +292,7 @@ private: public ChangeListener { public: - OverlayComponent (ComponentCanvas& canvas_) + OverlayComponent (Canvas& canvas_) : canvas (canvas_) { setAlwaysOnTop (true); @@ -382,7 +404,7 @@ private: } private: - ComponentCanvas& canvas; + Canvas& canvas; ScopedPointer > lasso; bool mouseDownResult, isDraggingClickedComp; uint32 mouseDownCompUID; @@ -436,24 +458,76 @@ private: } }; +//============================================================================== +class ComponentEditor::InfoPanel : public Component, + public ChangeListener +{ +public: + InfoPanel (ComponentEditor& editor_) + : editor (editor_) + { + setOpaque (true); + + addAndMakeVisible (props = new PropertyPanel()); + + editor.getCanvas()->getSelection().addChangeListener (this); + } + + ~InfoPanel() + { + editor.getCanvas()->getSelection().removeChangeListener (this); + + props->clear(); + deleteAllChildren(); + } + + void changeListenerCallback (void*) + { + Array newComps; + editor.getCanvas()->getSelectedItemProperties (newComps); + + props->clear(); + props->addProperties (newComps); + } + + void paint (Graphics& g) + { + g.fillAll (Colour::greyLevel (0.92f)); + } + + void resized() + { + props->setSize (getWidth(), getHeight()); + } + +private: + ComponentEditor& editor; + PropertyPanel* props; +}; + //============================================================================== ComponentEditor::ComponentEditor (OpenDocumentManager::Document* document, Project* project_, ComponentDocument* componentDocument_) : DocumentEditorComponent (document), project (project_), - componentDocument (componentDocument_) + componentDocument (componentDocument_), + infoPanel (0) { setOpaque (true); addAndMakeVisible (viewport = new Viewport()); if (document != 0) - viewport->setViewedComponent (new ComponentCanvas (*this)); + { + viewport->setViewedComponent (new Canvas (*this)); + addAndMakeVisible (infoPanel = new InfoPanel (*this)); + } } ComponentEditor::~ComponentEditor() { + deleteAndZero (infoPanel); deleteAllChildren(); } @@ -464,7 +538,16 @@ void ComponentEditor::paint (Graphics& g) void ComponentEditor::resized() { - viewport->setBounds (0, 0, getWidth(), getHeight()); + const int infoPanelWidth = 200; + viewport->setBounds (0, 0, getWidth() - infoPanelWidth, getHeight()); + + if (infoPanel != 0) + infoPanel->setBounds (getWidth() - infoPanelWidth, 0, infoPanelWidth, getHeight()); +} + +ComponentEditor::Canvas* ComponentEditor::getCanvas() const +{ + return dynamic_cast (viewport->getViewedComponent()); } void ComponentEditor::getAllCommands (Array & commands) 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 627a177c5b..a6b8606930 100644 --- a/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.h +++ b/extras/Jucer (experimental)/Source/ui/Component Editor/jucer_ComponentEditor.h @@ -53,11 +53,19 @@ public: ComponentDocument& getDocument() const { return *componentDocument; } + Viewport* getViewport() const throw() { return viewport; } + + class Canvas; + Canvas* getCanvas() const; + private: + class InfoPanel; + Project* project; ComponentDocument* componentDocument; Viewport* viewport; + InfoPanel* infoPanel; }; diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 02ecea8794..cdbae896c0 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -32624,7 +32624,7 @@ private: originalWndProc = (void*) GetWindowLongPtr (pluginHWND, GWL_WNDPROC); if (! pluginWantsKeys) - SetWindowLongPtr (pluginHWND, GWL_WNDPROC, (LONG_PTR) vstHookWndProc); + SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) vstHookWndProc); #pragma warning (pop) @@ -32717,7 +32717,7 @@ private: #pragma warning (disable: 4244) if (pluginHWND != 0 && IsWindow (pluginHWND)) - SetWindowLongPtr (pluginHWND, GWL_WNDPROC, (LONG_PTR) originalWndProc); + SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) originalWndProc); #pragma warning (pop)