| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- /**
- * @fileOverview
- *
- * 编辑器状态机
- *
- * @author: techird
- * @copyright: Baidu FEX, 2014
- */
- define(function(require, exports, module) {
- var Debug = require('../tool/debug');
- var debug = new Debug('fsm');
- function handlerConditionMatch(condition, when, exit, enter) {
- if (condition.when != when) return false;
- if (condition.enter != '*' && condition.enter != enter) return false;
- if (condition.exit != '*' && condition.exit != exit) return;
- return true;
- }
- function FSM(defaultState) {
- var currentState = defaultState;
- var BEFORE_ARROW = ' - ';
- var AFTER_ARROW = ' -> ';
- var handlers = [];
- /**
- * 状态跳转
- *
- * 会通知所有的状态跳转监视器
- *
- * @param {string} newState 新状态名称
- * @param {any} reason 跳转的原因,可以作为参数传递给跳转监视器
- */
- this.jump = function(newState, reason) {
- if (!reason) throw new Error('Please tell fsm the reason to jump');
- var oldState = currentState;
- var notify = [oldState, newState].concat([].slice.call(arguments, 1));
- var i, handler;
- // 跳转前
- for (i = 0; i < handlers.length; i++) {
- handler = handlers[i];
- if (handlerConditionMatch(handler.condition, 'before', oldState, newState)) {
- if (handler.apply(null, notify)) return;
- }
- }
- currentState = newState;
- debug.log('[{0}] {1} -> {2}', reason, oldState, newState);
- // 跳转后
- for (i = 0; i < handlers.length; i++) {
- handler = handlers[i];
- if (handlerConditionMatch(handler.condition, 'after', oldState, newState)) {
- handler.apply(null, notify);
- }
- }
- return currentState;
- };
- /**
- * 返回当前状态
- * @return {string}
- */
- this.state = function() {
- return currentState;
- };
- /**
- * 添加状态跳转监视器
- *
- * @param {string} condition
- * 监视的时机
- * "* => *" (默认)
- *
- * @param {Function} handler
- * 监视函数,当状态跳转的时候,会接收三个参数
- * * from - 跳转前的状态
- * * to - 跳转后的状态
- * * reason - 跳转的原因
- */
- this.when = function(condition, handler) {
- if (arguments.length == 1) {
- handler = condition;
- condition = '* -> *';
- }
- var when, resolved, exit, enter;
- resolved = condition.split(BEFORE_ARROW);
- if (resolved.length == 2) {
- when = 'before';
- } else {
- resolved = condition.split(AFTER_ARROW);
- if (resolved.length == 2) {
- when = 'after';
- }
- }
- if (!when) throw new Error('Illegal fsm condition: ' + condition);
- exit = resolved[0];
- enter = resolved[1];
- handler.condition = {
- when: when,
- exit: exit,
- enter: enter
- };
- handlers.push(handler);
- };
- }
- function FSMRumtime() {
- this.fsm = new FSM('normal');
- }
- return module.exports = FSMRumtime;
- });
|