You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by jb...@apache.org on 2010/06/30 04:08:05 UTC

svn commit: r959165 - in /commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop: drag-and-drop3.js drag-and-drop3.svg

Author: jbeard
Date: Wed Jun 30 02:08:05 2010
New Revision: 959165

URL: http://svn.apache.org/viewvc?rev=959165&view=rev
Log:
Created an SVG demo without the HTML context to see if this resolves the strange drag behaviour in Firefox.

Added:
    commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.js   (with props)
    commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.svg   (with props)

Added: commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.js
URL: http://svn.apache.org/viewvc/commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.js?rev=959165&view=auto
==============================================================================
--- commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.js (added)
+++ commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.js Wed Jun 30 02:08:05 2010
@@ -0,0 +1,662 @@
+function StatechartExecutionContext() {
+
+    var self = this; //used in the rare occasions we call public functions from inside this class
+    //system variable declarations
+    var _event = {
+        name: undefined,
+        data: undefined
+    },
+        _name = "",
+        _sessionid;
+
+    var _x = {
+        _event: _event,
+        _name: _name,
+        _sessionid: _sessionid
+    };
+
+    //variable declarations relating to data model
+    var firstEvent, eventStamp, tDelta, rawNode, textNode;
+
+
+    //abstract state
+
+    var AbstractState = new
+    function() {
+        //triggers are methods
+
+        this.$default = function() {};
+
+        this.init = function() {};
+
+        this.mousedown = function() {};
+
+        this.mouseup = function() {};
+
+        this.mousemove = function() {};
+
+
+        this.$default = function() {};
+    }
+
+
+    //states
+
+
+
+    var scxmlRoot = (function() {
+
+        function scxmlRootConstructor() {
+            this.parent = AbstractState;
+
+            this.initial = null;
+
+            this.depth = 0;
+
+            this.historyState = null;
+
+            //these variables facilitate fast In predicate
+            this.isBasic =
+
+            false;
+
+
+            this.toString = function() {
+                return "scxmlRoot"
+            }
+
+            this.enterAction = function() {
+
+                console.log("entering scxmlRoot");
+
+            }
+
+            this.exitAction = function() {
+
+                console.log("exiting scxmlRoot");
+
+            }
+
+
+
+
+        }
+        scxmlRootConstructor.prototype = AbstractState;
+        return new scxmlRootConstructor();
+    })();
+
+
+
+
+
+    var scxmlRoot_initial = (function() {
+
+        function scxmlRoot_initialConstructor() {
+            this.parent = scxmlRoot;
+
+            this.initial = null;
+
+            this.depth = 1;
+
+            this.historyState = null;
+
+            //these variables facilitate fast In predicate
+            this.isBasic =
+
+            true;
+
+            this.ancestors = [
+                scxmlRoot
+                ];
+
+            this.parent.initial = this; //init parent's pointer to initial state
+
+            this.toString = function() {
+                return "scxmlRoot_initial"
+            }
+
+            this.enterAction = function() {
+
+                console.log("entering scxmlRoot_initial");
+
+            }
+
+            this.exitAction = function() {
+
+                console.log("exiting scxmlRoot_initial");
+
+            }
+
+
+
+            this.$default = function() {
+
+
+                hasTakenDefaultTransition = true;
+
+
+                //exit states
+                scxmlRoot_initial.exitAction();
+
+
+                //transition action
+
+                //enter states
+                initial_default.enterAction();
+
+
+                //update configuration
+
+                currentConfiguration = [
+                    initial_default
+                    ];
+
+
+
+                //set whether preempted
+
+                return;
+                scxmlRoot['$default']();
+            }
+
+
+
+        }
+        scxmlRoot_initialConstructor.prototype = scxmlRoot;
+        return new scxmlRoot_initialConstructor();
+    })();
+
+
+
+
+
+    var initial_default = (function() {
+
+        function initial_defaultConstructor() {
+            this.parent = scxmlRoot;
+
+            this.initial = null;
+
+            this.depth = 1;
+
+            this.historyState = null;
+
+            //these variables facilitate fast In predicate
+            this.isBasic =
+
+            true;
+
+            this.ancestors = [
+                scxmlRoot
+                ];
+
+
+            this.toString = function() {
+                return "initial_default"
+            }
+
+            this.enterAction = function() {
+
+                console.log("entering initial_default");
+
+            }
+
+            this.exitAction = function() {
+
+                console.log("exiting initial_default");
+
+            }
+
+
+
+            this.init = function() {
+
+
+
+                //exit states
+                initial_default.exitAction();
+
+
+                //transition action
+                rawNode = _event.data.rawNode;
+                textNode = _event.data.textNode;
+                textNode.textContent = 'idle';
+
+
+                //enter states
+                idle.enterAction();
+
+
+                //update configuration
+
+                currentConfiguration = [
+                    idle
+                    ];
+
+
+
+                //set whether preempted
+
+                return;
+                scxmlRoot['init']();
+            }
+
+
+
+        }
+        initial_defaultConstructor.prototype = scxmlRoot;
+        return new initial_defaultConstructor();
+    })();
+
+
+
+
+
+    var idle = (function() {
+
+        function idleConstructor() {
+            this.parent = scxmlRoot;
+
+            this.initial = null;
+
+            this.depth = 1;
+
+            this.historyState = null;
+
+            //these variables facilitate fast In predicate
+            this.isBasic =
+
+            true;
+
+            this.ancestors = [
+                scxmlRoot
+                ];
+
+
+            this.toString = function() {
+                return "idle"
+            }
+
+            this.enterAction = function() {
+
+                console.log("entering idle");
+
+            }
+
+            this.exitAction = function() {
+
+                console.log("exiting idle");
+
+            }
+
+
+
+            this.mousedown = function() {
+
+
+
+                //exit states
+                idle.exitAction();
+
+
+                //transition action
+                firstEvent = _event.data;
+                eventStamp = _event.data;
+                textNode.textContent = 'dragging';
+
+
+                //enter states
+                dragging.enterAction();
+
+
+                //update configuration
+
+                currentConfiguration = [
+                    dragging
+                    ];
+
+
+
+                //set whether preempted
+
+                return;
+                scxmlRoot['mousedown']();
+            }
+
+
+
+        }
+        idleConstructor.prototype = scxmlRoot;
+        return new idleConstructor();
+    })();
+
+
+
+
+
+    var dragging = (function() {
+
+        function draggingConstructor() {
+            this.parent = scxmlRoot;
+
+            this.initial = null;
+
+            this.depth = 1;
+
+            this.historyState = null;
+
+            //these variables facilitate fast In predicate
+            this.isBasic =
+
+            true;
+
+            this.ancestors = [
+                scxmlRoot
+                ];
+
+
+            this.toString = function() {
+                return "dragging"
+            }
+
+            this.enterAction = function() {
+
+                console.log("entering dragging");
+
+            }
+
+            this.exitAction = function() {
+
+                console.log("exiting dragging");
+
+            }
+
+
+
+            this.mouseup = function() {
+
+
+
+                //exit states
+                dragging.exitAction();
+
+
+                //transition action
+                textNode.textContent = 'idle';
+
+
+                //enter states
+                idle.enterAction();
+
+
+                //update configuration
+
+                currentConfiguration = [
+                    idle
+                    ];
+
+
+
+                //set whether preempted
+
+                return;
+                scxmlRoot['mouseup']();
+            }
+
+
+            this.mousemove = function() {
+
+
+
+                //exit states
+                dragging.exitAction();
+
+
+                //transition action
+                tDelta = computeTDelta(eventStamp, _event.data);
+
+                translate(rawNode, tDelta);
+                eventStamp = _event.data;
+
+
+                //enter states
+                dragging.enterAction();
+
+
+                //update configuration
+
+                currentConfiguration = [
+                    dragging
+                    ];
+
+
+
+                //set whether preempted
+
+                return;
+                scxmlRoot['mousemove']();
+            }
+
+
+
+        }
+        draggingConstructor.prototype = scxmlRoot;
+        return new draggingConstructor();
+    })();
+
+
+
+
+    //states enum for glass-box unit testing
+
+    this._states = {
+        scxmlRoot_initial: scxmlRoot_initial,
+        initial_default: initial_default,
+        idle: idle,
+        dragging: dragging
+    }
+
+
+
+    //trigger methods for synchronous interaction
+
+    this.$default = function(data) {
+        if (isInStableState) {
+            runToCompletion("$default", data);
+        } else {
+            return undefined;
+        }
+    }
+
+
+    this.init = function(data) {
+        if (isInStableState) {
+            runToCompletion("init", data);
+        } else {
+            return undefined;
+        }
+    }
+
+
+    this.mousedown = function(data) {
+        if (isInStableState) {
+            runToCompletion("mousedown", data);
+        } else {
+            return undefined;
+        }
+    }
+
+
+    this.mouseup = function(data) {
+        if (isInStableState) {
+            runToCompletion("mouseup", data);
+        } else {
+            return undefined;
+        }
+    }
+
+
+    this.mousemove = function(data) {
+        if (isInStableState) {
+            runToCompletion("mousemove", data);
+        } else {
+            return undefined;
+        }
+    }
+
+
+    //initialization script
+
+    function computeTDelta(oldEvent, newEvent) {
+        //summary:computes the offset between two events; to be later used with this.translate
+        var dx = newEvent.clientX - oldEvent.clientX;
+        var dy = newEvent.clientY - oldEvent.clientY;
+
+        return {
+            'dx': dx,
+            'dy': dy
+        };
+    }
+
+    function translate(rawNode, tDelta) {
+        var tl = rawNode.transform.baseVal;
+        var t = tl.numberOfItems ? tl.getItem(0) : rawNode.ownerSVGElement.createSVGTransform();
+        var m = t.matrix;
+        var newM = rawNode.ownerSVGElement.createSVGMatrix().translate(tDelta.dx, tDelta.dy).multiply(m);
+        t.setMatrix(newM);
+        tl.initialize(t);
+        return newM;
+    }
+
+
+    //initialization method
+
+    this.initialize = function() {
+        currentConfiguration = [initial_default];
+        runToCompletion();
+        mainLoop();
+    }
+
+
+
+    //internal runtime functions
+
+    function sortByDepthDeepToShallow(a, b) {
+        return b.depth - a.depth;
+    }
+
+
+    //start static boilerplate code
+    //static private member variables
+    var currentConfiguration = []; //current configuration
+    var innerEventQueue = []; //inner event queue
+    var outerEventQueue = []; //outer event queue
+    var isInStableState = true;
+    var isPreempted = false;
+    var hasTakenDefaultTransition = false;
+    var destroyed = false;
+    var mainLoopCallback = null;
+
+    //static private member functions
+
+
+    function mainLoop() {
+
+        if (!destroyed) {
+            //take an event from the current outer event queue
+            if (outerEventQueue.length && isInStableState) {
+                runToCompletion(outerEventQueue.shift(), outerEventQueue.shift());
+            }
+            //call back
+            mainLoopCallback = window.setTimeout(function() {
+                mainLoop(); //FIXME: note that when calling mainloop this way, we won't have access to the "this" object. 
+                //I don't think we ever use it though. Everything we need is private in function scope.
+            }, 100);
+        }
+    }
+
+    function runToCompletion(e, data) {
+        isInStableState = false;
+
+        if (e) {
+            innerEventQueue.push(e, data);
+        }
+
+        do {
+            //take any available default transitions
+            microstep("$default");
+
+            if (!hasTakenDefaultTransition) {
+
+                if (!innerEventQueue.length) {
+                    //we have no more generated events, and no default transitions fired, so
+                    //we are done, and have run to completion
+                    break;
+                } else {
+                    //microstep, then dequeue next event sending in event
+                    microstep(innerEventQueue.shift(), innerEventQueue.shift());
+                }
+            } else {
+                //he has taken a default transition, so reset the global variable to false and loop again
+                hasTakenDefaultTransition = false;
+            }
+
+        } while (true)
+
+        isInStableState = true;
+    }
+
+    function microstep(e, data) {
+        currentConfiguration.forEach(function(state) {
+            if (!isPreempted) {
+                //we set the event as a global, rather than passing it into the function invocation as a parameter,
+                //because in cases of default events, the event object will be populated with previous event's data
+                if (e !== "$default") {
+                    _event.name = e;
+                    _event.data = data;
+                }
+                state[e]();
+            }
+        });
+
+        //reset the isPreempted flag
+        isPreempted = false;
+    }
+
+
+    this.destroy = function() {
+        //right now, this only disables timer and sets global destroyed variable to prevent future callbacks
+        window.clearTimeout(mainLoopCallback);
+        mainLoopCallback = null;
+        destroyed = true;
+    }
+
+
+    //this is for async communication
+    this.GEN = function(e, data) {
+        outerEventQueue.push(e, data);
+    }
+
+    //this may or may not be something we want to expose, but for right now, we at least need it for testing
+    this.getCurrentConfiguration = function() {
+        //slice it to return a copy of the configuration rather than the conf itself
+        //this saves us all kinds of confusion involving references and stuff
+        return currentConfiguration.slice();
+    }
+
+    //public API for In predicate
+    this.$in = function(state) {
+        return In(state);
+    }
+
+    //end static boilerplate code
+
+    function In(state) {
+        state = typeof state == "string" ? self._states[state] : state;
+
+        return state.isBasic ? currentConfiguration.indexOf(state) != -1 : currentConfiguration.some(function(s) {
+            return s.ancestors.indexOf(state) != -1;
+        });
+    }
+
+}

Propchange: commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.js
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.svg
URL: http://svn.apache.org/viewvc/commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.svg?rev=959165&view=auto
==============================================================================
--- commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.svg (added)
+++ commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.svg Wed Jun 30 02:08:05 2010
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<!--
+This demo illustrates mixing HTML, SVG, and SCXML content in a single compound
+XML document. 
+
+It also illustrates a fairly general technique, which would
+allow authoring of SVG content with inline, declarative behavioural descriptions
+using SCXML: 
+* the document is searched for scxml elements 
+* it compiles them locally to JavaScript, and then hooks up event listeners on the parent DOM node, 
+	so that DOM events are sent to the state machine for processing
+* the state machine is able to manipulate the DOM directly through executable content nodes
+-->
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="99%" id="svgRoot">
+	<script type="application/ecmascript" xlink:href="drag-and-drop3.js"/>
+	<g id="groupToTranslate">
+		<rect width="100" height="100" stroke="black" fill="red" id="rectToTranslate" />
+		<text id="textToTranslate" />
+	</g>
+
+	<script><![CDATA[
+		var resultText;
+
+		//hook up minimal console api
+		if(typeof console == "undefined"){
+			console = {};
+			["log","info","error","dirxml"].forEach(function(m){console[m] = console[m] || function(){} });
+		} 
+
+		var svgRoot = document.getElementById("svgRoot");
+
+		var rectToTranslate = document.getElementById("rectToTranslate");
+		var groupToTranslate = document.getElementById("groupToTranslate");
+		var textToTranslate = document.getElementById("textToTranslate");
+
+		var compiledStatechartInstance = new StatechartExecutionContext(); 
+
+		//initialize
+		compiledStatechartInstance.initialize();
+		
+		//pass in reference to rect
+		compiledStatechartInstance.init({rawNode:groupToTranslate,textNode:textToTranslate}); 
+
+		//hook up DOM events
+		["mousedown","mouseup","mousemove"].forEach(function(eventName){
+			groupToTranslate.addEventListener(eventName,compiledStatechartInstance[eventName],false);
+		});
+
+		//quick hack to ensure that mm events get captured by the rect
+		svgRoot.addEventListener("mousemove",compiledStatechartInstance["mousemove"],false);
+
+
+	]]></script>
+</svg>

Propchange: commons/sandbox/gsoc/2010/scxml-js/branches/SCXML-141-148/demo/drag-and-drop/drag-and-drop3.svg
------------------------------------------------------------------------------
    svn:eol-style = native