00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 module dcouple.signal;
00029
00030 private import dcouple.slot;
00031 private import dcouple.signalslot;
00032
00033
00034
00035 interface SignalManager
00036 {
00037
00038
00039
00040
00041
00042
00043
00044 void register(GenericSignal);
00045 void deregister(GenericSignal);
00046 public:
00047 bool signalsBlocked();
00048 bool signalsBlocked(bool block);
00049 }
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 template SignalManagement()
00060 {
00061
00062
00063
00064
00065
00066 protected:
00067
00068 void register(GenericSignal s)
00069 {
00070
00071 int len = _signals.length;
00072 int n = len-1;
00073 while (n >= 0 && _signals[n] is null)
00074 --n;
00075 if (n < len-1)
00076 _signals[n+1] = s;
00077 else
00078 _signals ~= s;
00079 }
00080
00081 void deregister(GenericSignal s)
00082 {
00083
00084 if (_signals.length == 0) return;
00085 bool found = false;
00086 int n;
00087 for (n=0 ; n < _signals.length-1; ++n) {
00088 if (!found && _signals[n] is s) found = true;
00089 if (found) _signals[n] = _signals[n+1];
00090 if (_signals[n] is null) break;
00091 }
00092 if (found || _signals[length-1] is s)
00093 _signals[length-1] = null;
00094 }
00095
00096 public:
00097
00098
00099
00100
00101
00102
00103 bool signalsBlocked() { return _signalsBlocked; }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 bool signalsBlocked(bool block) { return _signalsBlocked = block; }
00116
00117 protected:
00118 GenericSignal[] _signals;
00119 void deleteSignals()
00120 {
00121 debug printf("SignalManager::deleteSignals entered.\n_signals:\n");
00122 debug foreach(GenericSignal s; _signals) printf("signal %p.\n",s);
00123 foreach(GenericSignal s; _signals) {
00124 if (s is null) break;
00125
00126 s.freeFrom(this);
00127 debug printf("SignalManager::deleteSignals: deleting %p.\n", s);
00128 delete s;
00129 pragma(msg, "_signals contains dangling references. OK?");
00130 }
00131 }
00132 private:
00133 bool _signalsBlocked = false;
00134 }
00135
00136
00137
00138
00139 interface GenericSignal
00140
00141 {
00142
00143
00144
00145 void disconnect();
00146 SignalManager owner();
00147
00148 pragma(msg, "Want access specifier here.");
00149 void genericConnect(GenericSlot);
00150 void genericDisconnect(GenericSlot);
00151
00152 uint numberOfArguments();
00153 char[][] arguments();
00154
00155 void freeFrom(SignalManager);
00156 }
00157
00158
00159
00160 private template SignalGenericCore() {
00161
00162
00163
00164
00165
00166
00167 this(SignalManager owner=null)
00168 {
00169 _owner = owner;
00170 if (owner) owner.register(this);
00171 initArguments();
00172 }
00173
00174
00175
00176
00177
00178
00179 ~this()
00180 {
00181 disconnect();
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 if(_owner) _owner.deregister(this);
00192 }
00193
00194
00195
00196
00197 void connect(CompatibleSlot s)
00198 {
00199 debug printf("Signal::connect entered.\n");
00200 connectToo(s);
00201 s.connectToo(this);
00202 }
00203
00204 package void connectToo(CompatibleSlot s)
00205 {
00206 debug printf("Signal::connectToo entered.\n");
00207 debug printf("_slots before:\n");
00208 debug foreach( CompatibleSlot s; _slots ) printf( "slot %p\n", s);
00209
00210
00211 int len = _slots.length;
00212 int n = len-1;
00213 while (n >= 0 && _slots[n] is null)
00214 --n;
00215 if (n < len-1)
00216 _slots[n+1] = s;
00217 else
00218 _slots ~= s;
00219 debug printf("_slots after:\n");
00220 debug foreach( CompatibleSlot s; _slots ) printf( "slot %p\n", s);
00221 }
00222
00223 void genericConnect(GenericSlot gs)
00224 {
00225 debug printf( "Signal::genericConnect entered.\n");
00226 CompatibleSlot s = cast(CompatibleSlot) gs;
00227 if( s )
00228 connect(s);
00229 else {
00230 if (_owner)
00231 printf("dcouple WARNING: %.*s.%.*s!(",
00232 _owner.classinfo.name, this.classinfo.name);
00233 else
00234 printf("dcouple WARNING: %.*s!(", this.classinfo.name);
00235 if(numberOfArguments()>0)
00236 printf("%.*s",arguments()[0]);
00237 for(int i=1; i<numberOfArguments();i++)
00238 printf(",%.*s",arguments()[i]);
00239 if (gs.owner())
00240 printf(") is incompatible with %.*s.%.*s!(",
00241 gs.owner().classinfo.name, gs.classinfo.name);
00242 else
00243 printf(") is incompatible with %.*s!(", gs.classinfo.name);
00244 if(gs.numberOfArguments()>0)
00245 printf("%.*s",gs.arguments()[0]);
00246 for(int i=1; i<gs.numberOfArguments();i++)
00247 printf(",%.*s",gs.arguments()[i]);
00248 printf("); not connected. (Sorry, no line number...)\n");
00249 }
00250 }
00251
00252
00253
00254
00255 void disconnect(CompatibleSlot s)
00256 {
00257 debug printf("signal::disconnect entered.\n");
00258 if (disconnectToo(s))
00259 s.disconnectToo(this);
00260 }
00261 package bool disconnectToo(CompatibleSlot s)
00262 {
00263 debug printf("_slots before:\n");
00264 debug foreach( CompatibleSlot s; _slots ) printf( "slot %p\n", s);
00265
00266 debug printf("signal::disconnectToo: signal %p disconnecting from slot %p.\n", this, s);
00267 if (_slots.length == 0) return false;
00268 bool found = false;
00269 for (int n=0 ; n < _slots.length-1; ++n) {
00270 if (!found && _slots[n] is s) found = true;
00271 if (found) _slots[n] = _slots[n+1];
00272 if (_slots[n] is null) break;
00273 }
00274 if (found || _slots[length-1] is s)
00275 _slots[length-1] = null;
00276
00277 debug printf("_slots after:\n");
00278 debug foreach( CompatibleSlot s; _slots ) printf( "slot %p\n", s);
00279
00280 return found;
00281 }
00282
00283 void genericDisconnect(GenericSlot gs)
00284 {
00285 debug printf("signal::genericDisconnect entered.\n");
00286 CompatibleSlot s = cast(CompatibleSlot) gs;
00287 if( s )
00288 disconnect(s);
00289 else {
00290 if (_owner)
00291 printf("dcouple WARNING: %.*s.%.*s!(",
00292 _owner.classinfo.name, this.classinfo.name);
00293 else
00294 printf("dcouple WARNING: %.*s!(", this.classinfo.name);
00295 if(numberOfArguments()>0)
00296 printf("%.*s",arguments()[0]);
00297 for(int i=1; i<numberOfArguments();i++)
00298 printf(",%.*s",arguments()[i]);
00299 if (gs.owner())
00300 printf(") is incompatible with %.*s.%.*s!(",
00301 gs.owner().classinfo.name, gs.classinfo.name);
00302 else
00303 printf(") is incompatible with %.*s!(", gs.classinfo.name);
00304 if(gs.numberOfArguments()>0)
00305 printf("%.*s",gs.arguments()[0]);
00306 for(int i=1; i<gs.numberOfArguments();i++)
00307 printf(",%.*s",gs.arguments()[i]);
00308 printf("); not disconnected. (Sorry, no line number...)\n");
00309 }
00310 }
00311
00312
00313
00314 void disconnect()
00315 {
00316
00317
00318
00319
00320
00321
00322 for( int i=_slots.length-1; i>= 0; i-- ) {
00323 if( _slots[i] !is null ) disconnect(_slots[i]);
00324 }
00325 }
00326
00327
00328 int count()
00329 {
00330 return _slots.length;
00331 }
00332
00333 uint numberOfArguments()
00334 {
00335 return _arguments.length;
00336 }
00337
00338 char[][] arguments()
00339 {
00340 return _arguments;
00341 }
00342
00343 SignalManager owner()
00344 {
00345 return _owner;
00346 }
00347
00348 void freeFrom(SignalManager owner)
00349 {
00350
00351 assert(owner is _owner);
00352 _owner = null;
00353
00354 }
00355
00356 protected:
00357
00358 SignalManager _owner;
00359
00360 CompatibleSlot[] _slots;
00361 char[][] _arguments;
00362 }
00363
00364
00365
00366
00367
00368
00369 class Signal() : GenericSignal
00370 {
00371 alias Slot!() CompatibleSlot;
00372 mixin SignalGenericCore;
00373
00374
00375
00376
00377
00378
00379
00380 void emit()
00381 {
00382 debug printf("Signal!() emit() entered.\n");
00383 debug printf("_slots:\n");
00384 debug foreach(CompatibleSlot s; _slots) printf("slot %p\n", s);
00385 if (_owner && _owner.signalsBlocked())
00386 return;
00387 foreach( CompatibleSlot s; _slots ) {
00388 if (s is null) break;
00389 debug printf("emitting on %p\n", s);
00390 s();
00391 }
00392 }
00393
00394 void initArguments() {}
00395 }
00396
00397 class Signal(T1) : GenericSignal
00398 {
00399 alias Slot!(T1) CompatibleSlot;
00400 mixin SignalGenericCore;
00401
00402
00403 void emit(T1 t1)
00404 {
00405 if (_owner && _owner.signalsBlocked()) return;
00406 foreach( CompatibleSlot s; _slots ) {
00407 if (s is null) break;
00408 s(t1);
00409 }
00410 }
00411
00412 void initArguments()
00413 {
00414 _arguments ~= typeid(T1).toString();
00415 }
00416 }
00417
00418 class Signal(T1,T2) : GenericSignal
00419 {
00420 alias Slot!(T1,T2) CompatibleSlot;
00421 mixin SignalGenericCore;
00422
00423
00424 void emit(T1 t1, T2 t2)
00425 {
00426 if (_owner && _owner.signalsBlocked()) return;
00427 foreach( CompatibleSlot s; _slots ) {
00428 if (s is null) break;
00429 s(t1, t2);
00430 }
00431 }
00432
00433 void initArguments()
00434 {
00435 _arguments ~= typeid(T1).toString();
00436 _arguments ~= typeid(T2).toString();
00437 }
00438 }
00439
00440 class Signal(T1,T2,T3) : GenericSignal
00441 {
00442 alias Slot!(T1,T2,T3) CompatibleSlot;
00443 mixin SignalGenericCore;
00444
00445
00446 void emit(T1 t1, T2 t2, T3 t3)
00447 {
00448 if (_owner && _owner.signalsBlocked()) return;
00449 foreach( CompatibleSlot s; _slots ) {
00450 if (s is null) break;
00451 s(t1, t2, t3);
00452 }
00453 }
00454
00455 void initArguments()
00456 {
00457 _arguments ~= typeid(T1).toString();
00458 _arguments ~= typeid(T2).toString();
00459 _arguments ~= typeid(T3).toString();
00460 }
00461 }
00462
00463 class Signal(T1,T2,T3,T4) : GenericSignal
00464 {
00465 alias Slot!(T1,T2,T3,T4) CompatibleSlot;
00466 mixin SignalGenericCore;
00467
00468
00469 void emit(T1 t1, T2 t2, T3 t3, T4 t4)
00470 {
00471 if (_owner && _owner.signalsBlocked()) return;
00472 foreach( CompatibleSlot s; _slots ) {
00473 if (s is null) break;
00474 s(t1, t2, t3, t4);
00475 }
00476 }
00477
00478 void initArguments()
00479 {
00480 _arguments ~= typeid(T1).toString();
00481 _arguments ~= typeid(T2).toString();
00482 _arguments ~= typeid(T3).toString();
00483 _arguments ~= typeid(T4).toString();
00484 }
00485 }
00486
00487 class Signal(T1,T2,T3,T4,T5) : GenericSignal
00488 {
00489 alias Slot!(T1,T2,T3,T4,T5) CompatibleSlot;
00490 mixin SignalGenericCore;
00491
00492
00493 void emit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
00494 {
00495 if (_owner && _owner.signalsBlocked()) return;
00496 foreach( CompatibleSlot s; _slots ) {
00497 if (s is null) break;
00498 s(t1, t2, t3, t4, t5);
00499 }
00500 }
00501
00502 void initArguments()
00503 {
00504 _arguments ~= typeid(T1).toString();
00505 _arguments ~= typeid(T2).toString();
00506 _arguments ~= typeid(T3).toString();
00507 _arguments ~= typeid(T4).toString();
00508 _arguments ~= typeid(T5).toString();
00509 }
00510 }
00511
00512 class Signal(T1,T2,T3,T4,T5,T6) : GenericSignal
00513 {
00514 alias Slot!(T1,T2,T3,T4,T5,T6) CompatibleSlot;
00515 mixin SignalGenericCore;
00516
00517
00518 void emit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
00519 {
00520 if (_owner && _owner.signalsBlocked()) return;
00521 foreach( CompatibleSlot s; _slots ) {
00522 if (s is null) break;
00523 s(t1, t2, t3, t4, t5, t6);
00524 }
00525 }
00526
00527 void initArguments()
00528 {
00529 _arguments ~= typeid(T1).toString();
00530 _arguments ~= typeid(T2).toString();
00531 _arguments ~= typeid(T3).toString();
00532 _arguments ~= typeid(T4).toString();
00533 _arguments ~= typeid(T5).toString();
00534 _arguments ~= typeid(T6).toString();
00535 }
00536 }
00537
00538 class Signal(T1,T2,T3,T4,T5,T6,T7) : GenericSignal
00539 {
00540 alias Slot!(T1,T2,T3,T4,T5,T6,T7) CompatibleSlot;
00541 mixin SignalGenericCore;
00542
00543
00544 void emit(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
00545 {
00546 if (_owner && _owner.signalsBlocked()) return;
00547 foreach( CompatibleSlot s; _slots ) {
00548 if (s is null) break;
00549 s(t1, t2, t3, t4, t5, t6, t7);
00550 }
00551 }
00552
00553 void initArguments()
00554 {
00555 _arguments ~= typeid(T1).toString();
00556 _arguments ~= typeid(T2).toString();
00557 _arguments ~= typeid(T3).toString();
00558 _arguments ~= typeid(T4).toString();
00559 _arguments ~= typeid(T5).toString();
00560 _arguments ~= typeid(T6).toString();
00561 _arguments ~= typeid(T7).toString();
00562 }
00563 }
00564