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 }