1 /**
2  * Defines template mixins for defining properties in classes.
3  * 
4  * Authors: Colden Cullen, ColdenCullen@gmail.com
5  */
6 module core.properties;
7 
8 public:
9 /**
10  * Create a property.
11  * Params:
12  * 		type = 			The type of the object.
13  * 		name =			The name of the property.
14  * 		setterAccess =	[private] The access modifier of the setter.
15  * 		checkExpr =		[true] The expression to evaluate when setting the property.
16  */
17 mixin template Property( string type, string name, string setterAccess = "private", string checkExpr = "true" )
18 {
19 	mixin( Field!( type, name ) );
20 	mixin( Getter!( type, name ) );
21 	mixin( Setter!( setterAccess, type, name, checkExpr ) );
22 }
23 
24 /**
25  * Create a property backed by a field.
26  * Params:
27  * 		type = 			The type of the object.
28  * 		field =			The name of the field backing the property
29  * 		name =			The name of the property.
30  * 		setterAccess =	[private] The access modifier of the setter.
31  * 		checkExpr =		[true] The expression to evaluate when setting the property.
32  */
33 mixin template BackedProperty( string type, string field, string name, string setterAccess = "private", string checkExpr = "true" )
34 {
35 	mixin( Getter!( type, name, field ) );
36 	mixin( Setter!( setterAccess, type, name, checkExpr, field ) );
37 }
38 
39 /**
40  * Create a property that emits when set.
41  * Params:
42  * 		type = 			The type of the object.
43  * 		name =			The name of the property.
44  * 		setterAccess =	[private] The access modifier of the setter.
45  * 		checkExpr =		[true] The expression to evaluate when setting the property.
46  */
47 mixin template EmmittingProperty( string type, string name, string setterAccess = "private", string checkExpr = "true" )
48 {
49 	mixin( Field!( type, name ) );
50 	mixin( Getter!( type, name ) );
51 	mixin( EmmittingSetter!( setterAccess, type, name, checkExpr ) );
52 }
53 
54 /**
55  * Create a property backed by a field that emits when set.
56  * Params:
57  * 		type = 			The type of the object.
58  * 		field =			The name of the field backing the property.
59  * 		name =			The name of the property.
60  * 		setterAccess =	[private] The access modifier of the setter.
61  * 		checkExpr =		[true] The expression to evaluate when setting the property.
62  */
63 mixin template EmmittingBackedProperty( string type, string field, string name, string setterAccess = "private", string checkExpr = "true" )
64 {
65 	mixin( Getter!( type, name, field ) );
66 	mixin( EmmittingSetter!( setterAccess, type, name, checkExpr, field ) );
67 }
68 
69 /**
70  * Create a property that can be marked as dirty.
71  * Params:
72  * 		type = 			The type of the object.
73  * 		name =			The name of the property.
74  * 		updateFunc =	The name of the function to call when the property is dirty.
75  * 		setterAccess =	[private] The access modifier of the setter.
76  * 		checkExpr =		[true] The expression to evaluate when setting the property.
77  */
78 mixin template DirtyProperty( string type, string name, string updateFunc, string setterAccess = "private", string checkExpr = "true" )
79 {
80 	mixin( Field!( type, name ) );
81 	mixin( IsDirtyField!name );
82 	mixin( DirtyGetter!( type, name, updateFunc ) );
83 	mixin( Setter!( setterAccess, type, name, checkExpr ) );
84 }
85 
86 /**
87  * Create a property that is backed by a field, and can be marked as dirty.
88  * Params:
89  * 		type = 			The type of the object.
90  *		field =			The name of the field backing the property.
91  * 		name =			The name of the property.
92  * 		updateFunc =	The name of the function to call when the property is dirty.
93  * 		setterAccess =	[private] The access modifier of the setter.
94  * 		checkExpr =		[true] The expression to evaluate when setting the property.
95  */
96 mixin template BackedDirtyProperty( string type, string field, string name, string updateFunc, string setterAccess = "private", string checkExpr = "true" )
97 {
98 	mixin( IsDirtyField!name );
99 	mixin( DirtyGetter!( type, name, updateFunc, field ) );
100 	mixin( Setter!( setterAccess, type, name, checkExpr, field ) );
101 }
102 
103 /**
104  * Create a property that can be marked as dirty, and emits when set.
105  * Params:
106  * 		type = 			The type of the object.
107  * 		name =			The name of the property.
108  * 		updateFunc =	The name of the function to call when the property is dirty.
109  * 		setterAccess =	[private] The access modifier of the setter.
110  * 		checkExpr =		[true] The expression to evaluate when setting the property.
111  */
112 mixin template EmmittingDirtyProperty( string type, string name, string updateFunc, string setterAccess = "private", string checkExpr = "true" )
113 {
114 	mixin( Field!( type, name ) );
115 	mixin( IsDirtyField!name );
116 	mixin( DirtyGetter!( type, name, updateFunc ) );
117 	mixin( EmmittingSetter!( setterAccess, type, name, checkExpr ) );
118 }
119 
120 /**
121  * Create a property that is backed by a field, can be marked as dirty, and emits when set.
122  * Params:
123  * 		type = 			The type of the object.
124  * 		field =			The name of the field backing the property.
125  * 		name =			The name of the property.
126  * 		updateFunc =	The name of the function to call when the property is dirty.
127  * 		setterAccess =	[private] The access modifier of the setter.
128  * 		checkExpr =		[true] The expression to evaluate when setting the property.
129  */
130 mixin template BackedEmmittingDirtyProperty( string type, string field, string name, string updateFunc, string setterAccess = "private", string checkExpr = "true" )
131 {
132 	mixin( IsDirtyField!name );
133 	mixin( DirtyGetter!( type, name, updateFunc, field ) );
134 	mixin( EmmittingSetter!( setterAccess, type, name, checkExpr, field ) );
135 }
136 
137 /**
138  * Create a property that marks another property as dirty when set.
139  * Params:
140  * 		type = 			The type of the object.
141  * 		name =			The name of the property.
142  * 		dirtyProp =		Name of the property to mark dirty.
143  * 		setterAccess =	[private] The access modifier of the setter.
144  * 		checkExpr =		[true] The expression to evaluate when setting the property.
145  */
146 mixin template PropertySetDirty( string type, string name, string dirtyProp, string setterAccess = "private", string checkExpr = "true" )
147 {
148 	mixin( Field!( type, name ) );
149 	mixin( Getter!( type, name ) );
150 	mixin( DirtySetter!( setterAccess, type, name, dirtyField, setCond ) );
151 }
152 
153 /**
154  * Create a property that marks another property as dirty when set, and emits when set.
155  * Params:
156  * 		type = 			The type of the object.
157  * 		name =			The name of the property.
158  * 		dirtyProp =		Name of the property to mark dirty.
159  * 		setterAccess =	[private] The access modifier of the setter.
160  * 		checkExpr =		[true] The expression to evaluate when setting the property.
161  */
162 mixin template EmmittingPropertySetDirty( string type, string name, string dirtyProp, string setterAccess = "private", string checkExpr = "true" )
163 {
164 	mixin( Field!( type, name ) );
165 	mixin( Getter!( type, name ) );
166 	mixin( EmmittingDirtySetter!( setterAccess, type, name, dirtyProp, checkExpr ) );
167 }
168 
169 /**
170  * Create a property that marks another property as dirty when set, and is backed by a field.
171  * Params:
172  * 		type = 			The type of the object.
173  * 		field =			The name of the field backing the property.
174  * 		name =			The name of the property.
175  * 		dirtyProp =		Name of the property to mark dirty.
176  * 		setterAccess =	[private] The access modifier of the setter.
177  * 		checkExpr =		[true] The expression to evaluate when setting the property.
178  */
179 mixin template BackedPropertySetDirty( string type, string field, string name, string dirtyProp, string setterAccess = "private", string checkExpr = "true" )
180 {
181 	mixin( Getter!( type, name, field ) );
182 	mixin( DirtySetter!( setterAccess, type, name, dirtyField, checkExpr, field ) );
183 }
184 
185 /**
186  * Create a property that is backed by a field, emits when set, and marks another property as dirty when set.
187  * Params:
188  * 		type = 			The type of the object.
189  * 		field =			The name of the field backing the property.
190  * 		name =			The name of the property.
191  * 		dirtyProp =		Name of the property to mark dirty.
192  * 		setterAccess =	[private] The access modifier of the setter.
193  * 		checkExpr =		[true] The expression to evaluate when setting the property.
194  */
195 mixin template BackedEmmittingPropertySetDirty( string type, string field, string name, string dirtyProp, string setterAccess = "private", string checkExpr = "true" )
196 {
197 	mixin( Getter!( type, name, field ) );
198 	mixin( EmmittingDirtySetter!( setterAccess, type, name, dirtyField, checkExpr, field ) );
199 }
200 
201 //private:
202 template FieldName( string name, string field = "" )
203 {
204 	immutable char[] FieldName = field.length ? field : "_" ~ name;
205 }
206 template Field( string type, string name )
207 {
208 	immutable char[] Field = "private " ~ type ~ " " ~ FieldName!name ~ ";";
209 }
210 
211 template DirtyFieldName( string name )
212 {
213 	immutable char[] DirtyFieldName = FieldName!name ~ "IsDirty";
214 }
215 template IsDirtyField( string name )
216 {
217 	immutable char[] IsDirtyField = "public bool " ~ DirtyFieldName!name ~ " = false;";
218 }
219 
220 template Getter( string type, string name, string fieldName = "" )
221 {
222 	immutable char[] Getter =
223 		"public @property " ~ type ~ " " ~ name ~ "(){" ~
224 		"return " ~ FieldName!( name, fieldName ) ~ "; }";
225 }
226 template DirtyGetter( string type, string name, string dirtyUpdateFunc, string fieldName = "" )
227 {
228 	immutable char[] DirtyGetter = 
229 		"public @property " ~ type ~ " " ~ name ~ "() {" ~
230 		"if( " ~ DirtyFieldName!name ~ " ) {" ~ dirtyUpdateFunc ~ "();" ~
231 		DirtyFieldName!name ~ " = false; }" ~
232 		"return " ~ FieldName!( name, fieldName ) ~ "; }";
233 }
234 
235 template SetterHeader( string access, string type, string name )
236 {
237 	immutable char[] SetterHeader = access ~ " @property void " ~ name ~ "( " ~ type ~ " _newVal ) {";
238 }
239 template SetterAssignment( string name, string fieldName = "" )
240 {
241 	immutable char[] SetterAssignment = FieldName!( name, fieldName ) ~ " = _newVal;";
242 }
243 template SetterCond( string setCond, string name, string fieldName )
244 {
245 	immutable char[] SetterCond = setCond ~ " && _newVal != " ~ FieldName!( name, fieldName );
246 }
247 template SetterEmit( string name )
248 {
249 	immutable char[] SetterEmit = "emit( \"" ~ name ~ "\", to!string( _newVal ) );";
250 }
251 template Setter( string access, string type, string name, string setCond, string fieldName = "" )
252 {
253 	immutable char[] Setter =
254 		SetterHeader!( access, type, name ) ~
255 		"if( " ~ SetterCond!( setCond, name, fieldName ) ~ " ) { " ~
256 		SetterAssignment!( name, fieldName ) ~ " } }";
257 }
258 template EmmittingSetter( string access, string type, string name, string setCond, string fieldName = "" )
259 {
260 	immutable char[] EmmittingSetter =
261 		SetterHeader!( access, type, name ) ~
262 		"if( " ~ SetterCond!( setCond, name, fieldName ) ~ " ) { " ~
263 		SetterAssignment!( name, fieldName ) ~
264 		SetterEmit!name ~ " } }";
265 }
266 template DirtySetter( string access, string type, string name, string dirtyField, string setCond, string fieldName = "" )
267 {
268 	immutable char[] DirtySetter =
269 		SetterHeader!( access, type, name ) ~
270 		"if( " ~ SetterCond!( setCond, name, fieldName ) ~ " ) { " ~
271 		SetterAssignment!( name, fieldName ) ~
272 		DirtyFieldName!dirtyField ~ " = true; } }";
273 }
274 template EmmittingDirtySetter( string access, string type, string name, string dirtyField, string setCond, string fieldName = "" )
275 {
276 	immutable char[] EmmittingDirtySetter =
277 		SetterHeader!( access, type, name ) ~
278 		"if( " ~ SetterCond!( setCond, name, fieldName ) ~ " ) { " ~
279 		SetterAssignment!( name, fieldName ) ~
280 		SetterEmit!name ~
281 		DirtyFieldName!dirtyField ~ " = true; } }";
282 }