Added pimpl on DiffManager

This commit is contained in:
Michaël Lemaire 2016-01-18 23:06:50 +01:00
parent e869f5b9ca
commit fe24a0f48d
11 changed files with 85 additions and 60 deletions

View file

@ -149,7 +149,7 @@ void DefinitionNode::addWatcher(DefinitionWatcher *watcher, bool init_diff) {
} }
} }
int DefinitionNode::getWatcherCount() const { unsigned long DefinitionNode::getWatcherCount() const {
if (root && root->diffs) { if (root && root->diffs) {
return root->diffs->getWatcherCount(this); return root->diffs->getWatcherCount(this);
} else { } else {
@ -265,7 +265,8 @@ void DefinitionNode::addDiff(const DefinitionDiff *diff) {
if (root && root->diffs) { if (root && root->diffs) {
root->diffs->addDiff(this, diff); root->diffs->addDiff(this, diff);
} else { } else {
// TODO Apply diff ? // No diff manager available, apply it directly and delete it
applyDiff(diff);
delete diff; delete diff;
} }
} }

View file

@ -43,7 +43,7 @@ class DEFINITIONSHARED_EXPORT DefinitionNode {
inline DiffManager *getDiffManager() const { inline DiffManager *getDiffManager() const {
return diffs; return diffs;
} }
inline int getChildrenCount() const { inline unsigned long getChildrenCount() const {
return children.size(); return children.size();
} }
@ -94,7 +94,7 @@ class DEFINITIONSHARED_EXPORT DefinitionNode {
/** /**
* Get the current number of watchers. * Get the current number of watchers.
*/ */
int getWatcherCount() const; unsigned long getWatcherCount() const;
protected: protected:
void addChild(DefinitionNode *child); void addChild(DefinitionNode *child);

View file

@ -38,3 +38,7 @@ void DefinitionWatcher::startWatching(const DefinitionNode *root, const string &
Logs::warning("Definition") << "Node not found for watching : " << path << endl; Logs::warning("Definition") << "Node not found for watching : " << path << endl;
} }
} }
void DefinitionWatcher::startWatching(const DefinitionNode *node, bool init_diff) {
startWatching(node->getRoot(), node->getPath(), init_diff);
}

View file

@ -31,6 +31,13 @@ class DEFINITIONSHARED_EXPORT DefinitionWatcher {
*/ */
void startWatching(const DefinitionNode *root, const string &path, bool init_diff = true); void startWatching(const DefinitionNode *root, const string &path, bool init_diff = true);
/**
* Start watching a node.
*
* Overloaded for convenience.
*/
void startWatching(const DefinitionNode *node, bool init_diff = true);
/** /**
* Abstract convenience to receive integer node changes. * Abstract convenience to receive integer node changes.
*/ */

View file

@ -1,42 +1,59 @@
#include "DiffManager.h" #include "DiffManager.h"
#include <algorithm> #include <algorithm>
#include <memory> #include <map>
#include <vector>
#include "DefinitionNode.h" #include "DefinitionNode.h"
#include "DefinitionDiff.h" #include "DefinitionDiff.h"
#include "DefinitionWatcher.h" #include "DefinitionWatcher.h"
#include "Logs.h" #include "Logs.h"
DiffManager::DiffManager(DefinitionNode *tree) : tree(tree) { class DiffManager::pimpl {
undone = 0; public:
pimpl(DefinitionNode *tree) : tree(tree), undone(0) {
}
DefinitionNode *tree;
unsigned long undone;
vector<const DefinitionDiff *> diffs;
map<const DefinitionNode *, vector<DefinitionWatcher *>> watchers;
};
DiffManager::DiffManager(DefinitionNode *tree) : impl(new pimpl(tree)) {
} }
DiffManager::~DiffManager() { DiffManager::~DiffManager() {
for (auto diff : diffs) { // TODO smart pointers
for (auto diff : impl->diffs) {
delete diff; delete diff;
} }
diffs.clear(); impl->diffs.clear();
}
unsigned long DiffManager::getDiffCount(int include_undone) const {
return include_undone ? impl->diffs.size() : impl->diffs.size() - impl->undone;
} }
void DiffManager::addWatcher(const DefinitionNode *node, DefinitionWatcher *watcher) { void DiffManager::addWatcher(const DefinitionNode *node, DefinitionWatcher *watcher) {
if (find(watchers[node].begin(), watchers[node].end(), watcher) == watchers[node].end()) { auto &watchers = impl->watchers[node];
watchers[node].push_back(watcher); if (find(watchers.begin(), watchers.end(), watcher) == watchers.end()) {
watchers.push_back(watcher);
} }
} }
int DiffManager::getWatcherCount(const DefinitionNode *node) { unsigned long DiffManager::getWatcherCount(const DefinitionNode *node) {
return watchers[node].size(); return impl->watchers[node].size();
} }
void DiffManager::addDiff(DefinitionNode *node, const DefinitionDiff *diff) { void DiffManager::addDiff(DefinitionNode *node, const DefinitionDiff *diff) {
while (undone > 0) { while (impl->undone > 0) {
// truncate diffs ahead // truncate diffs ahead
delete diffs.back(); delete impl->diffs.back();
diffs.pop_back(); impl->diffs.pop_back();
undone--; impl->undone--;
} }
diffs.push_back(diff); impl->diffs.push_back(diff);
// TODO Delayed commit (with merge of consecutive diffs) // TODO Delayed commit (with merge of consecutive diffs)
@ -46,13 +63,13 @@ void DiffManager::addDiff(DefinitionNode *node, const DefinitionDiff *diff) {
} }
void DiffManager::undo() { void DiffManager::undo() {
if (undone < (int)diffs.size()) { if (impl->undone < impl->diffs.size()) {
const DefinitionDiff *diff = diffs[diffs.size() - undone - 1]; const DefinitionDiff *diff = impl->diffs[impl->diffs.size() - impl->undone - 1];
// Obtain the node by path and reverse apply diff on it // Obtain the node by path and reverse apply diff on it
DefinitionNode *node = tree->findByPath(diff->getPath()); DefinitionNode *node = impl->tree->findByPath(diff->getPath());
if (node) { if (node) {
undone++; impl->undone++;
unique_ptr<DefinitionDiff> reversed(diff->newReversed()); unique_ptr<DefinitionDiff> reversed(diff->newReversed());
@ -67,13 +84,13 @@ void DiffManager::undo() {
} }
void DiffManager::redo() { void DiffManager::redo() {
if (undone > 0) { if (impl->undone > 0) {
const DefinitionDiff *diff = diffs[diffs.size() - undone]; const DefinitionDiff *diff = impl->diffs[impl->diffs.size() - impl->undone];
// Obtain the node by path and re-apply diff on it // Obtain the node by path and re-apply diff on it
DefinitionNode *node = tree->findByPath(diff->getPath()); DefinitionNode *node = impl->tree->findByPath(diff->getPath());
if (node) { if (node) {
undone--; impl->undone--;
Logs::debug("Definition") << "Node redo : " << node->getPath() << endl; Logs::debug("Definition") << "Node redo : " << node->getPath() << endl;
node->applyDiff(diff); node->applyDiff(diff);
@ -88,7 +105,7 @@ void DiffManager::publishToWatchers(const DefinitionNode *node, const Definition
// TODO Parent node signaling should be aggregated (to not receive many nodeChanged calls) // TODO Parent node signaling should be aggregated (to not receive many nodeChanged calls)
const DefinitionNode *cnode = node; const DefinitionNode *cnode = node;
do { do {
for (auto watcher : watchers[cnode]) { for (auto watcher : impl->watchers[cnode]) {
watcher->nodeChanged(node, diff, cnode); watcher->nodeChanged(node, diff, cnode);
} }
cnode = cnode->getParent(); cnode = cnode->getParent();

View file

@ -3,8 +3,7 @@
#include "definition_global.h" #include "definition_global.h"
#include <map> #include <memory>
#include <vector>
namespace paysages { namespace paysages {
namespace definition { namespace definition {
@ -22,9 +21,7 @@ class DEFINITIONSHARED_EXPORT DiffManager {
/** /**
* Get the total number of diff stored. * Get the total number of diff stored.
*/ */
inline int getDiffCount(int include_undone = true) { unsigned long getDiffCount(int include_undone = true) const;
return include_undone ? diffs.size() : diffs.size() - undone;
}
/** /**
* Add a watcher for a specific node. * Add a watcher for a specific node.
@ -36,7 +33,7 @@ class DEFINITIONSHARED_EXPORT DiffManager {
/** /**
* Get the number of watchers registered for a given node. * Get the number of watchers registered for a given node.
*/ */
int getWatcherCount(const DefinitionNode *node); unsigned long getWatcherCount(const DefinitionNode *node);
/** /**
* Add a new diff of a node to the change flow. * Add a new diff of a node to the change flow.
@ -63,10 +60,8 @@ class DEFINITIONSHARED_EXPORT DiffManager {
void publishToWatchers(const DefinitionNode *node, const DefinitionDiff *diff); void publishToWatchers(const DefinitionNode *node, const DefinitionDiff *diff);
private: private:
DefinitionNode *tree; class pimpl;
int undone; unique_ptr<pimpl> impl;
vector<const DefinitionDiff *> diffs;
map<const DefinitionNode *, vector<DefinitionWatcher *>> watchers;
}; };
} }
} }

View file

@ -29,9 +29,9 @@ void VegetationDefinition::applyPreset(VegetationPreset preset, RandomGenerator
clear(); clear();
/*if (preset == VEGETATION_PRESET_TEMPERATE) { if (preset == VEGETATION_PRESET_TEMPERATE) {
layer.applyPreset(VegetationLayerDefinition::VEGETATION_BASIC_TREES, random); layer.applyPreset(VegetationLayerDefinition::VEGETATION_BASIC_TREES, random);
layer.setName("Basic tree"); layer.setName("Basic tree");
addLayer(layer); //addLayer(layer);
}*/ }
} }

View file

@ -118,7 +118,7 @@ void OpenGLVegetation::acquireLayers(vector<OpenGLVegetationLayer *> &layers) {
layers_lock->release(); layers_lock->release();
} }
void OpenGLVegetation::releaseLayers(const vector<OpenGLVegetationLayer *> &layers) { void OpenGLVegetation::releaseLayers(const vector<OpenGLVegetationLayer *> &) {
// TODO Reference count // TODO Reference count
} }

View file

@ -67,7 +67,8 @@ void OpenGLVegetationImpostor::render(OpenGLShaderProgram *program, const OpenGL
} }
void OpenGLVegetationImpostor::prepareTexture(const VegetationModelDefinition &model, const Scenery &environment, void OpenGLVegetationImpostor::prepareTexture(const VegetationModelDefinition &model, const Scenery &environment,
bool *interrupt) { bool *) {
// TODO interrupt
Scenery scenery; Scenery scenery;
environment.getAtmosphere()->copy(scenery.getAtmosphere()); environment.getAtmosphere()->copy(scenery.getAtmosphere());
SoftwareRenderer renderer(&scenery); SoftwareRenderer renderer(&scenery);

View file

@ -25,20 +25,20 @@ TEST(DefinitionNode, getPath) {
EXPECT_EQ("/branch/leaf", leaf.getPath()); EXPECT_EQ("/branch/leaf", leaf.getPath());
} }
class FakeWatcher : public DefinitionWatcher {
virtual void nodeChanged(const DefinitionNode *, const DefinitionDiff *, const DefinitionNode *) override {
}
};
TEST(DefinitionNode, addWatcher) { TEST(DefinitionNode, addWatcher) {
class FakeWatcher : public DefinitionWatcher {
virtual void nodeChanged(const DefinitionNode *, const DefinitionDiff *, const DefinitionNode *) override {
}
};
DefinitionNode root(NULL, "root"); DefinitionNode root(NULL, "root");
FakeWatcher watcher; FakeWatcher watcher;
EXPECT_EQ(0, root.getWatcherCount()); EXPECT_EQ(0u, root.getWatcherCount());
root.addWatcher(&watcher); root.addWatcher(&watcher);
EXPECT_EQ(1, root.getWatcherCount()); EXPECT_EQ(1u, root.getWatcherCount());
root.addWatcher(&watcher); root.addWatcher(&watcher);
EXPECT_EQ(1, root.getWatcherCount()); EXPECT_EQ(1u, root.getWatcherCount());
} }
TEST(DefinitionNode, findByPath) { TEST(DefinitionNode, findByPath) {
@ -65,15 +65,15 @@ TEST(DefinitionNode, attachDetach) {
EXPECT_EQ(root, child1->getParent()); EXPECT_EQ(root, child1->getParent());
EXPECT_EQ(root, child2->getParent()); EXPECT_EQ(root, child2->getParent());
EXPECT_EQ(2, root->getChildrenCount()); EXPECT_EQ(2u, root->getChildrenCount());
delete child1; delete child1;
EXPECT_EQ(1, root->getChildrenCount()); EXPECT_EQ(1u, root->getChildrenCount());
delete child2; delete child2;
EXPECT_EQ(0, root->getChildrenCount()); EXPECT_EQ(0u, root->getChildrenCount());
delete root; delete root;
} }

View file

@ -127,25 +127,25 @@ TEST(Layers, undoRedo) {
Layers layers(NULL, "layers", _construc3); Layers layers(NULL, "layers", _construc3);
EXPECT_EQ(0, layers.getLayerCount()); EXPECT_EQ(0, layers.getLayerCount());
EXPECT_EQ(0, layers.getDiffManager()->getDiffCount()); EXPECT_EQ(0u, layers.getDiffManager()->getDiffCount());
layers.addLayer("testlayer"); layers.addLayer("testlayer");
ASSERT_EQ(1, layers.getLayerCount()); ASSERT_EQ(1, layers.getLayerCount());
TestLayer *layer = (TestLayer *)layers.getLayer(0); auto layer = static_cast<TestLayer *>(layers.getLayer(0));
EXPECT_EQ(1, layers.getDiffManager()->getDiffCount()); EXPECT_EQ(1u, layers.getDiffManager()->getDiffCount());
checkLayerChild(layers, 0, "val", 5); checkLayerChild(layers, 0, "val", 5);
layer->val->setValue(8); layer->val->setValue(8);
EXPECT_EQ(2, layers.getDiffManager()->getDiffCount()); EXPECT_EQ(2u, layers.getDiffManager()->getDiffCount());
checkLayerChild(layers, 0, "val", 8); checkLayerChild(layers, 0, "val", 8);
layers.removeLayer(0); layers.removeLayer(0);
EXPECT_EQ(3, layers.getDiffManager()->getDiffCount()); EXPECT_EQ(3u, layers.getDiffManager()->getDiffCount());
EXPECT_EQ(0, layers.getLayerCount()); EXPECT_EQ(0, layers.getLayerCount());
// Start undoing // Start undoing
@ -156,7 +156,7 @@ TEST(Layers, undoRedo) {
layers.getDiffManager()->undo(); layers.getDiffManager()->undo();
EXPECT_EQ(0, layers.getLayerCount()); EXPECT_EQ(0, layers.getLayerCount());
EXPECT_EQ(3, layers.getDiffManager()->getDiffCount()); EXPECT_EQ(3u, layers.getDiffManager()->getDiffCount());
// Start redoing // Start redoing
layers.getDiffManager()->redo(); layers.getDiffManager()->redo();
@ -166,7 +166,7 @@ TEST(Layers, undoRedo) {
layers.getDiffManager()->redo(); layers.getDiffManager()->redo();
EXPECT_EQ(0, layers.getLayerCount()); EXPECT_EQ(0, layers.getLayerCount());
EXPECT_EQ(3, layers.getDiffManager()->getDiffCount()); EXPECT_EQ(3u, layers.getDiffManager()->getDiffCount());
// TODO Test swapping // TODO Test swapping
} }