diff --git a/CrdtExamples.jucer b/CrdtExamples.jucer index a688bbe..50c6c93 100644 --- a/CrdtExamples.jucer +++ b/CrdtExamples.jucer @@ -14,6 +14,10 @@ file="Source/crdtsimNetwork.cpp"/> + + @@ -26,9 +30,10 @@ + isDebug="1" optimisation="1" targetName="CrdtExamples" cppLanguageStandard="c++11"/> + isDebug="0" optimisation="3" targetName="CrdtExamples" linkTimeOptimisation="1" + cppLanguageStandard="c++11"/> diff --git a/Source/MainComponent.cpp b/Source/MainComponent.cpp index eb9967c..6b4d521 100644 --- a/Source/MainComponent.cpp +++ b/Source/MainComponent.cpp @@ -10,6 +10,8 @@ #define MAINCOMPONENT_H_INCLUDED #include "../JuceLibraryCode/JuceHeader.h" +#include "crdtsimNetworkComponent.h" +#include "crdtsimNetwork.h" //============================================================================== /* @@ -22,6 +24,12 @@ class MainContentComponent : public AnimatedAppComponent //============================================================================== MainContentComponent () { + //MODEL + networkComponent.setNodesValueTree (network.getNodesValueTree ()); + networkComponent.setConnexionsValueTree (network.getConnexionsValueTree ()); + network.createNode (); + //VIEW + addAndMakeVisible (&networkComponent); setSize (800, 600); setFramesPerSecond (60); } @@ -47,18 +55,13 @@ class MainContentComponent : public AnimatedAppComponent void resized () override { - // This is called when the MainContentComponent is resized. - // If you add any child components, this is where you should - // update their positions. + networkComponent.setBounds (getLocalBounds ()); } private: - //============================================================================== - - // Your private member variables go here... - - + crdtsim::NetworkComponent networkComponent; + crdtsim::Network network; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent) }; diff --git a/Source/crdtsimConnexionComponent.cpp b/Source/crdtsimConnexionComponent.cpp new file mode 100644 index 0000000..1e03c86 --- /dev/null +++ b/Source/crdtsimConnexionComponent.cpp @@ -0,0 +1,3 @@ +#include "crdtsimConnexionComponent.h" + +using namespace crdtsim; diff --git a/Source/crdtsimConnexionComponent.h b/Source/crdtsimConnexionComponent.h new file mode 100644 index 0000000..f386735 --- /dev/null +++ b/Source/crdtsimConnexionComponent.h @@ -0,0 +1,10 @@ +#ifndef CRDTSIMCONNEXIONCOMPONENT_H_INCLUDED +#define CRDTSIMCONNEXIONCOMPONENT_H_INCLUDED +#include "JuceHeader.h" +namespace crdtsim +{ +class NodeComponent : public juce::Component +{ +}; +} //namespace crdtsim +#endif // CRDTSIMCONNEXIONCOMPONENT_H_INCLUDED diff --git a/Source/crdtsimNetwork.cpp b/Source/crdtsimNetwork.cpp index 667827d..33c68e1 100644 --- a/Source/crdtsimNetwork.cpp +++ b/Source/crdtsimNetwork.cpp @@ -1,15 +1,17 @@ #include "crdtsimNetwork.h" -#include "JuceHeader.h" #include namespace crdtsim { +Network::Network () : valueTree ("RootNetwork") {} int Network::size () const { return nodes.size (); } int Network::createNode () { auto newNode = Node{lastNodeIdentifier++}; nodes.push_back (newNode); jassert (size () > 0); + getNodesValueTree ().getOrCreateChildWithName (getNodeIdentifier (nodes.back ().getIdentifier ()), nullptr); + jassert (valueTree.getNumChildren () > 0); return nodes.back ().getIdentifier (); } const Node* Network::getNode (int identifier) const @@ -39,6 +41,7 @@ bool Network::eraseNode (int identifier) return false; } nodes.erase (nodeToRemodeIt, std::end (nodes)); + getNodesValueTree ().removeChild (getNodesValueTree ().getChildWithName (getNodeIdentifier (identifier)), nullptr); eraseAllConnexionsWithNode (identifier); return true; } @@ -64,6 +67,7 @@ bool Network::createConnexion (int sourceIdentifier, int destinationIdentifier) if (std::find (std::begin (connexions), std::end (connexions), connexionToAdd) == std::end (connexions)) { connexions.push_back (connexionToAdd); + getConnexionsValueTree ().getOrCreateChildWithName (getConnexionIdentifier (sourceIdentifier, destinationIdentifier), nullptr); } return true; } @@ -77,6 +81,7 @@ bool Network::eraseConnexion (int sourceIdentifier, int destinationIdentifier) return false; } connexions.erase (findResult); + getConnexionsValueTree ().removeChild (getConnexionsValueTree ().getChildWithName (getConnexionIdentifier (sourceIdentifier, destinationIdentifier)), nullptr); return true; } bool Network::connexionExists (int sourceIdentifier, int destinationIdentifier) @@ -98,6 +103,22 @@ void Network::eraseAllConnexionsWithNode (int nodeIdentifier) }; connexions.erase (std::remove_if (std::begin (connexions), std::end (connexions), sameDestinationPredicate), std::end (connexions)); } +juce::ValueTree Network::getNodesValueTree () +{ + return valueTree.getOrCreateChildWithName ("NODES", nullptr); +} +juce::ValueTree Network::getConnexionsValueTree () +{ + return valueTree.getOrCreateChildWithName ("CONNEXIONS", nullptr); +} +juce::Identifier Network::getNodeIdentifier (int nodeIdentifier) +{ + return juce::String ("NODE#" + std::to_string (nodeIdentifier)); +} +juce::Identifier Network::getConnexionIdentifier (int sourceIdentifier, int destinationIdentifier) +{ + return juce::String ("CONNEXION#" + std::to_string (sourceIdentifier) + "->" + std::to_string (destinationIdentifier)); +} class TestNetwork : public juce::UnitTest @@ -228,6 +249,40 @@ class TestNetwork : public juce::UnitTest expect (!network.connexionExists (nodeIdentifier1, nodeIdentifier2)); expect (!network.connexionExists (nodeIdentifier2, nodeIdentifier3)); } + { + beginTest ("Network creates a child to ValueTree when creating a node."); + Network network; + auto initialValueTreeSize = network.getNodesValueTree ().getNumChildren (); + network.createNode (); + expectEquals (network.getNodesValueTree ().getNumChildren (), initialValueTreeSize + 1, "Network hasn't taken care of its tree."); + } + { + beginTest ("Network deletes a child to ValueTree when deleting a node."); + Network network; + auto nodeId = network.createNode (); + auto initialValueTreeSize = network.getNodesValueTree ().getNumChildren (); + network.eraseNode (nodeId); + expectEquals (network.getNodesValueTree ().getNumChildren (), initialValueTreeSize - 1, "Network hasn't taken care of its tree."); + } + { + beginTest ("Network creates a child to ValueTree when creating a connexion."); + Network network; + auto nodeId1 = network.createNode (); + auto nodeId2 = network.createNode (); + auto initialValueTreeSize = network.getConnexionsValueTree ().getNumChildren (); + network.createConnexion (nodeId1, nodeId2); + expectEquals (network.getConnexionsValueTree ().getNumChildren (), initialValueTreeSize + 1, "Network hasn't taken care of its tree."); + } + { + beginTest ("Network deletes a child to ValueTree when deleting a connexion."); + Network network; + auto nodeId1 = network.createNode (); + auto nodeId2 = network.createNode (); + network.createConnexion (nodeId1, nodeId2); + auto initialValueTreeSize = network.getConnexionsValueTree ().getNumChildren (); + network.eraseConnexion (nodeId1, nodeId2); + expectEquals (network.getConnexionsValueTree ().getNumChildren (), initialValueTreeSize - 1, "Network hasn't taken care of its tree."); + } } } testTestNetwork; } diff --git a/Source/crdtsimNetwork.h b/Source/crdtsimNetwork.h index eb93b20..03d4188 100644 --- a/Source/crdtsimNetwork.h +++ b/Source/crdtsimNetwork.h @@ -3,11 +3,13 @@ #include #include "crdtsimNode.h" #include "crdtsimConnexion.h" +#include "JuceHeader.h" namespace crdtsim { class Network { public: + Network (); int size () const; int createNode (); const Node* getNode (int identifier) const; @@ -15,6 +17,8 @@ class Network bool createConnexion (int sourceIdentifier, int destinationIdentifier); bool eraseConnexion (int sourceIdentifier, int destinationIdentifier); bool connexionExists (int sourceIdentifier, int destinationIdentifier); + juce::ValueTree getNodesValueTree (); + juce::ValueTree getConnexionsValueTree (); private: std::vector nodes; @@ -22,6 +26,9 @@ class Network std::vector connexions; void eraseAllConnexionsWithNode (int nodeIdentifier); + juce::ValueTree valueTree; + static juce::Identifier getNodeIdentifier (int nodeIdentifier); + static juce::Identifier getConnexionIdentifier (int sourceIdentifier, int destinationIdentifier); }; } //crdtsim #endif // NETWORK_H_INCLUDED diff --git a/Source/crdtsimNetworkComponent.cpp b/Source/crdtsimNetworkComponent.cpp new file mode 100644 index 0000000..8f40b53 --- /dev/null +++ b/Source/crdtsimNetworkComponent.cpp @@ -0,0 +1,82 @@ +#include "crdtsimNetworkComponent.h" + +using namespace crdtsim; + +class NodesMultiDocumentPanelWindow : public MultiDocumentPanelWindow +{ +public: + NodesMultiDocumentPanelWindow (Colour backgroundColour) : MultiDocumentPanelWindow (backgroundColour) + { + setTitleBarButtonsRequired (DocumentWindow::closeButton, true); + } +}; + +NetworkComponent::NetworkComponent () +{ + useFullscreenWhenOneDocument (false); + setLayoutMode (LayoutMode::FloatingWindows); +} +bool NetworkComponent::tryToCloseDocument (juce::Component* component) +{ + //TODO +} +void NetworkComponent::setNodesValueTree (juce::ValueTree newValueTree) +{ + nodesValueTree = newValueTree; + nodesValueTree.addListener (this); +} +void NetworkComponent::setConnexionsValueTree (juce::ValueTree newValueTree) +{ + connexionsValueTree = newValueTree; + connexionsValueTree.addListener (this); +} +void NetworkComponent::valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const Identifier& property) +{ + //TODO +} +void NetworkComponent::valueTreeChildAdded (ValueTree& parentTree, ValueTree& childWhichHasBeenAdded) +{ + if (parentTree == nodesValueTree) + { + auto identifier = childWhichHasBeenAdded.getType (); + auto newNote = new juce::TextButton{}; + newNote->setButtonText (identifier.toString ()); + newNote->setSize (100, 100); + addDocument (newNote, Colours::lightblue.withAlpha (0.6f), true); + } + else if (parentTree == connexionsValueTree) + { + //TODO + } + else + { + jassertfalse; + } +} +void NetworkComponent::valueTreeChildRemoved (ValueTree& parentTree, ValueTree& childWhichHasBeenRemoved, int /*indexFromWhichChildWasRemoved*/) +{ + if (parentTree == nodesValueTree) + { + //TODO + } + else if (parentTree == connexionsValueTree) + { + //TODO + } + else + { + jassertfalse; + } +} +void NetworkComponent::valueTreeChildOrderChanged (ValueTree& parentTreeWhoseChildrenHaveMoved, int oldIndex, int newIndex) +{ + //TODO +} +void NetworkComponent::valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) +{ + //TODO +} +MultiDocumentPanelWindow* NetworkComponent::createNewDocumentWindow () +{ + return new NodesMultiDocumentPanelWindow (getBackgroundColour ()); +} diff --git a/Source/crdtsimNetworkComponent.h b/Source/crdtsimNetworkComponent.h new file mode 100644 index 0000000..0af8768 --- /dev/null +++ b/Source/crdtsimNetworkComponent.h @@ -0,0 +1,26 @@ +#ifndef CRDTSIMNETWORKCOMPONENT_H_INCLUDED +#define CRDTSIMNETWORKCOMPONENT_H_INCLUDED + +#include "JuceHeader.h" +namespace crdtsim +{ +class NetworkComponent : public juce::MultiDocumentPanel, + public juce::ValueTree::Listener +{ +public: + NetworkComponent (); + bool tryToCloseDocument (juce::Component* component) override; + void setNodesValueTree (juce::ValueTree newValueTree); + void setConnexionsValueTree (juce::ValueTree newValueTree); + void valueTreePropertyChanged (ValueTree& treeWhosePropertyHasChanged, const Identifier& property) override; + void valueTreeChildAdded (ValueTree& parentTree, ValueTree& childWhichHasBeenAdded) override; + void valueTreeChildRemoved (ValueTree& parentTree, ValueTree& childWhichHasBeenRemoved, int indexFromWhichChildWasRemoved) override; + void valueTreeChildOrderChanged (ValueTree& parentTreeWhoseChildrenHaveMoved, int oldIndex, int newIndex) override; + void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) override; + MultiDocumentPanelWindow* createNewDocumentWindow () override; + +private: + juce::ValueTree nodesValueTree, connexionsValueTree; +}; +} //namespace crdtsim +#endif // CRDTSIMNETWORKCOMPONENT_H_INCLUDED