-
Notifications
You must be signed in to change notification settings - Fork 47
/
EditableDeclaration.h
84 lines (73 loc) · 2.97 KB
/
EditableDeclaration.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#pragma once
#include "DeclarationBase.h"
namespace decl
{
/**
* Declaration class used by all types that can be changed after parsing
* through their public API (e.g. Particles or Materials).
*
* Implementing classes need to invoke onParsedContentsChanged() on any
* change of its contents.The attached syntax block will be marked as
* outdated and calls to getSyntaxBlock() will trigger a refresh
* of the syntax block through the generateSyntaxBlock() override.
*
* Note that calling setSyntaxBlock() will clear the invalid status,
* the subsequent parseFromTokens() will very likely overwrite all changes.
* It's up to the client code to avoid these situations.
* On a related note, subclasses need to call ensureParsed() before altering
* its members, to avoid parseFromTokens() from undoing the changes.
*
* Example implementation of a public setter method:
*
* void YourDeclaration::setFloatValue(float value)
* {
* ensureParsed();
* _value = value;
* onParsedContentsChanged();
* }
*/
template<typename DeclarationInterface>
class EditableDeclaration :
public DeclarationBase<DeclarationInterface>
{
private:
// Is set to true once the contents of the declaration
// have been changed by the subclass (see onParsedContentsChanged).
// The assigned syntax block's contents are no longer up to date
// and will be regenerated before a call to getSyntaxBlock() returns.
bool _syntaxBlockInvalidated;
protected:
EditableDeclaration(decl::Type type, const std::string& name) :
DeclarationBase<DeclarationInterface>(type, name),
_syntaxBlockInvalidated(false)
{}
EditableDeclaration(const EditableDeclaration<DeclarationInterface>& other) = default;
public:
const DeclarationBlockSyntax& getBlockSyntax() override
{
// In case the contents have been invalidated, acquire the new source text
if (_syntaxBlockInvalidated)
{
_syntaxBlockInvalidated = false;
DeclarationBase<DeclarationInterface>::assignSyntaxBlockContents(generateSyntax());
}
return DeclarationBase<DeclarationInterface>::getBlockSyntax();
}
protected:
// Needs to be called by subclasses when members change and the
// syntax block (that has been used to parse them) is no longer valid
// The next time client code will acquire the syntax block, the subclass
// will be asked to provide it through the virtual generateSyntaxBlock()
void onParsedContentsChanged()
{
_syntaxBlockInvalidated = true;
// Emit the changed signal of the base
DeclarationBase<DeclarationInterface>::signal_DeclarationChanged().emit();
}
// Should generate a new syntax block based on the current state of the instance.
// Will be invoked by the EditableDeclaration base class when clients request
// the syntax using getSyntaxBlock() and the syntax has been invalidated by
// onParsedContentsChanged().
virtual std::string generateSyntax() = 0;
};
}