fsm.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /**
  2. * @fileOverview
  3. *
  4. * 编辑器状态机
  5. *
  6. * @author: techird
  7. * @copyright: Baidu FEX, 2014
  8. */
  9. define(function(require, exports, module) {
  10. var Debug = require('../tool/debug');
  11. var debug = new Debug('fsm');
  12. function handlerConditionMatch(condition, when, exit, enter) {
  13. if (condition.when != when) return false;
  14. if (condition.enter != '*' && condition.enter != enter) return false;
  15. if (condition.exit != '*' && condition.exit != exit) return;
  16. return true;
  17. }
  18. function FSM(defaultState) {
  19. var currentState = defaultState;
  20. var BEFORE_ARROW = ' - ';
  21. var AFTER_ARROW = ' -> ';
  22. var handlers = [];
  23. /**
  24. * 状态跳转
  25. *
  26. * 会通知所有的状态跳转监视器
  27. *
  28. * @param {string} newState 新状态名称
  29. * @param {any} reason 跳转的原因,可以作为参数传递给跳转监视器
  30. */
  31. this.jump = function(newState, reason) {
  32. if (!reason) throw new Error('Please tell fsm the reason to jump');
  33. var oldState = currentState;
  34. var notify = [oldState, newState].concat([].slice.call(arguments, 1));
  35. var i, handler;
  36. // 跳转前
  37. for (i = 0; i < handlers.length; i++) {
  38. handler = handlers[i];
  39. if (handlerConditionMatch(handler.condition, 'before', oldState, newState)) {
  40. if (handler.apply(null, notify)) return;
  41. }
  42. }
  43. currentState = newState;
  44. debug.log('[{0}] {1} -> {2}', reason, oldState, newState);
  45. // 跳转后
  46. for (i = 0; i < handlers.length; i++) {
  47. handler = handlers[i];
  48. if (handlerConditionMatch(handler.condition, 'after', oldState, newState)) {
  49. handler.apply(null, notify);
  50. }
  51. }
  52. return currentState;
  53. };
  54. /**
  55. * 返回当前状态
  56. * @return {string}
  57. */
  58. this.state = function() {
  59. return currentState;
  60. };
  61. /**
  62. * 添加状态跳转监视器
  63. *
  64. * @param {string} condition
  65. * 监视的时机
  66. * "* => *" (默认)
  67. *
  68. * @param {Function} handler
  69. * 监视函数,当状态跳转的时候,会接收三个参数
  70. * * from - 跳转前的状态
  71. * * to - 跳转后的状态
  72. * * reason - 跳转的原因
  73. */
  74. this.when = function(condition, handler) {
  75. if (arguments.length == 1) {
  76. handler = condition;
  77. condition = '* -> *';
  78. }
  79. var when, resolved, exit, enter;
  80. resolved = condition.split(BEFORE_ARROW);
  81. if (resolved.length == 2) {
  82. when = 'before';
  83. } else {
  84. resolved = condition.split(AFTER_ARROW);
  85. if (resolved.length == 2) {
  86. when = 'after';
  87. }
  88. }
  89. if (!when) throw new Error('Illegal fsm condition: ' + condition);
  90. exit = resolved[0];
  91. enter = resolved[1];
  92. handler.condition = {
  93. when: when,
  94. exit: exit,
  95. enter: enter
  96. };
  97. handlers.push(handler);
  98. };
  99. }
  100. function FSMRumtime() {
  101. this.fsm = new FSM('normal');
  102. }
  103. return module.exports = FSMRumtime;
  104. });