/*COMPILED*/





 /*JS File: ../js/ajaxanimator.js*/ 


 /**
 * Ajax Animator
 *
 * @author    Antimatter15
 * @copyright (c) 2007-2008, by Antimatter15
 * @date      14. April 2008
 * @version   0.20+ Testing
 *
 * @license application.js is licensed under the terms of the Open Source GPL 2.0 license. 
 * 
 * License details: http://www.gnu.org/licenses/gpl.html
 */
 
/*global Ext, Application */



Ext.ns('Ax'); //i got tired of typing ajaxanimator.xxx so i shortened it

Ax.animation = {
  name: "Untitled Production",
  markup: {}
}
// application main entry point
Ext.onReady(function() {
  
  Ext.get("loading-msg").update("Initializing...")
   
  Ext.QuickTips.init();

 
    // code here
 
}); // eo function onReady
 
 
Ax.set_version = function(version_object){
  //Sets the current version of the applicaiton and does some operations with it
  
  Ax.v = version_object;
  
  if(window.developer==true){
    Ax.title = [Ax.v.app,Ax.v.release,Ax.v.stability,"Development"].join(" ");
  }else if(Ax.v.dev == true){
    Ax.title = [Ax.v.app,Ax.v.release,Ax.v.stability,"Testing build",Ax.v.build].join(" ");
  }else{
    Ax.title = [Ax.v.app,Ax.v.release,Ax.v.stability].join(" ");
  }
  
  document.title = Ax.title;
} 
 
// eof


 /*JS File: ../js/version.js*/ 


 /*Auto-Generated Ajax Animator Version config (Markup Version II)*/
/*Generated By versions.php in /server/dev/compile/*/
Ax.set_version( /*START*/
{"app":"Ajax Animator","build":514,"release":"0.20.02","dev":false,"stability":"Beta RC3","date":1218925525.7}
/*STOP*/ )
/*End Of File*/



 /*JS File: ../js/misc/alt/files.js*/ 


 /*
 files and direcories used via ajax
 */

Ext.BLANK_IMAGE_URL = 'http://ajaxanimator.googlecode.com/svn-history/r444/trunk/ajaxanimator/theme/images/default/s.gif';

Ax.files = {
    userlist: "../server/user/userlist.php",
	test: "../server/user/test.php",
    animations: "../server/user/animation.php?id=",
	library: "../server/user/library.php",
	libraryitem: "../server/user/libraryitem.php?id=",
    save_proxy: "../server/user/save_proxy.php",
    open_proxy: "../server/user/open_proxy.php",
	export_gif: "../server/export/gif.php",
	export_swf: "../server/export/swf.php",
	faq: "../server/doc/faq.htm",
	manual: "../server/doc/manual.htm",
	
	themes: "http://ajaxanimator.googlecode.com/svn-history/r444/trunk/ajaxanimator/theme/css/"
}


 /*JS File: ../js/ext/ux/Ext.ux.base64.js*/ 


 
Ext.ux.base64 = {

    base64s : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
    
    encode: function(decStr){
        if (typeof btoa === 'function') {
             return btoa(decStr);            
        }
        var base64s = this.base64s;
        var bits;
        var dual;
        var i = 0;
        var encOut = "";
        while(decStr.length >= i + 3){
            bits = (decStr.charCodeAt(i++) & 0xff) <<16 | (decStr.charCodeAt(i++) & 0xff) <<8 | decStr.charCodeAt(i++) & 0xff;
            encOut += base64s.charAt((bits & 0x00fc0000) >>18) + base64s.charAt((bits & 0x0003f000) >>12) + base64s.charAt((bits & 0x00000fc0) >> 6) + base64s.charAt((bits & 0x0000003f));
        }
        if(decStr.length -i > 0 && decStr.length -i < 3){
            dual = Boolean(decStr.length -i -1);
            bits = ((decStr.charCodeAt(i++) & 0xff) <<16) |    (dual ? (decStr.charCodeAt(i) & 0xff) <<8 : 0);
            encOut += base64s.charAt((bits & 0x00fc0000) >>18) + base64s.charAt((bits & 0x0003f000) >>12) + (dual ? base64s.charAt((bits & 0x00000fc0) >>6) : '=') + '=';
        }
        return(encOut);
    },
    
    decode: function(encStr){
        if (typeof atob === 'function') {
            return atob(encStr); 
        }
        var base64s = this.base64s;        
        var bits;
        var decOut = "";
        var i = 0;
        for(; i<encStr.length; i += 4){
            bits = (base64s.indexOf(encStr.charAt(i)) & 0xff) <<18 | (base64s.indexOf(encStr.charAt(i +1)) & 0xff) <<12 | (base64s.indexOf(encStr.charAt(i +2)) & 0xff) << 6 | base64s.indexOf(encStr.charAt(i +3)) & 0xff;
            decOut += String.fromCharCode((bits & 0xff0000) >>16, (bits & 0xff00) >>8, bits & 0xff);
        }
        if(encStr.charCodeAt(i -2) == 61){
            return(decOut.substring(0, decOut.length -2));
        }
        else if(encStr.charCodeAt(i -1) == 61){
            return(decOut.substring(0, decOut.length -1));
        }
        else {
            return(decOut);
        }
    }

}; 







 /*JS File: ../js/ext/ux/Ext.ux.clone.js*/ 


 /**
 * Clone Function
 */

Ext.ux.clone = function(o) {
    if(!o || 'object' !== typeof o) {
        return o;
    }
    var c = 'function' === typeof o.pop ? [] : {};
    var p, v;
    for(p in o) {
        if(o.hasOwnProperty(p)) {
            v = o[p];
            if(v && 'object' === typeof v) {
                c[p] = Ext.ux.clone(v);
            }
            else {
                c[p] = v;
            }
        }
    }
    return c;
}; // eo function clone 



 /*JS File: ../js/ext/ux/Ext.ux.Crypto.SHA1.js*/ 


 Ext.namespace('Ext.ux', 'Ext.ux.Crypto');

Ext.ux.Crypto.SHA1 = function() {
  // function 'f' [§4.1.1]
  var f = function(s, x, y, z) {
      switch (s) {
          case 0: return (x & y) ^ (~x & z);           // Ch()
          case 1: return x ^ y ^ z;                    // Parity()
          case 2: return (x & y) ^ (x & z) ^ (y & z);  // Maj()
          case 3: return x ^ y ^ z;                    // Parity()
      }
  };
  // rotate left (circular left shift) value x by n positions [§3.2.5]
  var ROTL = function(x, n) {
      return (x<<n) | (x>>>(32-n));
  };
  return {
    hash : function(msg) {
      // constants [§4.2.1]
      var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
  
  
      // PREPROCESSING 
   
      msg += String.fromCharCode(0x80); // add trailing '1' bit to string [§5.1.1]
  
      // convert string msg into 512-bit/16-integer blocks arrays of ints [§5.2.1]
      var l = Math.ceil(msg.length/4) + 2;  // long enough to contain msg plus 2-word length
      var N = Math.ceil(l/16);              // in N 16-int blocks
      var M = new Array(N);
      for (var i=0; i<N; i++) {
          M[i] = new Array(16);
          for (var j=0; j<16; j++) {  // encode 4 chars per integer, big-endian encoding
              M[i][j] = (msg.charCodeAt(i*64+j*4)<<24) | (msg.charCodeAt(i*64+j*4+1)<<16) | 
                        (msg.charCodeAt(i*64+j*4+2)<<8) | (msg.charCodeAt(i*64+j*4+3));
          }
      }
      // add length (in bits) into final pair of 32-bit integers (big-endian) [5.1.1]
      // note: most significant word would be ((len-1)*8 >>> 32, but since JS converts
      // bitwise-op args to 32 bits, we need to simulate this by arithmetic operators
      M[N-1][14] = ((msg.length-1)*8) / Math.pow(2, 32); M[N-1][14] = Math.floor(M[N-1][14])
      M[N-1][15] = ((msg.length-1)*8) & 0xffffffff;
  
      // set initial hash value [§5.3.1]
      var H0 = 0x67452301;
      var H1 = 0xefcdab89;
      var H2 = 0x98badcfe;
      var H3 = 0x10325476;
      var H4 = 0xc3d2e1f0;
  
      // HASH COMPUTATION [§6.1.2]
  
      var W = new Array(80); var a, b, c, d, e;
      for (var i=0; i<N; i++) {
  
          // 1 - prepare message schedule 'W'
          for (var t=0;  t<16; t++) W[t] = M[i][t];
          for (var t=16; t<80; t++) W[t] = ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
  
          // 2 - initialise five working variables a, b, c, d, e with previous hash value
          a = H0; b = H1; c = H2; d = H3; e = H4;
  
          // 3 - main loop
          for (var t=0; t<80; t++) {
              var s = Math.floor(t/20); // seq for blocks of 'f' functions and 'K' constants
              var T = (ROTL(a,5) + f(s,b,c,d) + e + K[s] + W[t]) & 0xffffffff;
              e = d;
              d = c;
              c = ROTL(b, 30);
              b = a;
              a = T;
          }
  
          // 4 - compute the new intermediate hash value
          H0 = (H0+a) & 0xffffffff;  // note 'addition modulo 2^32'
          H1 = (H1+b) & 0xffffffff; 
          H2 = (H2+c) & 0xffffffff; 
          H3 = (H3+d) & 0xffffffff; 
          H4 = (H4+e) & 0xffffffff;
      }
  
      return H0.toHexStr() + H1.toHexStr() + H2.toHexStr() + H3.toHexStr() + H4.toHexStr();
    }
  }
  
}();

/**
 * @class Number
 */
Ext.applyIf(Number.prototype, {
    /**
     * extend Number class with a tailored hex-string method (note toString(16) is implementation-dependant, and in IE returns signed numbers when used on full words)
     * @return {String} The number in Hexidecimal format.
     */
    toHexStr : function(){
        var s = '', v;
        for(var i = 7; i >= 0; i--) {
            v = (this >>> (i * 4)) & 0xf;
            s += v.toString(16);
        }
        return s;
    }
});



 /*JS File: ../js/ext/ux/Ext.ux.ThemeMenu.js*/ 


 /*
* Theme Selection Menu
*
* By Antimatter15 2008
* i donno. gpl v3 maybe.
*/

Ext.ux.ThemeMenu = function(config){
    Ext.ux.ThemeMenu.superclass.constructor.call(this, config);

    //this.plain = true;
	for(var theme = 0; theme < this.themeconfig.length; theme++){
	this.add(new Ext.menu.CheckItem({
    text: this.themeconfig[theme][1], //text title
	theme: theme,
	checked: (this.themeconfig[theme][2]==true),
    group: 'thememenu',
    checkHandler: function(item, checked) {
        if (checked){
		item.parentMenu.setTheme(item.theme)
		};
    }
}))
}

};

Ext.extend(Ext.ux.ThemeMenu, Ext.menu.Menu, {

cssPath: Ax.files.themes, //mind the trailing slash

themeconfig:[ //array of stuff
 ['xtheme-default.css','Ext Blue Theme',true] //t3h default
,['xtheme-gray.css', 'Gray Theme']
,['xtheme-gray.css,xtheme-gray-extend.css', 'Extended Gray Theme'] //this is an "extend" theme, it is applied over another theme
,['xtheme-darkgray.css', 'Dark Gray Theme']
,['xtheme-black.css',  'Black Theme']
,['xtheme-olive.css', 'Olive Theme']
,['xtheme-purple.css', 'Purple Theme']
,['xtheme-slate.css', 'Slate Theme']
,['xtheme-peppermint.css',  'Peppermint Theme']
,['xtheme-chocolate.css', 'Chocolate Theme']
,['xtheme-slickness.css', 'SlicknesS Theme']
,['xtheme-pink.css', 'Pink Theme']
,['xtheme-midnight.css', "Midnight Theme"]
,['xtheme-green.css', "Green Theme"]
,['xtheme-indigo.css', "Indigo Theme"]
,['xtheme-silverCherry.css',"Silver Cherry Theme"]
,['xtheme-orange.css',"Orange Theme"]
],
setTheme: function(id){
//console.log(this)
var theme = this.themeconfig[id][0];
var themes = theme.split(",")
for(var i = 0; i < 4; i++){ //up to 4 themes on top of each other
if(themes[i]){
Ext.util.CSS.swapStyleSheet('csstheme'+i, this.cssPath + themes[i]);
}else{
Ext.util.CSS.removeStyleSheet('csstheme'+i);
}
}

}//end setTheme
});









 /*JS File: ../js/ext/ux/Ext.ux.ToastWindow.js*/ 


 Ext.ux.ToastWindowMgr = {
    positions: [] 
};

Ext.ux.ToastWindow = Ext.extend(Ext.Window, {
    initComponent: function(){
          Ext.apply(this, {
            iconCls: this.iconCls || 'information',
            width: 200,
            height: 100,
			delay: this.delay?this.delay:4000,
            autoScroll: true,
            autoDestroy: true,
            plain: false
          });
        this.task = new Ext.util.DelayedTask(this.hide, this);
        Ext.ux.ToastWindow.superclass.initComponent.call(this);
		
		//console.log(this.delay)
    },
    setMessage: function(msg){
        this.body.update(msg);
    },
    setTitle: function(title, iconCls){
        Ext.ux.ToastWindow.superclass.setTitle.call(this, title, iconCls||this.iconCls);
    },
    onRender:function(ct, position) {
        Ext.ux.ToastWindow.superclass.onRender.call(this, ct, position);
    },
    onDestroy: function(){
        Ext.ux.ToastWindowMgr.positions.remove(this.pos);
        Ext.ux.ToastWindow.superclass.onDestroy.call(this);
    },
    afterShow: function(){
        Ext.ux.ToastWindow.superclass.afterShow.call(this);
        this.on('move', function(){
               Ext.ux.ToastWindowMgr.positions.remove(this.pos);
            this.task.cancel();}
        , this);
        this.task.delay(this.delay);
    },
    animShow: function(){
        this.pos = 0;
        while(Ext.ux.ToastWindowMgr.positions.indexOf(this.pos)>-1)
            this.pos++;
        Ext.ux.ToastWindowMgr.positions.push(this.pos);
        this.setSize(200,100);
        this.el.alignTo(document, "br-br", [ -20, -20-((this.getSize().height+10)*this.pos) ]);
        this.el.slideIn('b', {
            duration: 1,
            callback: this.afterShow,
            scope: this
        });    
    },
    animHide: function(){
        Ext.ux.ToastWindowMgr.positions.remove(this.pos);
        this.el.ghost("b", {
            duration: 1,
            remove: true,
        	scope: this,
        	callback: this.destroy
        });
    },
	  focus: Ext.emptyFn 

});  


 /*JS File: ../js/ext/ux/Ext.ux.grid.CellActions.js*/ 


 // vim: ts=4:sw=4:nu:fdc=4:nospell
/**
 * CellActions plugin for Ext grid
 *
 * Contains renderer for an icon and fires events when icon is clicked
 *
 * @author    Ing. Jozef SakÃ¡loÅ¡
 * @date      22. March 2008
 * @version   $Id: Ext.ux.grid.CellActions.js 163 2008-06-18 17:24:54Z antimatter15 $
 *
 * @license Ext.ux.grid.CellActions is licensed under the terms of
 * the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
 * that the code/component(s) do NOT become part of another Open Source or Commercially
 * licensed development library or toolkit without explicit permission.
 * 
 * License details: http://www.gnu.org/licenses/lgpl.html
 */

/**
 * The following css is required:
 *
 * .ux-cell-value {
 * 	position:relative;
 * 	zoom:1;
 * }
 * .ux-cell-actions {
 * 	position:absolute;
 * 	right:0;
 * 	top:-2px;
 * }
 * .ux-cell-actions-left {
 * 	left:0;
 * 	top:-2px;
 * }
 * .ux-cell-action {
 * 	width:16px;
 * 	height:16px;
 * 	float:left;
 * 	cursor:pointer;
 * 	margin: 0 0 0 4px;
 * }
 * .ux-cell-actions-left .ux-cell-action {
 * 	margin: 0 4px 0 0;
 * }
 */

/*global Ext */

Ext.ns('Ext.ux.grid');

// constructor and cellActions documentation
// {{{
/**
 * @class Ext.ux.grid.CellActions
 * @extends Ext.util.Observable
 * @constructor
 *
 * CellActions plugin causes that column model recognizes the config property cellAcions
 * that is the array of configuration objects for that column. The documentationi follows.
 *
 * THE FOLLOWING CONFIG OPTIONS ARE FOR COLUMN MODEL COLUMN, NOT FOR CellActions ITSELF.
 *
 * @cfg {Array} cellActions Mandatory. Array of action configuration objects. The following
 * configuration options of action are recognized:
 *
 * - @cfg {Function} callback Optional. Function to call if the action icon is clicked.
 *   This function is called with same signature as action event and in its original scope.
 *   If you need to call it in different scope or with another signature use 
 *   createCallback or createDelegate functions. Works for statically defined actions. Use
 *   callbacks configuration options for store bound actions.
 *
 * - @cfg {Function} cb Shortcut for callback.
 *
 * - @cfg {String} iconIndex Optional, however either iconIndex or iconCls must be
 *   configured. Field name of the field of the grid store record that contains
 *   css class of the icon to show. If configured, shown icons can vary depending
 *   of the value of this field.
 *
 * - @cfg {String} iconCls. css class of the icon to show. It is ignored if iconIndex is
 *   configured. Use this if you want static icons that are not base on the values in the record.
 *
 * - @cfg {String} qtipIndex Optional. Field name of the field of the grid store record that 
 *   contains tooltip text. If configured, the tooltip texts are taken from the store.
 *
 * - @cfg {String} tooltip Optional. Tooltip text to use as icon tooltip. It is ignored if 
 *   qtipIndex is configured. Use this if you want static tooltips that are not taken from the store.
 *
 * - @cfg {String} qtip Synonym for tooltip
 *
 * - @cfg {String} style Optional. Style to apply to action icon container.
 */
Ext.ux.grid.CellActions = function(config) {
	Ext.apply(this, config);

	this.addEvents(
		/**
		 * @event action
		 * Fires when user clicks a cell action
		 * @param {Ext.grid.GridPanel} grid
		 * @param {Ext.data.Record} record Record containing data of clicked cell
		 * @param {String} action Action clicked (equals iconCls);
		 * @param {Mixed} value Value of the clicke cell
		 * @param {String} dataIndex as specified in column model
		 * @param {Number} rowIndex Index of row clicked
		 * @param {Number} colIndex Incex of col clicked
		 */
		'action'
		/**
		 * @event beforeaction
		 * Fires when user clicks a cell action but before action event is fired. Return false to cancel the action;
		 * @param {Ext.grid.GridPanel} grid
		 * @param {Ext.data.Record} record Record containing data of clicked cell
		 * @param {String} action Action clicked (equals iconCls);
		 * @param {Mixed} value Value of the clicke cell
		 * @param {String} dataIndex as specified in column model
		 * @param {Number} rowIndex Index of row clicked
		 * @param {Number} colIndex Incex of col clicked
		 */
		,'beforeaction'
	);
	// call parent
	Ext.ux.grid.CellActions.superclass.constructor.call(this);

}; // eo constructor
// }}}

Ext.extend(Ext.ux.grid.CellActions, Ext.util.Observable, {

	/**
	 * @cfg {String} actionEvnet Event to trigger actions, e.g. click, dblclick, mouseover (defaults to 'click')
	 */
	 actionEvent:'click'

	/**
	 * @cfg {Number} actionWidth Width of action icon in pixels. Has effect only if align:'left'
	 */
	,actionWidth:20

	/**
	 * @cfg {String} align Set to 'left' to put action icons before the cell text. (defaults to undefined, meaning right)
	 */

	/**
	 * @private
	 * @cfg {String} tpl Template for cell with actions
	 */
	,tpl:'<div class="ux-cell-value" style="padding-left:{padding}px">'
			+'<tpl if="\'left\'!==align">{value}</tpl>'
		 	+'<div class="ux-cell-actions<tpl if="\'left\'===align"> ux-cell-actions-left</tpl>" style="width:{width}px">'
				+'<tpl for="actions"><div class="ux-cell-action {cls}" qtip="{qtip}" style="{style}">&#160;</div></tpl>'
			+'</div>'
			+'<tpl if="\'left\'===align">{value}</tpl>'
		+'<div>'
		
	/**
	 * Called at the end of processActions. Override this if you need it.
	 * @param {Object} c Column model configuration object
	 * @param {Object} data See this.processActions method for details
	 */
	,userProcessing:Ext.emptyFn

	// {{{
	/**
	 * Init function
	 * @param {Ext.grid.GridPanel} grid Grid this plugin is in
	 */
	,init:function(grid) {
		this.grid = grid;
//		grid.on({scope:this, render:this.onRenderGrid});
		grid.afterRender = grid.afterRender.createSequence(this.onRenderGrid, this);

		var cm = this.grid.getColumnModel();
		Ext.each(cm.config, function(c, idx) {
			if('object' === typeof c.cellActions) {
				c.origRenderer = cm.getRenderer(idx);
				c.renderer = this.renderActions.createDelegate(this);
			}
		}, this);


	} // eo function init
	// }}}
	// {{{
	/**
	 * grid render event handler, install actionEvent handler on view.mainBody
	 * @private
	 */
	,onRenderGrid:function() {

		// install click event handler on view mainBody
		this.view = this.grid.getView();
		var cfg = {scope:this};
		cfg[this.actionEvent] = this.onClick;
		this.view.mainBody.on(cfg);

	} // eo function onRender
	// }}}
	// {{{
	/**
	 * Returns data to apply to template. Override this if needed
	 * @param {Mixed} value 
	 * @param {Object} cell object to set some attributes of the grid cell
	 * @param {Ext.data.Record} record from which the data is extracted
	 * @param {Number} row row index
	 * @param {Number} col col index
	 * @param {Ext.data.Store} store object from which the record is extracted
	 * @returns {Object} data to apply to template
	 */
	,getData:function(value, cell, record, row, col, store) {
		return record.data || {};
	}
	// }}}
	// {{{
	/**
	 * replaces (but calls) the original renderer from column model
	 * @private
	 * @param {Mixed} value 
	 * @param {Object} cell object to set some attributes of the grid cell
	 * @param {Ext.data.Record} record from which the data is extracted
	 * @param {Number} row row index
	 * @param {Number} col col index
	 * @param {Ext.data.Store} store object from which the record is extracted
	 * @returns {String} markup of cell content
	 */
	,renderActions:function(value, cell, record, row, col, store) {

		// get column config from column model
		var c = this.grid.getColumnModel().config[col];

		// get output of the original renderer
		var val = c.origRenderer(value, cell, record, row, col, store);

		// get actions template if we need but don't have one
		if(c.cellActions && !c.actionsTpl) {
			c.actionsTpl = this.processActions(c);
			c.actionsTpl.compile();
		}
		// return original renderer output if we don't have actions
		else if(!c.cellActions) {
			return val;
		}

		// get and return final markup
		var data = this.getData.apply(this, arguments);
		data.value = val;
		return c.actionsTpl.apply(data);

	} // eo function renderActions
	// }}}
	// {{{
	/**
	 * processes the actions configs from column model column, saves callbacks and creates template
	 * @param {Object} c column model config of one column
	 * @private
	 */
	,processActions:function(c) {

		// callbacks holder
		this.callbacks = this.callbacks || {};

		// data for intermediate template
		var data = {
			 align:this.align || 'right'
			,width:this.actionWidth * c.cellActions.length
			,padding:'left' === this.align ? this.actionWidth * c.cellActions.length : 0
			,value:'{value}'
			,actions:[]
		};

		// cellActions loop
		Ext.each(c.cellActions, function(a, i) {

			// save callback
			if(a.iconCls && 'function' === typeof (a.callback || a.cb)) {
				this.callbacks[a.iconCls] = a.callback || a.cb;
			}

			// data for intermediate xtemplate action
			var o = {
				 cls:a.iconIndex ? '{' + a.iconIndex + '}' : (a.iconCls ? a.iconCls : '')
				,qtip:a.qtipIndex ? '{' + a.qtipIndex + '}' : (a.tooltip || a.qtip ? a.tooltip || a.qtip : '')
				,style:a.style ? a.style : ''
			};
			data.actions.push(o);

		}, this); // eo cellActions loop

		this.userProcessing(c, data);

		// get and return final template
		var xt = new Ext.XTemplate(this.tpl);
		return new Ext.Template(xt.apply(data));

	} // eo function processActions
	// }}}
	// {{{
	/**
	 * Grid body actionEvent event handler
	 * @private
	 */
	,onClick:function(e, target) {

		// collect all variables for callback and/or events
		var t = e.getTarget('div.ux-cell-action');
		var row = e.getTarget('.x-grid3-row');
		var col = this.view.findCellIndex(target.parentNode.parentNode);
		var c = this.grid.getColumnModel().config[col];
		var record, dataIndex, value, action;
		if(t) {
			record = this.grid.store.getAt(row.rowIndex);
			dataIndex = c.dataIndex;
			value = record.get(dataIndex);
			action = t.className.replace(/ux-cell-action /, '');
		}

		// check if we've collected all necessary variables
		if(false !== row && false !== col && record && dataIndex && action) {

			// call callback if any
			if(this.callbacks && 'function' === typeof this.callbacks[action]) {
				this.callbacks[action](this.grid, record, action, value, row.rowIndex, col);
			}

			// fire events
			if(true !== this.eventsSuspended && false === this.fireEvent('beforeaction', this.grid, record, action, value, dataIndex, row.rowIndex, col)) {
				return;
			}
			else if(true !== this.eventsSuspended) {
				this.fireEvent('action', this.grid, record, action, value, dataIndex, row.rowIndex, col);
			}

		}
	} // eo function onClick
	// }}}

});

// register xtype
Ext.reg('cellactions', Ext.ux.grid.CellActions);

// eof



 /*JS File: ../js/ext/ux/Ext.ux.SliderTip.js*/ 


 /**
 * @class Ext.ux.SliderTip
* @extends Ext.Tip
 * Simple plugin for using an Ext.Tip with a slider to show the slider value
 * stolen from the Ext Slider Example http://extjs.com/deploy/dev/examples/slider/slider.html
 */
 
Ext.ux.SliderTip = Ext.extend(Ext.Tip, {
 minWidth: 10,
 offsets : [0, -10],
 init : function(slider){
 slider.on('dragstart', this.onSlide, this);
 slider.on('drag', this.onSlide, this);
 slider.on('dragend', this.hide, this);
 slider.on('destroy', this.destroy, this);
 },

 onSlide : function(slider){
 this.show();
 this.body.update(this.getText(slider));
 this.doAutoWidth();
 this.el.alignTo(slider.thumb, 'b-t?', this.offsets);
 },

 getText : function(slider){
 return slider.getValue();
 }
});


 /*JS File: ../js/ext/ux/Ext.ux.ColorField.js*/ 


 /**
 * @class Ext.ux.ColorField
 * @extends Ext.form.TriggerField
 * Provides a very simple color form field with a ColorMenu dropdown.
 * Values are stored as a six-character hex value without the '#'.
 * I.e. 'ffffff'
 * @constructor
 * Create a new ColorField
 * <br />Example:
 * <pre><code>
var cf = new Ext.ux.ColorField({
	fieldLabel: 'Color',
	hiddenName:'pref_sales',
	showHexValue:true
});
</code></pre>
 * @param {Object} config
 */
 
Ext.ux.ColorField = function(config){
    Ext.ux.ColorField.superclass.constructor.call(this, config);
	this.on('render', this.handleRender);
};

Ext.extend(Ext.ux.ColorField, Ext.form.TriggerField,  {
   initComponent: function(){
    this.addEvents({
      "select": true
    })
   },
    /**
     * @cfg {Boolean} showHexValue
     * True to display the HTML Hexidecimal Color Value in the field
     * so it is manually editable.
     */
    showHexValue : false,
	
	/**
     * @cfg {String} triggerClass
     * An additional CSS class used to style the trigger button.  The trigger will always get the
     * class 'x-form-trigger' and triggerClass will be <b>appended</b> if specified (defaults to 'x-form-color-trigger'
     * which displays a calendar icon).
     */
    triggerClass : 'x-form-color-trigger',
	
    /**
     * @cfg {String/Object} autoCreate
     * A DomHelper element spec, or true for a default element spec (defaults to
     * {tag: "input", type: "text", size: "10", autocomplete: "off"})
     */
    // private
    defaultAutoCreate : {tag: "input", type: "text", size: "10",
						 autocomplete: "off", maxlength:"6"},
	
	/**
	 * @cfg {String} lengthText
	 * A string to be displayed when the length of the input field is
	 * not 3 or 6, i.e. 'fff' or 'ffccff'.
	 */
	lengthText: "Color hex values must be either 3 or 6 characters.",
	
	//text to use if blank and allowBlank is false
	blankText: "Must have a hexidecimal value in the format ABCDEF.",
	
	/**
	 * @cfg {String} color
	 * A string hex value to be used as the default color.  Defaults
	 * to 'FFFFFF' (white).
	 */
	defaultColor: 'FFFFFF',
	
	maskRe: /[a-f0-9]/i,
	// These regexes limit input and validation to hex values
	regex: /[a-f0-9]/i,

	//private
	curColor: 'ffffff',
	
    // private
    validateValue : function(value){
		if(!this.showHexValue) {
			return true;
		}
		if(value.length<1) {
			this.el.setStyle({
				'background-color':'#' + this.defaultColor
			});
			if(!this.allowBlank) {
				this.markInvalid(String.format(this.blankText, value));
				return false
			}
			return true;
		}
		if(value.length!=3 && value.length!=6 ) {
			this.markInvalid(String.format(this.lengthText, value));
			return false;
		}
		this.setColor(value);
        return true;
    },

    // private
    validateBlur : function(){
        return !this.menu || !this.menu.isVisible();
    },
	
	// Manually apply the invalid line image since the background
	// was previously cleared so the color would show through.
	markInvalid : function( msg ) {
		Ext.ux.ColorField.superclass.markInvalid.call(this, msg);
		this.el.setStyle({
			'background-image': 'url(../theme/images/default/grid/invalid_line.gif)'
		});
	},

    /**
     * Returns the current color value of the color field
     * @return {String} value The hexidecimal color value
     */
    getValue : function(){
		return this.curValue || this.defaultValue || "FFFFFF";
    },

    /**
     * Sets the value of the color field.  Format as hex value 'FFFFFF'
     * without the '#'.
     * @param {String} hex The color value
     */
    setValue : function(hex){

		Ext.ux.ColorField.superclass.setValue.call(this, hex);
		this.setColor(hex);
    },
	
	/**
	 * Sets the current color and changes the background.
	 * Does *not* change the value of the field.
	 * @param {String} hex The color value.
	 */
	setColor : function(hex) {
		this.curColor = hex;
		
		this.el.setStyle( {
			'background-color': '#' + hex,
			'background-image': 'none'
		});
		if(!this.showHexValue) {
			this.el.setStyle({
				'text-indent': '-100px'
			});
			if(Ext.isIE) {
				this.el.setStyle({
					'margin-left': '100px'
				});
			}
		}
	},
	
	handleRender: function() {
		this.setDefaultColor();
	},
	
	setDefaultColor : function() {
		this.setValue(this.defaultColor);
	},

    // private
    menuListeners : {
        select: function(m, d){
            this.setValue(d);
        },
        show : function(){ // retain focus styling
            this.onFocus();
        },
        hide : function(){
            this.focus();
            var ml = this.menuListeners;
            this.menu.un("select", ml.select,  this);
            this.menu.un("show", ml.show,  this);
            this.menu.un("hide", ml.hide,  this);
        }
    },
	
	//private
	handleSelect : function(palette, selColor) {
    this.fireEvent("select",palette,selColor);
		this.setValue(selColor);
	},

    // private
    // Implements the default empty TriggerField.onTriggerClick function to display the ColorPicker
    onTriggerClick : function(){
        if(this.disabled){
            return;
        }
        if(this.menu == null){
            this.menu = new Ext.menu.ColorMenu();
			this.menu.palette.on('select', this.handleSelect, this );
        }
        this.menu.on(Ext.apply({}, this.menuListeners, {
            scope:this
        }));
        this.menu.show(this.el, "tl-bl?");
    }
});

Ext.reg("colorfield",Ext.ux.ColorField)


 /*JS File: ../js/drawing/tools.js*/ 


   Ax.ToolItem = Ext.extend(Ext.Component,{
  tool: "",
  imgclass: "",
  selected: false,
  onSelect: function(){},
  onUnselect: function(){},
  
  unselect: function(nofire){
	this.selected = false;
  this.el.dom.className = "toolboxItem"
	if(nofire!=true){
  this.onUnselect(this);
  }
  },
  select: function(nofire){
    this.el.dom.className = "toolboxItem"; //remove all classes except the standard one
    this.el.addClass("tbx_sel");
    this.selected = true
    if(nofire!=true){
			this.onSelect(this);
    }
  },
  initComponents: function(){
  Ax.ToolItem.superclass.initComponent.apply(this, arguments);
  },
  handleMouseEvents: function(event,del){
  
    //console.log(arguments)
    if(!this.el.hasClass("tbx_sel")){
    //If it is not selected
    this.el.dom.className = "toolboxItem"; //remove all classes except the standard one
    switch(event.type){
    case "mouseover":
    this.el.addClass("tbx_ovr")
    break;
    case "mouseout":
    this.el.addClass("tbx_idl")
    break;
    case "mousedown":
		//Ax.gs(9)
    this.onSelect(this);
    this.el.addClass("tbx_sel");
    this.selected = true
    break;
    }
    }else{
	//you shouldn't be able to not select any tool.
	
    //switch(event.type){
    //case "mousedown":
	//this.onUnselect(this);
    //this.el.dom.className = "toolboxItem";
    //this.selected = false;

    //}
    //If it is already selected
     }
  },
  onRender: function(ct){
  if(!this.template){
  this.template = new Ext.Template(
  //'<div id="{tool}" class="toolboxItem tbx_idl">',
  '<div class="toolboxButton {imgclass}"></div>');
  }
  if(!this.el){
  this.el = ct.createChild()
  }
  
  this.template.append(this.el,{tool: this.tool, imgclass: this.imgclass})
  
  
  this.el.dom.className = "toolboxItem tbx_idl"; //idle/toolbox
  
  
  this.el.on("mousedown",this.handleMouseEvents,this)
  this.el.on("mouseover",this.handleMouseEvents,this)
  this.el.on("mouseout",this.handleMouseEvents,this)
  
  if(this.qtip){
  //console.log(this.qtip)
  Ext.QuickTips.register({
    target: this.el.dom.firstChild,
    title: 'Draw Tools',
    text: this.qtip
    //dismissDelay: 20
  });
  }

  }
  
  })
  
  Ext.reg("tbxitem",Ax.ToolItem)


 /*JS File: ../js/drawing/toolbox.js*/ 


 Ax.toolConfig={
	"select":      ["tx_select","Select Shapes","Select"],
	"rect":        ["tx_rectangle","Draw Rectangle","Rectangle"],
	"roundrect":   ["tx_roundrect","Draw Rounded Rectangle","Round Rectangle"],
	"ellipse":     ["tx_circle","Draw Ellipse/Circle","Ellipse/Circle"],
	"line":        ["tx_line","Draw Line","Line"],
	"path":        ["tx_path","Draw freeform path","Freeform Path"],
	"controlpath": ["tx_polygon","Draw Polygon","Polygon"],
	"text":        ["tx_text","Draw text","Text"],
	"image":       ["tx_image", "Draw Image/Picture","Image"],

	"shape":       ["tx_shape","Add a Shape from library","Library"],
	"reset":       ["tx_reset","Reset/Clear/Empty Frame","Reset"],
	"delete":      ["tx_delete","Delete selected shape","Delete"]
}

Ax.ToolsPanel = Ext.extend(Ext.Panel,{

changeTool: function(tool){
Ax.setTool(tool.tool);
},

initComponent: function(){
var ia = []
for(var tool in Ax.toolConfig){


ia.push(new Ax.ToolItem({
tool:tool,
id: "tool_"+ tool,
toolConfig: Ax.toolConfig,
qtip: Ax.toolConfig[tool][1],
imgclass:Ax.toolConfig[tool][0], //ooh! gets the toolbox icons dir, and adds it to the stuff
onSelect: this.changeTool
}))
	
}
  
  
Ext.apply(this,{
layout: "table",
border: false,
layoutConfig: {
        // The total column count must be specified here
        columns: 2
    },
	items: ia
  })

   Ax.ToolsPanel.superclass.initComponent.apply(this, arguments);//i dont really know what that does
  }
  })
  
  Ext.reg("toolbox",Ax.ToolsPanel)
  
  
  
  

  
  



 /*JS File: ../js/drawing/colorpanel.js*/ 


 Ax.defaultcolor = {
  line: "000000",
  fill:"FF0000",
  width: 1, //okay, so width isn't really a color..
  grid: 1 //this isn't really a color either
}

Ax.Color = {
  update: function(){},
  line: Ax.defaultcolor.line,
  fill: Ax.defaultcolor.fill,
  width: Ax.defaultcolor.width,//okay, so width isn't really a color
  grid: Ax.defaultcolor.grid   //this is *my* _fav_ color.
}                           

Ax.setColors = function(c){
  //its probably bad to not use those pesky braces
  if (c.gd) { //grid
  	Ax.viewport.findById("fgd").setValue(c.gd)
  }
  if (c.lw) { //linewidth (stoke)
  	Ax.viewport.findById("flw").setValue(c.lw)
  }
  if (c.lc) {//linecolor (stroke)
  	Ax.viewport.findById("flc").setColor(c.lc)
  }
  if(c.fc){ //fill color
   Ax.viewport.findById("ffc").setColor(c.fc)
  }
}

Ax.ColorPanel = Ext.extend(Ext.Panel,{
  initComponent: function(){
    this.LWTip = new Ext.ux.SliderTip({
      getText: function(slider){
        return String.format('Line Width: {0}px', slider.getValue());
      }
    })
    this.GDTip = new Ext.ux.SliderTip({
      getText: function(slider){
        
        return String.format('Snapping Grid Size: {0}px', slider.getValue()+1);
      }
    })
    Ext.apply(this,{
    border: false,
    items: [
      {xtype: "label",style: "font-size: xx-small; margin-left: 3px", text: "Line"},
      {xtype: "slider", id: "flw",maxValue: 20,plugins: this.LWTip, value: Ax.Color.width, listeners: {
        "drag":function(slider,event){
          Ax.Color.width = slider.getValue(); //huh? width isn't a color? you're crazy
          Ax.Color.update("lw");
        }
      }},
      {xtype: "colorfield", id: "flc", width: 48, defaultColor:Ax.Color.line, listeners: {
        "select":function(palette,hex){
        Ax.Color.line = hex;
        Ax.Color.update("lc");
        }
      }},
      {xtype: "label",style: "font-size: xx-small; margin-left: 3px", text: "Fill"},
      {xtype: "colorfield", id: "ffc",width: 48, defaultColor:Ax.Color.fill, listeners: {
        "select":function(palette,hex){
        Ax.Color.fill = hex;
        Ax.Color.update("fc");
        }
      }},
      {xtype: "label",style: "font-size: xx-small; margin-left: 3px", text: "Grid"},
      {xtype: "slider", maxValue: 30, id: "fgd", plugins: this.GDTip, value: Ax.Color.grid, listeners: {
        "drag":function(slider,event){
          Ax.Color.grid = slider.getValue()+1; //huh? width isn't a color? you're crazy
          //trick it into having 1px being the minimum
          Ax.Color.update("gd");
        }
      }}
    ]
    })
    Ax.ColorPanel.superclass.initComponent.apply(this, arguments);
  }
})
Ext.reg("drawpanel",Ax.ColorPanel)




 /*JS File: ../js/drawing/onlypaths/sylvester.js*/ 


 // === Sylvester ===
// Vector and Matrix mathematics modules for JavaScript
// Copyright (c) 2007 James Coglan
// 
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
// 
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

var Sylvester = {
  version: '0.1.3',
  precision: 1e-6
};

function Vector() {}
Vector.prototype = {

  // Returns element i of the vector
  e: function(i) {
    return (i < 1 || i > this.elements.length) ? null : this.elements[i-1];
  },

  // Returns the number of elements the vector has
  dimensions: function() {
    return this.elements.length;
  },

  // Returns the modulus ('length') of the vector
  modulus: function() {
    return Math.sqrt(this.dot(this));
  },

  // Returns true iff the vector is equal to the argument
  eql: function(vector) {
    var n = this.elements.length;
    var V = vector.elements || vector;
    if (n != V.length) { return false; }
    do {
      if (Math.abs(this.elements[n-1] - V[n-1]) > Sylvester.precision) { return false; }
    } while (--n);
    return true;
  },

  // Returns a copy of the vector
  dup: function() {
    return Vector.create(this.elements);
  },

  // Maps the vector to another vector according to the given function
  map: function(fn) {
    var elements = [];
    this.each(function(x, i) {
      elements.push(fn(x, i));
    });
    return Vector.create(elements);
  },
  
  // Calls the iterator for each element of the vector in turn
  each: function(fn) {
    var n = this.elements.length, k = n, i;
    do { i = k - n;
      fn(this.elements[i], i+1);
    } while (--n);
  },

  // Returns a new vector created by normalizing the receiver
  toUnitVector: function() {
    var r = this.modulus();
    if (r === 0) { return this.dup(); }
    return this.map(function(x) { return x/r; });
  },

  // Returns the angle between the vector and the argument (also a vector)
  angleFrom: function(vector) {
    var V = vector.elements || vector;
    var n = this.elements.length, k = n, i;
    if (n != V.length) { return null; }
    var dot = 0, mod1 = 0, mod2 = 0;
    // Work things out in parallel to save time
    this.each(function(x, i) {
      dot += x * V[i-1];
      mod1 += x * x;
      mod2 += V[i-1] * V[i-1];
    });
    mod1 = Math.sqrt(mod1); mod2 = Math.sqrt(mod2);
    if (mod1*mod2 === 0) { return null; }
    var theta = dot / (mod1*mod2);
    if (theta < -1) { theta = -1; }
    if (theta > 1) { theta = 1; }
    return Math.acos(theta);
  },

  // Returns true iff the vector is parallel to the argument
  isParallelTo: function(vector) {
    var angle = this.angleFrom(vector);
    return (angle === null) ? null : (angle <= Sylvester.precision);
  },

  // Returns true iff the vector is antiparallel to the argument
  isAntiparallelTo: function(vector) {
    var angle = this.angleFrom(vector);
    return (angle === null) ? null : (Math.abs(angle - Math.PI) <= Sylvester.precision);
  },

  // Returns true iff the vector is perpendicular to the argument
  isPerpendicularTo: function(vector) {
    var dot = this.dot(vector);
    return (dot === null) ? null : (Math.abs(dot) <= Sylvester.precision);
  },

  // Returns the result of adding the argument to the vector
  add: function(vector) {
    var V = vector.elements || vector;
    if (this.elements.length != V.length) { return null; }
    return this.map(function(x, i) { return x + V[i-1]; });
  },

  // Returns the result of subtracting the argument from the vector
  subtract: function(vector) {
    var V = vector.elements || vector;
    if (this.elements.length != V.length) { return null; }
    return this.map(function(x, i) { return x - V[i-1]; });
  },

  // Returns the result of multiplying the elements of the vector by the argument
  multiply: function(k) {
    return this.map(function(x) { return x*k; });
  },

  x: function(k) { return this.multiply(k); },

  // Returns the scalar product of the vector with the argument
  // Both vectors must have equal dimensionality
  dot: function(vector) {
    var V = vector.elements || vector;
    var i, product = 0, n = this.elements.length;
    if (n != V.length) { return null; }
    do { product += this.elements[n-1] * V[n-1]; } while (--n);
    return product;
  },

  // Returns the vector product of the vector with the argument
  // Both vectors must have dimensionality 3
  cross: function(vector) {
    var B = vector.elements || vector;
    if (this.elements.length != 3 || B.length != 3) { return null; }
    var A = this.elements;
    return Vector.create([
      (A[1] * B[2]) - (A[2] * B[1]),
      (A[2] * B[0]) - (A[0] * B[2]),
      (A[0] * B[1]) - (A[1] * B[0])
    ]);
  },

  // Returns the (absolute) largest element of the vector
  max: function() {
    var m = 0, n = this.elements.length, k = n, i;
    do { i = k - n;
      if (Math.abs(this.elements[i]) > Math.abs(m)) { m = this.elements[i]; }
    } while (--n);
    return m;
  },

  // Returns the index of the first match found
  indexOf: function(x) {
    var index = null, n = this.elements.length, k = n, i;
    do { i = k - n;
      if (index === null && this.elements[i] == x) {
        index = i + 1;
      }
    } while (--n);
    return index;
  },

  // Returns a diagonal matrix with the vector's elements as its diagonal elements
  toDiagonalMatrix: function() {
    return Matrix.Diagonal(this.elements);
  },

  // Returns the result of rounding the elements of the vector
  round: function() {
    return this.map(function(x) { return Math.round(x); });
  },

  // Returns a copy of the vector with elements set to the given value if they
  // differ from it by less than Sylvester.precision
  snapTo: function(x) {
    return this.map(function(y) {
      return (Math.abs(y - x) <= Sylvester.precision) ? x : y;
    });
  },

  // Returns the vector's distance from the argument, when considered as a point in space
  distanceFrom: function(obj) {
    if (obj.anchor) { return obj.distanceFrom(this); }
    var V = obj.elements || obj;
    if (V.length != this.elements.length) { return null; }
    var sum = 0, part;
    this.each(function(x, i) {
      part = x - V[i-1];
      sum += part * part;
    });
    return Math.sqrt(sum);
  },

  // Returns true if the vector is point on the given line
  liesOn: function(line) {
    return line.contains(this);
  },

  // Return true iff the vector is a point in the given plane
  liesIn: function(plane) {
    return plane.contains(this);
  },

  // Rotates the vector about the given object. The object should be a 
  // point if the vector is 2D, and a line if it is 3D. Be careful with line directions!
  rotate: function(t, obj) {
    var V, R, x, y, z;
    switch (this.elements.length) {
      case 2:
        V = obj.elements || obj;
        if (V.length != 2) { return null; }
        R = Matrix.Rotation(t).elements;
        x = this.elements[0] - V[0];
        y = this.elements[1] - V[1];
        return Vector.create([
          V[0] + R[0][0] * x + R[0][1] * y,
          V[1] + R[1][0] * x + R[1][1] * y
        ]);
        break;
      case 3:
        if (!obj.direction) { return null; }
        var C = obj.pointClosestTo(this).elements;
        R = Matrix.Rotation(t, obj.direction).elements;
        x = this.elements[0] - C[0];
        y = this.elements[1] - C[1];
        z = this.elements[2] - C[2];
        return Vector.create([
          C[0] + R[0][0] * x + R[0][1] * y + R[0][2] * z,
          C[1] + R[1][0] * x + R[1][1] * y + R[1][2] * z,
          C[2] + R[2][0] * x + R[2][1] * y + R[2][2] * z
        ]);
        break;
      default:
        return null;
    }
  },

  // Returns the result of reflecting the point in the given point, line or plane
  reflectionIn: function(obj) {
    if (obj.anchor) {
      // obj is a plane or line
      var P = this.elements.slice();
      var C = obj.pointClosestTo(P).elements;
      return Vector.create([C[0] + (C[0] - P[0]), C[1] + (C[1] - P[1]), C[2] + (C[2] - (P[2] || 0))]);
    } else {
      // obj is a point
      var Q = obj.elements || obj;
      if (this.elements.length != Q.length) { return null; }
      return this.map(function(x, i) { return Q[i-1] + (Q[i-1] - x); });
    }
  },

  // Utility to make sure vectors are 3D. If they are 2D, a zero z-component is added
  to3D: function() {
    var V = this.dup();
    switch (V.elements.length) {
      case 3: break;
      case 2: V.elements.push(0); break;
      default: return null;
    }
    return V;
  },

  // Returns a string representation of the vector
  inspect: function() {
    return '[' + this.elements.join(', ') + ']';
  },

  // Set vector's elements from an array
  setElements: function(els) {
    this.elements = (els.elements || els).slice();
    return this;
  }
};
  
// Constructor function
Vector.create = function(elements) {
  var V = new Vector();
  return V.setElements(elements);
};

// i, j, k unit vectors
Vector.i = Vector.create([1,0,0]);
Vector.j = Vector.create([0,1,0]);
Vector.k = Vector.create([0,0,1]);

// Random vector of size n
Vector.Random = function(n) {
  var elements = [];
  do { elements.push(Math.random());
  } while (--n);
  return Vector.create(elements);
};

// Vector filled with zeros
Vector.Zero = function(n) {
  var elements = [];
  do { elements.push(0);
  } while (--n);
  return Vector.create(elements);
};



function Matrix() {}
Matrix.prototype = {

  // Returns element (i,j) of the matrix
  e: function(i,j) {
    if (i < 1 || i > this.elements.length || j < 1 || j > this.elements[0].length) { return null; }
    return this.elements[i-1][j-1];
  },

  // Returns row k of the matrix as a vector
  row: function(i) {
    if (i > this.elements.length) { return null; }
    return Vector.create(this.elements[i-1]);
  },

  // Returns column k of the matrix as a vector
  col: function(j) {
    if (j > this.elements[0].length) { return null; }
    var col = [], n = this.elements.length, k = n, i;
    do { i = k - n;
      col.push(this.elements[i][j-1]);
    } while (--n);
    return Vector.create(col);
  },

  // Returns the number of rows/columns the matrix has
  dimensions: function() {
    return {rows: this.elements.length, cols: this.elements[0].length};
  },

  // Returns the number of rows in the matrix
  rows: function() {
    return this.elements.length;
  },

  // Returns the number of columns in the matrix
  cols: function() {
    return this.elements[0].length;
  },

  // Returns true iff the matrix is equal to the argument. You can supply
  // a vector as the argument, in which case the receiver must be a
  // one-column matrix equal to the vector.
  eql: function(matrix) {
    var M = matrix.elements || matrix;
    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
    if (this.elements.length != M.length ||
        this.elements[0].length != M[0].length) { return false; }
    var ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
    do { i = ki - ni;
      nj = kj;
      do { j = kj - nj;
        if (Math.abs(this.elements[i][j] - M[i][j]) > Sylvester.precision) { return false; }
      } while (--nj);
    } while (--ni);
    return true;
  },

  // Returns a copy of the matrix
  dup: function() {
    return Matrix.create(this.elements);
  },

  // Maps the matrix to another matrix (of the same dimensions) according to the given function
  map: function(fn) {
    var els = [], ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
    do { i = ki - ni;
      nj = kj;
      els[i] = [];
      do { j = kj - nj;
        els[i][j] = fn(this.elements[i][j], i + 1, j + 1);
      } while (--nj);
    } while (--ni);
    return Matrix.create(els);
  },

  // Returns true iff the argument has the same dimensions as the matrix
  isSameSizeAs: function(matrix) {
    var M = matrix.elements || matrix;
    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
    return (this.elements.length == M.length &&
        this.elements[0].length == M[0].length);
  },

  // Returns the result of adding the argument to the matrix
  add: function(matrix) {
    var M = matrix.elements || matrix;
    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
    if (!this.isSameSizeAs(M)) { return null; }
    return this.map(function(x, i, j) { return x + M[i-1][j-1]; });
  },

  // Returns the result of subtracting the argument from the matrix
  subtract: function(matrix) {
    var M = matrix.elements || matrix;
    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
    if (!this.isSameSizeAs(M)) { return null; }
    return this.map(function(x, i, j) { return x - M[i-1][j-1]; });
  },

  // Returns true iff the matrix can multiply the argument from the left
  canMultiplyFromLeft: function(matrix) {
    var M = matrix.elements || matrix;
    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
    // this.columns should equal matrix.rows
    return (this.elements[0].length == M.length);
  },

  // Returns the result of multiplying the matrix from the right by the argument.
  // If the argument is a scalar then just multiply all the elements. If the argument is
  // a vector, a vector is returned, which saves you having to remember calling
  // col(1) on the result.
  multiply: function(matrix) {
    if (!matrix.elements) {
      return this.map(function(x) { return x * matrix; });
    }
    var returnVector = matrix.modulus ? true : false;
    var M = matrix.elements || matrix;
    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
    if (!this.canMultiplyFromLeft(M)) { return null; }
    var ni = this.elements.length, ki = ni, i, nj, kj = M[0].length, j;
    var cols = this.elements[0].length, elements = [], sum, nc, c;
    do { i = ki - ni;
      elements[i] = [];
      nj = kj;
      do { j = kj - nj;
        sum = 0;
        nc = cols;
        do { c = cols - nc;
          sum += this.elements[i][c] * M[c][j];
        } while (--nc);
        elements[i][j] = sum;
      } while (--nj);
    } while (--ni);
    var M = Matrix.create(elements);
    return returnVector ? M.col(1) : M;
  },

  x: function(matrix) { return this.multiply(matrix); },

  // Returns a submatrix taken from the matrix
  // Argument order is: start row, start col, nrows, ncols
  // Element selection wraps if the required index is outside the matrix's bounds, so you could
  // use this to perform row/column cycling or copy-augmenting.
  minor: function(a, b, c, d) {
    var elements = [], ni = c, i, nj, j;
    var rows = this.elements.length, cols = this.elements[0].length;
    do { i = c - ni;
      elements[i] = [];
      nj = d;
      do { j = d - nj;
        elements[i][j] = this.elements[(a+i-1)%rows][(b+j-1)%cols];
      } while (--nj);
    } while (--ni);
    return Matrix.create(elements);
  },

  // Returns the transpose of the matrix
  transpose: function() {
    var rows = this.elements.length, cols = this.elements[0].length;
    var elements = [], ni = cols, i, nj, j;
    do { i = cols - ni;
      elements[i] = [];
      nj = rows;
      do { j = rows - nj;
        elements[i][j] = this.elements[j][i];
      } while (--nj);
    } while (--ni);
    return Matrix.create(elements);
  },

  // Returns true iff the matrix is square
  isSquare: function() {
    return (this.elements.length == this.elements[0].length);
  },

  // Returns the (absolute) largest element of the matrix
  max: function() {
    var m = 0, ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
    do { i = ki - ni;
      nj = kj;
      do { j = kj - nj;
        if (Math.abs(this.elements[i][j]) > Math.abs(m)) { m = this.elements[i][j]; }
      } while (--nj);
    } while (--ni);
    return m;
  },

  // Returns the indeces of the first match found by reading row-by-row from left to right
  indexOf: function(x) {
    var index = null, ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
    do { i = ki - ni;
      nj = kj;
      do { j = kj - nj;
        if (this.elements[i][j] == x) { return {i: i+1, j: j+1}; }
      } while (--nj);
    } while (--ni);
    return null;
  },

  // If the matrix is square, returns the diagonal elements as a vector.
  // Otherwise, returns null.
  diagonal: function() {
    if (!this.isSquare) { return null; }
    var els = [], n = this.elements.length, k = n, i;
    do { i = k - n;
      els.push(this.elements[i][i]);
    } while (--n);
    return Vector.create(els);
  },

  // Make the matrix upper (right) triangular by Gaussian elimination.
  // This method only adds multiples of rows to other rows. No rows are
  // scaled up or switched, and the determinant is preserved.
  toRightTriangular: function() {
    var M = this.dup(), els;
    var n = this.elements.length, k = n, i, np, kp = this.elements[0].length, p;
    do { i = k - n;
      if (M.elements[i][i] == 0) {
        for (j = i + 1; j < k; j++) {
          if (M.elements[j][i] != 0) {
            els = []; np = kp;
            do { p = kp - np;
              els.push(M.elements[i][p] + M.elements[j][p]);
            } while (--np);
            M.elements[i] = els;
            break;
          }
        }
      }
      if (M.elements[i][i] != 0) {
        for (j = i + 1; j < k; j++) {
          var multiplier = M.elements[j][i] / M.elements[i][i];
          els = []; np = kp;
          do { p = kp - np;
            // Elements with column numbers up to an including the number
            // of the row that we're subtracting can safely be set straight to
            // zero, since that's the point of this routine and it avoids having
            // to loop over and correct rounding errors later
            els.push(p <= i ? 0 : M.elements[j][p] - M.elements[i][p] * multiplier);
          } while (--np);
          M.elements[j] = els;
        }
      }
    } while (--n);
    return M;
  },

  toUpperTriangular: function() { return this.toRightTriangular(); },

  // Returns the determinant for square matrices
  determinant: function() {
    if (!this.isSquare()) { return null; }
    var M = this.toRightTriangular();
    var det = M.elements[0][0], n = M.elements.length - 1, k = n, i;
    do { i = k - n + 1;
      det = det * M.elements[i][i];
    } while (--n);
    return det;
  },

  det: function() { return this.determinant(); },

  // Returns true iff the matrix is singular
  isSingular: function() {
    return (this.isSquare() && this.determinant() === 0);
  },

  // Returns the trace for square matrices
  trace: function() {
    if (!this.isSquare()) { return null; }
    var tr = this.elements[0][0], n = this.elements.length - 1, k = n, i;
    do { i = k - n + 1;
      tr += this.elements[i][i];
    } while (--n);
    return tr;
  },

  tr: function() { return this.trace(); },

  // Returns the rank of the matrix
  rank: function() {
    var M = this.toRightTriangular(), rank = 0;
    var ni = this.elements.length, ki = ni, i, nj, kj = this.elements[0].length, j;
    do { i = ki - ni;
      nj = kj;
      do { j = kj - nj;
        if (Math.abs(M.elements[i][j]) > Sylvester.precision) { rank++; break; }
      } while (--nj);
    } while (--ni);
    return rank;
  },
  
  rk: function() { return this.rank(); },

  // Returns the result of attaching the given argument to the right-hand side of the matrix
  augment: function(matrix) {
    var M = matrix.elements || matrix;
    if (typeof(M[0][0]) == 'undefined') { M = Matrix.create(M).elements; }
    var T = this.dup(), cols = T.elements[0].length;
    var ni = T.elements.length, ki = ni, i, nj, kj = M[0].length, j;
    if (ni != M.length) { return null; }
    do { i = ki - ni;
      nj = kj;
      do { j = kj - nj;
        T.elements[i][cols + j] = M[i][j];
      } while (--nj);
    } while (--ni);
    return T;
  },

  // Returns the inverse (if one exists) using Gauss-Jordan
  inverse: function() {
    if (!this.isSquare() || this.isSingular()) { return null; }
    var ni = this.elements.length, ki = ni, i, j;
    var M = this.augment(Matrix.I(ni)).toRightTriangular();
    var np, kp = M.elements[0].length, p, els, divisor;
    var inverse_elements = [], new_element;
    // Matrix is non-singular so there will be no zeros on the diagonal
    // Cycle through rows from last to first
    do { i = ni - 1;
      // First, normalise diagonal elements to 1
      els = []; np = kp;
      inverse_elements[i] = [];
      divisor = M.elements[i][i];
      do { p = kp - np;
        new_element = M.elements[i][p] / divisor;
        els.push(new_element);
        // Shuffle of the current row of the right hand side into the results
        // array as it will not be modified by later runs through this loop
        if (p >= ki) { inverse_elements[i].push(new_element); }
      } while (--np);
      M.elements[i] = els;
      // Then, subtract this row from those above it to
      // give the identity matrix on the left hand side
      for (j = 0; j < i; j++) {
        els = []; np = kp;
        do { p = kp - np;
          els.push(M.elements[j][p] - M.elements[i][p] * M.elements[j][i]);
        } while (--np);
        M.elements[j] = els;
      }
    } while (--ni);
    return Matrix.create(inverse_elements);
  },

  inv: function() { return this.inverse(); },

  // Returns the result of rounding all the elements
  round: function() {
    return this.map(function(x) { return Math.round(x); });
  },

  // Returns a copy of the matrix with elements set to the given value if they
  // differ from it by less than Sylvester.precision
  snapTo: function(x) {
    return this.map(function(p) {
      return (Math.abs(p - x) <= Sylvester.precision) ? x : p;
    });
  },

  // Returns a string representation of the matrix
  inspect: function() {
    var matrix_rows = [];
    var n = this.elements.length, k = n, i;
    do { i = k - n;
      matrix_rows.push(Vector.create(this.elements[i]).inspect());
    } while (--n);
    return matrix_rows.join('\n');
  },

  // Set the matrix's elements from an array. If the argument passed
  // is a vector, the resulting matrix will be a single column.
  setElements: function(els) {
    var i, elements = els.elements || els;
    if (typeof(elements[0][0]) != 'undefined') {
      var ni = elements.length, ki = ni, nj, kj, j;
      this.elements = [];
      do { i = ki - ni;
        nj = elements[i].length; kj = nj;
        this.elements[i] = [];
        do { j = kj - nj;
          this.elements[i][j] = elements[i][j];
        } while (--nj);
      } while(--ni);
      return this;
    }
    var n = elements.length, k = n;
    this.elements = [];
    do { i = k - n;
      this.elements.push([elements[i]]);
    } while (--n);
    return this;
  }
};

// Constructor function
Matrix.create = function(elements) {
  var M = new Matrix();
  return M.setElements(elements);
};

// Identity matrix of size n
Matrix.I = function(n) {
  var els = [], k = n, i, nj, j;
  do { i = k - n;
    els[i] = []; nj = k;
    do { j = k - nj;
      els[i][j] = (i == j) ? 1 : 0;
    } while (--nj);
  } while (--n);
  return Matrix.create(els);
};

// Diagonal matrix - all off-diagonal elements are zero
Matrix.Diagonal = function(elements) {
  var n = elements.length, k = n, i;
  var M = Matrix.I(n);
  do { i = k - n;
    M.elements[i][i] = elements[i];
  } while (--n);
  return M;
};

// Rotation matrix about some axis. If no axis is
// supplied, assume we're after a 2D transform
Matrix.Rotation = function(theta, a) {
  if (!a) {
    return Matrix.create([
      [Math.cos(theta),  -Math.sin(theta)],
      [Math.sin(theta),   Math.cos(theta)]
    ]);
  }
  var axis = a.dup();
  if (axis.elements.length != 3) { return null; }
  var mod = axis.modulus();
  var x = axis.elements[0]/mod, y = axis.elements[1]/mod, z = axis.elements[2]/mod;
  var s = Math.sin(theta), c = Math.cos(theta), t = 1 - c;
  // Formula derived here: http://www.gamedev.net/reference/articles/article1199.asp
  // That proof rotates the co-ordinate system so theta
  // becomes -theta and sin becomes -sin here.
  return Matrix.create([
    [ t*x*x + c, t*x*y - s*z, t*x*z + s*y ],
    [ t*x*y + s*z, t*y*y + c, t*y*z - s*x ],
    [ t*x*z - s*y, t*y*z + s*x, t*z*z + c ]
  ]);
};

// Special case rotations
Matrix.RotationX = function(t) {
  var c = Math.cos(t), s = Math.sin(t);
  return Matrix.create([
    [  1,  0,  0 ],
    [  0,  c, -s ],
    [  0,  s,  c ]
  ]);
};
Matrix.RotationY = function(t) {
  var c = Math.cos(t), s = Math.sin(t);
  return Matrix.create([
    [  c,  0,  s ],
    [  0,  1,  0 ],
    [ -s,  0,  c ]
  ]);
};
Matrix.RotationZ = function(t) {
  var c = Math.cos(t), s = Math.sin(t);
  return Matrix.create([
    [  c, -s,  0 ],
    [  s,  c,  0 ],
    [  0,  0,  1 ]
  ]);
};

// Random matrix of n rows, m columns
Matrix.Random = function(n, m) {
  return Matrix.Zero(n, m).map(
    function() { return Math.random(); }
  );
};

// Matrix filled with zeros
Matrix.Zero = function(n, m) {
  var els = [], ni = n, i, nj, j;
  do { i = n - ni;
    els[i] = [];
    nj = m;
    do { j = m - nj;
      els[i][j] = 0;
    } while (--nj);
  } while (--ni);
  return Matrix.create(els);
};



function Line() {}
Line.prototype = {

  // Returns true if the argument occupies the same space as the line
  eql: function(line) {
    return (this.isParallelTo(line) && this.contains(line.anchor));
  },

  // Returns a copy of the line
  dup: function() {
    return Line.create(this.anchor, this.direction);
  },

  // Returns the result of translating the line by the given vector/array
  translate: function(vector) {
    var V = vector.elements || vector;
    return Line.create([
      this.anchor.elements[0] + V[0],
      this.anchor.elements[1] + V[1],
      this.anchor.elements[2] + (V[2] || 0)
    ], this.direction);
  },

  // Returns true if the line is parallel to the argument. Here, 'parallel to'
  // means that the argument's direction is either parallel or antiparallel to
  // the line's own direction. A line is parallel to a plane if the two do not
  // have a unique intersection.
  isParallelTo: function(obj) {
    if (obj.normal) { return obj.isParallelTo(this); }
    var theta = this.direction.angleFrom(obj.direction);
    return (Math.abs(theta) <= Sylvester.precision || Math.abs(theta - Math.PI) <= Sylvester.precision);
  },

  // Returns the line's perpendicular distance from the argument,
  // which can be a point, a line or a plane
  distanceFrom: function(obj) {
    if (obj.normal) { return obj.distanceFrom(this); }
    if (obj.direction) {
      // obj is a line
      if (this.isParallelTo(obj)) { return this.distanceFrom(obj.anchor); }
      var N = this.direction.cross(obj.direction).toUnitVector().elements;
      var A = this.anchor.elements, B = obj.anchor.elements;
      return Math.abs((A[0] - B[0]) * N[0] + (A[1] - B[1]) * N[1] + (A[2] - B[2]) * N[2]);
    } else {
      // obj is a point
      var P = obj.elements || obj;
      var A = this.anchor.elements, D = this.direction.elements;
      var PA1 = P[0] - A[0], PA2 = P[1] - A[1], PA3 = (P[2] || 0) - A[2];
      var modPA = Math.sqrt(PA1*PA1 + PA2*PA2 + PA3*PA3);
      if (modPA === 0) return 0;
      // Assumes direction vector is normalized
      var cosTheta = (PA1 * D[0] + PA2 * D[1] + PA3 * D[2]) / modPA;
      var sin2 = 1 - cosTheta*cosTheta;
      return Math.abs(modPA * Math.sqrt(sin2 < 0 ? 0 : sin2));
    }
  },

  // Returns true iff the argument is a point on the line
  contains: function(point) {
    var dist = this.distanceFrom(point);
    return (dist !== null && dist <= Sylvester.precision);
  },

  // Returns true iff the line lies in the given plane
  liesIn: function(plane) {
    return plane.contains(this);
  },

  // Returns true iff the line has a unique point of intersection with the argument
  intersects: function(obj) {
    if (obj.normal) { return obj.intersects(this); }
    return (!this.isParallelTo(obj) && this.distanceFrom(obj) <= Sylvester.precision);
  },

  // Returns the unique intersection point with the argument, if one exists
  intersectionWith: function(obj) {
    if (obj.normal) { return obj.intersectionWith(this); }
    if (!this.intersects(obj)) { return null; }
    var P = this.anchor.elements, X = this.direction.elements,
        Q = obj.anchor.elements, Y = obj.direction.elements;
    var X1 = X[0], X2 = X[1], X3 = X[2], Y1 = Y[0], Y2 = Y[1], Y3 = Y[2];
    var PsubQ1 = P[0] - Q[0], PsubQ2 = P[1] - Q[1], PsubQ3 = P[2] - Q[2];
    var XdotQsubP = - X1*PsubQ1 - X2*PsubQ2 - X3*PsubQ3;
    var YdotPsubQ = Y1*PsubQ1 + Y2*PsubQ2 + Y3*PsubQ3;
    var XdotX = X1*X1 + X2*X2 + X3*X3;
    var YdotY = Y1*Y1 + Y2*Y2 + Y3*Y3;
    var XdotY = X1*Y1 + X2*Y2 + X3*Y3;
    var k = (XdotQsubP * YdotY / XdotX + XdotY * YdotPsubQ) / (YdotY - XdotY * XdotY);
    return Vector.create([P[0] + k*X1, P[1] + k*X2, P[2] + k*X3]);
  },

  // Returns the point on the line that is closest to the given point or line
  pointClosestTo: function(obj) {
    if (obj.direction) {
      // obj is a line
      if (this.intersects(obj)) { return this.intersectionWith(obj); }
      if (this.isParallelTo(obj)) { return null; }
      var D = this.direction.elements, E = obj.direction.elements;
      var D1 = D[0], D2 = D[1], D3 = D[2], E1 = E[0], E2 = E[1], E3 = E[2];
      // Create plane containing obj and the shared normal and intersect this with it
      // Thank you: http://www.cgafaq.info/wiki/Line-line_distance
      var x = (D3 * E1 - D1 * E3), y = (D1 * E2 - D2 * E1), z = (D2 * E3 - D3 * E2);
      var N = Vector.create([x * E3 - y * E2, y * E1 - z * E3, z * E2 - x * E1]);
      var P = Plane.create(obj.anchor, N);
      return P.intersectionWith(this);
    } else {
      // obj is a point
      var P = obj.elements || obj;
      if (this.contains(P)) { return Vector.create(P); }
      var A = this.anchor.elements, D = this.direction.elements;
      var D1 = D[0], D2 = D[1], D3 = D[2], A1 = A[0], A2 = A[1], A3 = A[2];
      var x = D1 * (P[1]-A2) - D2 * (P[0]-A1), y = D2 * ((P[2] || 0) - A3) - D3 * (P[1]-A2),
          z = D3 * (P[0]-A1) - D1 * ((P[2] || 0) - A3);
      var V = Vector.create([D2 * x - D3 * z, D3 * y - D1 * x, D1 * z - D2 * y]);
      var k = this.distanceFrom(P) / V.modulus();
      return Vector.create([
        P[0] + V.elements[0] * k,
        P[1] + V.elements[1] * k,
        (P[2] || 0) + V.elements[2] * k
      ]);
    }
  },

  // Returns a copy of the line rotated by t radians about the given line. Works by
  // finding the argument's closest point to this line's anchor point (call this C) and
  // rotating the anchor about C. Also rotates the line's direction about the argument's.
  // Be careful with this - the rotation axis' direction affects the outcome!
  rotate: function(t, line) {
    // If we're working in 2D
    if (typeof(line.direction) == 'undefined') { line = Line.create(line.to3D(), Vector.k); }
    var R = Matrix.Rotation(t, line.direction).elements;
    var C = line.pointClosestTo(this.anchor).elements;
    var A = this.anchor.elements, D = this.direction.elements;
    var C1 = C[0], C2 = C[1], C3 = C[2], A1 = A[0], A2 = A[1], A3 = A[2];
    var x = A1 - C1, y = A2 - C2, z = A3 - C3;
    return Line.create([
      C1 + R[0][0] * x + R[0][1] * y + R[0][2] * z,
      C2 + R[1][0] * x + R[1][1] * y + R[1][2] * z,
      C3 + R[2][0] * x + R[2][1] * y + R[2][2] * z
    ], [
      R[0][0] * D[0] + R[0][1] * D[1] + R[0][2] * D[2],
      R[1][0] * D[0] + R[1][1] * D[1] + R[1][2] * D[2],
      R[2][0] * D[0] + R[2][1] * D[1] + R[2][2] * D[2]
    ]);
  },

  // Returns the line's reflection in the given point or line
  reflectionIn: function(obj) {
    if (obj.normal) {
      // obj is a plane
      var A = this.anchor.elements, D = this.direction.elements;
      var A1 = A[0], A2 = A[1], A3 = A[2], D1 = D[0], D2 = D[1], D3 = D[2];
      var newA = this.anchor.reflectionIn(obj).elements;
      // Add the line's direction vector to its anchor, then mirror that in the plane
      var AD1 = A1 + D1, AD2 = A2 + D2, AD3 = A3 + D3;
      var Q = obj.pointClosestTo([AD1, AD2, AD3]).elements;
      var newD = [Q[0] + (Q[0] - AD1) - newA[0], Q[1] + (Q[1] - AD2) - newA[1], Q[2] + (Q[2] - AD3) - newA[2]];
      return Line.create(newA, newD);
    } else if (obj.direction) {
      // obj is a line - reflection obtained by rotating PI radians about obj
      return this.rotate(Math.PI, obj);
    } else {
      // obj is a point - just reflect the line's anchor in it
      var P = obj.elements || obj;
      return Line.create(this.anchor.reflectionIn([P[0], P[1], (P[2] || 0)]), this.direction);
    }
  },

  // Set the line's anchor point and direction.
  setVectors: function(anchor, direction) {
    // Need to do this so that line's properties are not
    // references to the arguments passed in
    anchor = Vector.create(anchor);
    direction = Vector.create(direction);
    if (anchor.elements.length == 2) {anchor.elements.push(0); }
    if (direction.elements.length == 2) { direction.elements.push(0); }
    if (anchor.elements.length > 3 || direction.elements.length > 3) { return null; }
    var mod = direction.modulus();
    if (mod === 0) { return null; }
    this.anchor = anchor;
    this.direction = Vector.create([
      direction.elements[0] / mod,
      direction.elements[1] / mod,
      direction.elements[2] / mod
    ]);
    return this;
  }
};

  
// Constructor function
Line.create = function(anchor, direction) {
  var L = new Line();
  return L.setVectors(anchor, direction);
};

// Axes
Line.X = Line.create(Vector.Zero(3), Vector.i);
Line.Y = Line.create(Vector.Zero(3), Vector.j);
Line.Z = Line.create(Vector.Zero(3), Vector.k);



function Plane() {}
Plane.prototype = {

  // Returns true iff the plane occupies the same space as the argument
  eql: function(plane) {
    return (this.contains(plane.anchor) && this.isParallelTo(plane));
  },

  // Returns a copy of the plane
  dup: function() {
    return Plane.create(this.anchor, this.normal);
  },

  // Returns the result of translating the plane by the given vector
  translate: function(vector) {
    var V = vector.elements || vector;
    return Plane.create([
      this.anchor.elements[0] + V[0],
      this.anchor.elements[1] + V[1],
      this.anchor.elements[2] + (V[2] || 0)
    ], this.normal);
  },

  // Returns true iff the plane is parallel to the argument. Will return true
  // if the planes are equal, or if you give a line and it lies in the plane.
  isParallelTo: function(obj) {
    var theta;
    if (obj.normal) {
      // obj is a plane
      theta = this.normal.angleFrom(obj.normal);
      return (Math.abs(theta) <= Sylvester.precision || Math.abs(Math.PI - theta) <= Sylvester.precision);
    } else if (obj.direction) {
      // obj is a line
      return this.normal.isPerpendicularTo(obj.direction);
    }
    return null;
  },
  
  // Returns true iff the receiver is perpendicular to the argument
  isPerpendicularTo: function(plane) {
    var theta = this.normal.angleFrom(plane.normal);
    return (Math.abs(Math.PI/2 - theta) <= Sylvester.precision);
  },

  // Returns the plane's distance from the given object (point, line or plane)
  distanceFrom: function(obj) {
    if (this.intersects(obj) || this.contains(obj)) { return 0; }
    if (obj.anchor) {
      // obj is a plane or line
      var A = this.anchor.elements, B = obj.anchor.elements, N = this.normal.elements;
      return Math.abs((A[0] - B[0]) * N[0] + (A[1] - B[1]) * N[1] + (A[2] - B[2]) * N[2]);
    } else {
      // obj is a point
      var P = obj.elements || obj;
      var A = this.anchor.elements, N = this.normal.elements;
      return Math.abs((A[0] - P[0]) * N[0] + (A[1] - P[1]) * N[1] + (A[2] - (P[2] || 0)) * N[2]);
    }
  },

  // Returns true iff the plane contains the given point or line
  contains: function(obj) {
    if (obj.normal) { return null; }
    if (obj.direction) {
      return (this.contains(obj.anchor) && this.contains(obj.anchor.add(obj.direction)));
    } else {
      var P = obj.elements || obj;
      var A = this.anchor.elements, N = this.normal.elements;
      var diff = Math.abs(N[0]*(A[0] - P[0]) + N[1]*(A[1] - P[1]) + N[2]*(A[2] - (P[2] || 0)));
      return (diff <= Sylvester.precision);
    }
  },

  // Returns true iff the plane has a unique point/line of intersection with the argument
  intersects: function(obj) {
    if (typeof(obj.direction) == 'undefined' && typeof(obj.normal) == 'undefined') { return null; }
    return !this.isParallelTo(obj);
  },

  // Returns the unique intersection with the argument, if one exists. The result
  // will be a vector if a line is supplied, and a line if a plane is supplied.
  intersectionWith: function(obj) {
    if (!this.intersects(obj)) { return null; }
    if (obj.direction) {
      // obj is a line
      var A = obj.anchor.elements, D = obj.direction.elements,
          P = this.anchor.elements, N = this.normal.elements;
      var multiplier = (N[0]*(P[0]-A[0]) + N[1]*(P[1]-A[1]) + N[2]*(P[2]-A[2])) / (N[0]*D[0] + N[1]*D[1] + N[2]*D[2]);
      return Vector.create([A[0] + D[0]*multiplier, A[1] + D[1]*multiplier, A[2] + D[2]*multiplier]);
    } else if (obj.normal) {
      // obj is a plane
      var direction = this.normal.cross(obj.normal).toUnitVector();
      // To find an anchor point, we find one co-ordinate that has a value
      // of zero somewhere on the intersection, and remember which one we picked
      var N = this.normal.elements, A = this.anchor.elements,
          O = obj.normal.elements, B = obj.anchor.elements;
      var solver = Matrix.Zero(2,2), i = 0;
      while (solver.isSingular()) {
        i++;
        solver = Matrix.create([
          [ N[i%3], N[(i+1)%3] ],
          [ O[i%3], O[(i+1)%3]  ]
        ]);
      }
      // Then we solve the simultaneous equations in the remaining dimensions
      var inverse = solver.inverse().elements;
      var x = N[0]*A[0] + N[1]*A[1] + N[2]*A[2];
      var y = O[0]*B[0] + O[1]*B[1] + O[2]*B[2];
      var intersection = [
        inverse[0][0] * x + inverse[0][1] * y,
        inverse[1][0] * x + inverse[1][1] * y
      ];
      var anchor = [];
      for (var j = 1; j <= 3; j++) {
        // This formula picks the right element from intersection by
        // cycling depending on which element we set to zero above
        anchor.push((i == j) ? 0 : intersection[(j + (5 - i)%3)%3]);
      }
      return Line.create(anchor, direction);
    }
  },

  // Returns the point in the plane closest to the given point
  pointClosestTo: function(point) {
    var P = point.elements || point;
    var A = this.anchor.elements, N = this.normal.elements;
    var dot = (A[0] - P[0]) * N[0] + (A[1] - P[1]) * N[1] + (A[2] - (P[2] || 0)) * N[2];
    return Vector.create([P[0] + N[0] * dot, P[1] + N[1] * dot, (P[2] || 0) + N[2] * dot]);
  },

  // Returns a copy of the plane, rotated by t radians about the given line
  // See notes on Line#rotate.
  rotate: function(t, line) {
    var R = Matrix.Rotation(t, line.direction).elements;
    var C = line.pointClosestTo(this.anchor).elements;
    var A = this.anchor.elements, N = this.normal.elements;
    var C1 = C[0], C2 = C[1], C3 = C[2], A1 = A[0], A2 = A[1], A3 = A[2];
    var x = A1 - C1, y = A2 - C2, z = A3 - C3;
    return Plane.create([
      C1 + R[0][0] * x + R[0][1] * y + R[0][2] * z,
      C2 + R[1][0] * x + R[1][1] * y + R[1][2] * z,
      C3 + R[2][0] * x + R[2][1] * y + R[2][2] * z
    ], [
      R[0][0] * N[0] + R[0][1] * N[1] + R[0][2] * N[2],
      R[1][0] * N[0] + R[1][1] * N[1] + R[1][2] * N[2],
      R[2][0] * N[0] + R[2][1] * N[1] + R[2][2] * N[2]
    ]);
  },

  // Returns the reflection of the plane in the given point, line or plane.
  reflectionIn: function(obj) {
    if (obj.normal) {
      // obj is a plane
      var A = this.anchor.elements, N = this.normal.elements;
      var A1 = A[0], A2 = A[1], A3 = A[2], N1 = N[0], N2 = N[1], N3 = N[2];
      var newA = this.anchor.reflectionIn(obj).elements;
      // Add the plane's normal to its anchor, then mirror that in the other plane
      var AN1 = A1 + N1, AN2 = A2 + N2, AN3 = A3 + N3;
      var Q = obj.pointClosestTo([AN1, AN2, AN3]).elements;
      var newN = [Q[0] + (Q[0] - AN1) - newA[0], Q[1] + (Q[1] - AN2) - newA[1], Q[2] + (Q[2] - AN3) - newA[2]];
      return Plane.create(newA, newN);
    } else if (obj.direction) {
      // obj is a line
      return this.rotate(Math.PI, obj);
    } else {
      // obj is a point
      var P = obj.elements || obj;
      return Plane.create(this.anchor.reflectionIn([P[0], P[1], (P[2] || 0)]), this.normal);
    }
  },

  // Sets the anchor point and normal to the plane. If three arguments are specified,
  // the normal is calculated by assuming the three points should lie in the same plane.
  // If only two are sepcified, the second is taken to be the normal. Normal vector is
  // normalised before storage.
  setVectors: function(anchor, v1, v2) {
    anchor = Vector.create(anchor);
    anchor = anchor.to3D(); if (anchor === null) { return null; }
    v1 = Vector.create(v1);
    v1 = v1.to3D(); if (v1 === null) { return null; }
    if (typeof(v2) == 'undefined') {
      v2 = null;
    } else {
      v2 = Vector.create(v2);
      v2 = v2.to3D(); if (v2 === null) { return null; }
    }
    var A1 = anchor.elements[0], A2 = anchor.elements[1], A3 = anchor.elements[2];
    var v11 = v1.elements[0], v12 = v1.elements[1], v13 = v1.elements[2];
    var normal, mod;
    if (v2 !== null) {
      var v21 = v2.elements[0], v22 = v2.elements[1], v23 = v2.elements[2];
      normal = Vector.create([
        (v12 - A2) * (v23 - A3) - (v13 - A3) * (v22 - A2),
        (v13 - A3) * (v21 - A1) - (v11 - A1) * (v23 - A3),
        (v11 - A1) * (v22 - A2) - (v12 - A2) * (v21 - A1)
      ]);
      mod = normal.modulus();
      if (mod === 0) { return null; }
      normal = Vector.create([normal.elements[0] / mod, normal.elements[1] / mod, normal.elements[2] / mod]);
    } else {
      mod = Math.sqrt(v11*v11 + v12*v12 + v13*v13);
      if (mod === 0) { return null; }
      normal = Vector.create([v1.elements[0] / mod, v1.elements[1] / mod, v1.elements[2] / mod]);
    }
    this.anchor = anchor;
    this.normal = normal;
    return this;
  }
};

// Constructor function
Plane.create = function(anchor, v1, v2) {
  var P = new Plane();
  return P.setVectors(anchor, v1, v2);
};

// X-Y-Z planes
Plane.XY = Plane.create(Vector.Zero(3), Vector.k);
Plane.YZ = Plane.create(Vector.Zero(3), Vector.i);
Plane.ZX = Plane.create(Vector.Zero(3), Vector.j);
Plane.YX = Plane.XY; Plane.ZY = Plane.YZ; Plane.XZ = Plane.ZX;

// Utility functions
var $V = Vector.create;
var $M = Matrix.create;
var $L = Line.create;
var $P = Plane.create;



 /*JS File: ../js/drawing/onlypaths/onlypaths.js*/ 


 /*----------------------------------------------------------------------------
 ONLYPATHS 0.1 
 from
 RICHDRAW 1.0
 Vector Graphics Drawing Script
 -----------------------------------------------------------------------------
 Created by Mark Finkle (mark.finkle@gmail.com)
 Implementation of simple vector graphic drawing control using SVG or VML.
 -----------------------------------------------------------------------------
 Copyright (c) 2006 Mark Finkle  
               2008 Antimatter15  
               2008 Josep_ssv

 This program is  free software;  you can redistribute  it and/or  modify it
 under the terms of the MIT License.

 Permission  is hereby granted,  free of charge, to  any person  obtaining a
 copy of this software and associated documentation files (the "Software"),
 to deal in the  Software without restriction,  including without limitation
 the  rights to use, copy, modify,  merge, publish, distribute,  sublicense,
 and/or  sell copies  of the  Software, and to  permit persons to  whom  the
 Software is  furnished  to do  so, subject  to  the  following  conditions:
 The above copyright notice and this  permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS",  WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED,  INCLUDING BUT NOT LIMITED TO  THE WARRANTIES  OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR  COPYRIGHT  HOLDERS BE  LIABLE FOR  ANY CLAIM,  DAMAGES OR OTHER
 LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT OR  OTHERWISE,  ARISING
 FROM,  OUT OF OR  IN  CONNECTION  WITH  THE  SOFTWARE OR THE  USE OR  OTHER
 DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------
 Dependencies: (SVG or VML rendering implementations)
 History:
 2006-04-05 | Created richdraw.js  
 2008       | Update content and added framework ExtJS    
 2008-06-08 | Rename onlypaths.js   
 --------------------------------------------------------------------------*/  
 
var xpArray=new Array();
var ypArray=new Array(); 
var setPoints=new Array(); 

var inout='';//true;
var typeTransform='';

var contmove=0;  
var zoomx=0;
var zoomy=0;
var zoomscale=1;
var zoommode='frame'; //more minus frame

//
 
var data_path_close=true;
var data_text_family='';
var data_text_size=19
var data_text_messaje='';
var data_image_href='';   
 
var numClics=0;  

////////////

function RichDrawEditor(elem, renderer) {
 this.container = elem;
 this.gridX = 10;
 this.gridY = 10;
 this.mouseDownX = 0;  
 this.mouseDownY = 0;    
 this.clicX = 0;  
 this.clicY = 0;
 this.nowDraw=false;
 this.mode = '';
 this.fillColor = '';  
 this.lineColor = '';
 this.lineWidth = '';
 this.selected = null;   
 this.focusin = null;  
 this.lineOpac = 1;
 this.fillOpac = 1;
 this.gridWidth = 1;
 this.opac = 1;          
 //++ ;
 this.text_messaje="";
 this.text_size=19;
 this.text_family="Arial";
 
 this.pathsEdit = false;
 this.previusBox=null; 
 this.initialPath='';
 this.clipboard=null;
 this.moveNow=true;
 
 this.selectedBounds = { x:0, y:0, width:0, height: 0 };
 this.onselect = function() {}
 this.onunselect = function() {}
 
 this.logtext = "";
 
 this.renderer = renderer;
 this.renderer.init(this.container);
 this.renderer.editor = this;
 this.inputxy = [];
 this.onInputXY = function(){};
  
 Ext.get(this.container).on( "mousedown", this.onMouseDown,this);
 Ext.get(this.container).on( "mouseup", this.onMouseUp,this);  
 //Ext.get(this.container).on( "mouseout", this.outShape,this);   
 //Ext.get(this.container).on( "mouseover", this.overShape,this);
 Ext.get(this.container).on( "mousemove", this.onTranslate,this); 
 Ext.get(this.container).on( "dblclick", this.onEndLine,this);
 Ext.get(this.container).on( "selectstart", this.onSelectStart,this);  
 //Event.observe(document, "keypress", this.onKeyPress,this);  
  
}

RichDrawEditor.prototype.log = function(logtext){
  //this.logtext = logtext
  if(document.forms[0].code){
    document.forms[0].code.value = logtext
  }
}


RichDrawEditor.prototype.getshapes = function(){
 return this.renderer.getshapes();
}

RichDrawEditor.prototype.info = function(shape){
 return this.renderer.info(shape)
}


RichDrawEditor.prototype.clearWorkspace = function() {
  this.container.innerHTML = '';
};

RichDrawEditor.prototype.deleteSelection = function() {
 if (this.selected) {
   this.renderer.remove(this.container.ownerDocument.getElementById('tracker'));
   this.renderer.remove(this.selected);
   this.selected = null;
 }
};

RichDrawEditor.prototype.toFront = function(order) {
 if (this.selected) { 
   this.renderer.index(this.selected, order);
 }
};

RichDrawEditor.prototype.deleteAll = function() {   
 this.renderer.removeAll();
};


RichDrawEditor.prototype.select = function(elem) {
 if (elem == this.selected){  return;  }
 this.selected = elem;
 this.renderer.showTracker(this.selected,this.pathsEdit);
 this.onselect(this);
};


RichDrawEditor.prototype.unselect = function() {
 if (this.selected) {
   this.renderer.remove(this.container.ownerDocument.getElementById('tracker'));
   this.selected = null;
   this.onunselect(this);
  }
};

RichDrawEditor.prototype.getSelectedElement = function() {
 return this.selected;
};

RichDrawEditor.prototype.toCurve = function() {  
 this.renderer.tocurve();
}

RichDrawEditor.prototype.submitShape = function(data) {  
 if (this.mode != 'select') {   
   setMode('path', 'Path');  
   this.actualStyle();
   //onColorChange();   
   //shape, fillColor, lineColor, fillOpac, lineOpac, lineWidth, left, top, width, height, textMessaje, textSize, textFamily, imageHref, points, transform, parent
   //this.selected = this.renderer.datacreate(this.fillColor, this.lineColor, this.fillOpac, this.lineOpac, this.lineWidth, this.mouseDownX, this.mouseDownY, 1, 1,data);
   this.selected = this.renderer.create(this.mode, this.fillColor, this.lineColor, this.fillOpac, this.lineOpac, this.lineWidth, this.mouseDownX, this.mouseDownY, 1, 1,this.textMessaje,this.textSize,this.textFamily,this.imageHref, data, '', '');

   this.selected.id = 'shape:' + createUUID();
   Ext.get(this.selected).on("mousedown", this.onHit,this);   
   setMode('select', 'Select'); 
 } else {
   this.renderer.transformShape(this.selected,data,null); 
   this.renderer.remove(this.container.ownerDocument.getElementById('tracker')); 
   this.renderer.showTracker(this.selected,this.pathsEdit);
 }
};

RichDrawEditor.prototype.setGrid = function(horizontal, vertical) {
 this.gridX = horizontal;
 this.gridY = vertical;
 this.gridWidth = (vertical+horizontal)/2; //average. ideally, it should be the same
};


// ++
RichDrawEditor.prototype.actualStyle = function()
{
 this.textMessaje=$('option_text_message').value;
 this.textSize=parseFloat($('option_text_size').value);
 this.textFamily=$('option_text_family').value;
 this.pathClose = $('option_path_close').checked; 
 this.imageHref = $('option_image_href').value;

 return;
};


RichDrawEditor.prototype.editCommand = function(cmd, value)
{
 if (cmd == 'mode') 
  {
   this.mode = value;
  }
 else if (this.selected == null) 
  {  
   if (cmd == 'fillcolor') 
    {
     this.fillColor = value;
    }
   else if (cmd == 'linecolor') 
    {
     this.lineColor = value;
    }
   else if (cmd == 'linewidth') 
    {
     this.lineWidth = parseInt(value) + 'px';
    } 
   else if (cmd == 'fillopacity') {
     this.fillOpac = parseInt(value);
    } 
   else if (cmd == 'lineopacity') {
     this.lineOpac = parseInt(value);
    }
  }
 else 
  {
    this.renderer.editCommand(this.selected, cmd, value);
  }
}


RichDrawEditor.prototype.queryCommand = function(cmd)
{
 if (cmd == 'mode') 
  {
   return this.mode;
  }
 else if (this.selected == null) 
  {
   if (cmd == 'fillcolor') 
    {
     return this.fillColor;
    }
   else if (cmd == 'linecolor') 
    {
     return this.lineColor;
    }
   else if (cmd == 'linewidth') 
    {
     return this.lineWidth;
    }
   else if (cmd == 'fillopacity') 
    {
     return  this.fillOpac;
    }
   else if (cmd == 'lineopacity') 
    {
     return  this.fillOpac;
    }
  }
 else 
  {
   return this.renderer.queryCommand(this.selected, cmd);
  }
}




RichDrawEditor.prototype.onSelectStart = function(event) {
  return false
}


/////////////////////////////

RichDrawEditor.prototype.onKeyPress =  function(event){
 //alert('Character was ')
 //Ext.get(this.container).on( "keypress", function(event){
	var code;

	if (!event){ var event = window.event;}
	if (event.keyCode){ code = event.keyCode;}
	else if (event.which){ code = event.which;} 
	
	var pressedKey = String.fromCharCode(code);//.toLowerCase();
            //UNDO
	   if(event.ctrlKey && pressedKey == "z" || event.ctrlKey && pressedKey == "Z" )
            {
		this.clipboard=this.renderer.undo();
	     	//this.deleteSelection();
	    }

	if (this.mode == 'select') 
         {
	   //DELETE
	   if(code==46)
            {
	     	this.deleteSelection();
		
            }   
	   //CUT
	   if(event.ctrlKey && pressedKey == "x" || event.ctrlKey && pressedKey == "X" )
            {
		this.clipboard=this.renderer.copy(this.selected);
	     	this.deleteSelection();
	    }
	   //COPY
	   if (event.ctrlKey && pressedKey == "c" || event.ctrlKey && pressedKey == "C")
	    { 
			 this.clipboard=this.renderer.copy(this.selected);
	    }
	   //PASTE
       	   if (event.ctrlKey && pressedKey == "v" || event.ctrlKey && pressedKey == "V")
	    { 
			 //this.unselect();
			 this.selected=this.renderer.paste(this.clipboard,this.mouseDownX,this.mouseDownY);
			 this.selected.id = 'shape:' + createUUID();
 			Ext.get(this.selected).on( "mousedown", this.onHit,this);  
	    }
	    //DUPLICATE
       	   if (event.ctrlKey && pressedKey == "d" || event.ctrlKey && pressedKey == "D" )
	    { 
			 this.selected=this.renderer.duplicate(this.selected);
			 this.selected.id = 'shape:' + createUUID();
    			Ext.get(this.selected).on( "mousedown", this.onHit,this);  
	    }   
	    //LEFT
           if (event.ctrlKey && code==37)
            {
                //alert('left');  
               if(this.pathsEdit==true)
                {
                  var newx=parseFloat($('option_path_x').value)-1;    
                  var newy=parseFloat($('option_path_y').value); 
                  this.renderer.nodeMove(newx,newy);
                }
            }
            //UP
           if (code==38)
            {
                //alert('up');
               if(this.pathsEdit==true)
                {
                  var newx=parseFloat($('option_path_x').value);    
                  var newy=parseFloat($('option_path_y').value)-1; 
                  this.renderer.nodeMove(newx,newy);
                
                }
            }
            //RIGHT
            if (code==39)
             {
                //alert('right');
               if(this.pathsEdit==true) 
                {
                  var newx=parseFloat($('option_path_x').value)+1;    
                  var newy=parseFloat($('option_path_y').value); 
                  this.renderer.nodeMove(newx,newy);
                }
             }
            //DOWN
           if (code==40)
            {
                //alert('down')
               if(this.pathsEdit==true)
                {
                  var newx=parseFloat($('option_path_x').value);    
                  var newy=parseFloat($('option_path_y').value)+1; 
                  this.renderer.nodeMove(newx,newy);
                
                }
            }


	 }else{
			//alert('Character was ' +event.ctrlKey+' '+ code);
		if (event.ctrlKey && pressedKey == "x" ) 
		 {

			var cad;
		//for (i=0; i<this.length; i++){
			//cad+=this.renderer.child(i)+' ';//item
			//cad+=this.svgRoot.childNodes.length;
	 	//}
		    //this.deleteSelection();
			//alert(cad+'');
			//alert('Character was ' +event.ctrlKey+' '+ code);
		 }
  	 }
	//var character = String.fromCharCode(code);
	//alert('Character was ' + character);
  //});
 
  return false;
};

 /*

Event.observe(window, 'load', function() {
Event.observe(document, 'keypress', function(e){
var code;
if (!e) var e = window.event;
if (e.keyCode) code = e.keyCode;
else if (e.which) code = e.which;
var character = String.fromCharCode(code);
alert('Character was ' + character);
});
});
*/

////////////////////////
/*RichDrawEditor.prototype.outShape = function(event) {  
  if(typeTransform=='Translate')
   {
    typeTransform='';
   } 
} 
RichDrawEditor.prototype.overShape = function(event) {  
   typeTransform='Translate';
  
} 
*/
RichDrawEditor.prototype.onMouseDown = function(event) {  
 if(event.button != 0){return}
 
 clockdata();
 
 //MODE NO SELECT
 if (this.mode != 'select') 
  {      
   var modeUsed=0;     
   if (this.mode == 'zoom') 
    {     
     var offset = Ext.get(this.container).getXY();
     var snappedX = Math.round((event.getXY()[0] - offset[0]) / this.gridX) * this.gridX;
     var snappedY = Math.round((event.getXY()[1] - offset[1]) / this.gridY) * this.gridY;
     var width=this.gridWidth;
     contmove=0;
     this.setGrid(width, width);  
     this.unselect(); 
     xpArray=new Array();
     ypArray=new Array();
     this.mouseDownX = snappedX;
     this.mouseDownY = snappedY;   
     xpArray.push(this.mouseDownX);
     ypArray.push(this.mouseDownY);
     this.renderer.zoom(this.mouseDownX, this.mouseDownY);  
     modeUsed=1; 
    } //end zoom     
   if (this.mode == 'controlpath') 
    {
     this.actualStyle(); 
     //onColorChange();         
     if(numClics<=0)
      {     
       this.nowDraw=true;
       setPoints=new Array();    
       var offset = Ext.get(this.container).getXY();
       var snappedX = Math.round((event.getXY()[0] - offset[0]) / this.gridX) * this.gridX;
       var snappedY = Math.round((event.getXY()[1] - offset[1]) / this.gridY) * this.gridY;
       var width=this.gridWidth;  
       contmove=0;
       this.setGrid(width, width);  
       this.unselect(); 
       xpArray=new Array();
       ypArray=new Array();
       this.mouseDownX = snappedX;
       this.mouseDownY = snappedY;   
       xpArray.push(this.mouseDownX);
       ypArray.push(this.mouseDownY);
       setPoints.push(this.mouseDownX+','+this.mouseDownY); 
       // ++ ;
        //onColorChange();
        this.actualStyle();                                                                                                                                                  
       // ++ ;                       
       //shape, fillColor, lineColor, fillOpac, lineOpac, lineWidth, left, top, width, height, textMessaje, textSize, textFamily, imageHref, points, transform, parent
       //this.selected = this.renderer.create(this.mode, this.fillColor, this.lineColor, this.fillOpac, this.lineOpac, this.lineWidth, this.mouseDownX, this.mouseDownY, 1, 1,this.textMessaje,this.textSize,this.textFamily,this.imageHref, '');

       this.selected = this.renderer.create(this.mode, this.fillColor, this.lineColor, this.fillOpac, this.lineOpac, this.lineWidth, this.mouseDownX, this.mouseDownY, 1, 1,this.textMessaje,this.textSize,this.textFamily,this.imageHref, 'M0,0 1,1', '', '');
              
       this.selected.id = 'shape:' + createUUID(); 
       Ext.get(this.selected).on( "mousedown", this.onHit,this);  
       this.log(this.selected.id);   
       
       Ext.get(this.selected).on( "dblclick", this.onEndLine,this);  
       Ext.get(this.container).on( "mousemove", this.onDraw,this); 
       numClics++;
     }
      else
     {  
       var coord=this.inputxy;
       var X=parseFloat(coord[0]);
       var Y=parseFloat(coord[1]); 
       setPoints.push(X+','+Y);
       this.renderer.clic(this.selected);
       numClics++;
     }
     modeUsed=1; 
    } //end mode controlpath
   if (modeUsed == 0) 
    {   
     var offset = Ext.get(this.container).getXY();
     var snappedX = Math.round((event.getXY()[0] - offset[0]) / this.gridX) * this.gridX;
     var snappedY = Math.round((event.getXY()[1] - offset[1]) / this.gridY) * this.gridY;
     var width=this.gridWidth;
     contmove=0; 
     this.setGrid(width, width);  
     this.unselect(); 
     xpArray=new Array();
     ypArray=new Array();
     this.mouseDownX = snappedX;
     this.mouseDownY = snappedY;   
     xpArray.push(this.mouseDownX);
     ypArray.push(this.mouseDownY);
     this.unselect();   
      //onColorChange();
      this.actualStyle(); 
     //this.selected = this.renderer.create(this.mode, this.fillColor, this.lineColor, this.fillOpac, this.lineOpac, this.lineWidth, this.mouseDownX, this.mouseDownY, 1, 1,this.textMessaje,this.textSize,this.textFamily,this.imageHref,'');
     
     this.selected = this.renderer.create(this.mode, this.fillColor, this.lineColor, this.fillOpac, this.lineOpac, this.lineWidth, this.mouseDownX, this.mouseDownY, 1, 1,this.textMessaje,this.textSize,this.textFamily,this.imageHref,'M0,0 1,1', '', '');
     
     this.selected.id = 'shape:' + createUUID();   
     //-- this.selected.id = this.mode+':' + createUUID();
     Ext.get(this.selected).on( "mousedown", this.onHit,this);  
     Ext.get(this.container).on( "mousemove", this.onDraw,this);
     //Ext.get(this.container).on( "mouseover", this.overShape,this);   
     //Ext.get(this.container).on( "mouseout", this.outShape,this); 
    }     
  }
   else   //----- MODE SELECT
  {                                            
   
   var offset = Ext.get(this.container).getXY();
   var snappedX = Math.round((event.getXY()[0] - offset[0]) / this.gridX) * this.gridX;
   var snappedY = Math.round((event.getXY()[1] - offset[1]) / this.gridY) * this.gridY;
   // if ((this.mouseDownX != snappedX && this.mouseDownY != snappedY) || typeTransform=='')
   if (this.mouseDownX != snappedX || this.mouseDownY != snappedY)
    { 
      if(this.selected!=null && typeTransform=='Translate' )
       {
        
        Ext.get(this.container).un("mousemove", this.onDrag); 
        this.unselect();
       }
      //typeTransform='';
    }     
    
  // if (typeTransform=='' && (this.mouseDownX != snappedX || this.mouseDownY != snappedY) )    
     // { 
      //if(typeTransform=='Rotate' || typeTransform=='Translate'){  }else{  
        
         //this.unselect();           
      // }
   // } 
     //else
    //{   
     // if(this.nowDraw==true){ alert('Double click, please'); this.onEndLineListener(event); return true;}
     //Ext.get(this.container).on( "mouseout", this.onRotate,this);  
          
         
     // if (this.mouseDownX != snappedX || this.mouseDownY != snappedY)
     //{  
     if(typeTransform=='Translate')
      {  
       inout='move';//true;   
       //Event.observe(this.selected, "mousedown", this.onHit,this);  
       //Ext.get(this.container).on( "mousemove", this.onDrag,this);  
       this.renderer.remove(this.container.ownerDocument.getElementById('tracker')); 

      }
     if(typeTransform=='Scale'  || typeTransform=='Rotate') 
      {
       inout='rotate_escale';//false  
       Ext.get(this.container).on( "mousemove", this.onDrag,this);         
       Ext.get(this.selected).on( "mousedown", this.onHit,this);  
       this.renderer.remove(this.container.ownerDocument.getElementById('tracker')); 

       //Ext.get(this.container).on( "mouseover", this.onTranslate,this);  
       //Ext.get(this.container).on( "mouseout", this.onRotate,this); 
       //this.unselect();   
      }  
    //} //end typeTransform==''
  } //end mode select
 return false;
};


RichDrawEditor.prototype.onMouseUp = function(event) 
{
 //Ext.get(this.selected).un("mousemove",this.onDrag)
 
   //MODE NO SELECT
 if (this.mode != 'select') 
  {  
   //this.renderer.restruct(this.selected);
   if(this.mode == 'controlpath') 
    {
     //Event.observe(this.selected, "mousemove", this.onClic,this);  
     //this.renderer.info(this.selected);
    }
     else
    {  
     Ext.get(this.container).un("mousemove", this.onDraw);  
     this.selected = null;   
    }
  } 
   else //MODE SELECT
  { 
   Ext.get(this.container).un("mousemove", this.onDraw);  //or drag
   //Ext.get(this.container).un("mousemove", this.onDrag);  
   Ext.get(this.container).un("mousemove", this.onDrag);  
   
    
   moveNow=false;   
   contmove=0; 
   // if(inout=='move' || inout=='rotate_scale' ){
   if(typeTransform=="Rotate" || typeTransform=="Scale" ) 
    {  
      //this.renderer.remove(this.container.ownerDocument.getElementById('tracker'));
      this.renderer.showTracker(this.selected,this.pathsEdit); 
   
     //inout='move';//true; 
     //this.renderer.restruct(this.selected);
     typeTransform=='';
    } 
   if(typeTransform=="Translate" ) 
    { 
              
     this.renderer.showTracker(this.selected,this.pathsEdit); 
     //Ext.get(this.container).un("mousemove", this.renderer.move);    
     //Ext.get(this.container).un("mousemove", this.onDrag);  
     typeTransform=='';   
     //this.renderer.restruct(this.selected); 
     //this.unselect();
     contmove=0; 
     
    }
   if(inout=='multiSelect')
    {
      
     //inout='move';//true;      
    } 
    
   typeTransform==''; 
  }  
   //Event.stopObserving(this.container, "mousemove", this.onDraw,this);  
};


RichDrawEditor.prototype.onDrag = function(event) {  

  moveNow=true; 
  var offset = Ext.get(this.container).getXY();
  var snappedX = Math.round((event.getXY()[0] - offset[0]) / this.gridX) * this.gridX;
  var snappedY = Math.round((event.getXY()[1] - offset[1]) / this.gridY) * this.gridY;

  var deltaX = snappedX - this.mouseDownX;
  var deltaY = snappedY - this.mouseDownY; 

  var modeUsed=0;              
  if(this.mode == 'zoom') 
   {  
       //this.renderer.zoom(this.selectedBounds.x + deltaX, this.selectedBounds.y + deltaY); 
      // this.renderer.zoom(this.mouseDownX, this.mouseDownY);  
 
          modeUsed=1; 
   }
  if(this.mode == 'controlpath') 
     {  
      modeUsed=1; 
     }
  if(modeUsed==0)
   {        
           if(inout=='multiSelect'){ 
               this.renderer.showMultiSelect(this.mouseDownX, this.mouseDownY);  
           }
       
       
           if(typeTransform=="Translate")
            {  
            Ext.get(this.container).getXY();  
              
 
           //var coord=this.inputxy;
	   //var moveX=parseFloat(coord[0]);
	   //var moveY=parseFloat(coord[1]); 
               this.log(this.mouseDownX+' '+event.getXY()[0]+' '+ this.selectedBounds.x +'contmove'+contmove); 
               this.renderer.move(this.selected, this.selectedBounds.x + deltaX, this.selectedBounds.y +deltaY,this.clicX,this.clicY);
                //this.renderer.showTracker(this.selected,this.pathsEdit); 
                 
            }  
          
                      
               if(typeTransform=="Rotate") 
                 { 
                   this.renderer.rotateShape(this.selected, this.previusBox,deltaX, deltaY);
                   //this.renderer.showTracker(this.selected,this.pathsEdit);
                 }

              	//if(typeTransform=="Scale") {this.renderer.scale(this.selected, this.previusBox, deltaX, deltaY); }
          	if(typeTransform=="Scale") 
          	 {

          	      this.renderer.scaleShape(this.selected, this.previusBox, this.selectedBounds.x + deltaX, this.selectedBounds.y + deltaY); 
          	      //this.renderer.showTracker(this.selected,this.pathsEdit);
          	 }
          	//if(typeTransform=="Scale") {this.renderer.scale(this.selected, this.previusBox, this.selectedBounds.width + deltaX, this.selectedBounds.height + deltaY); }
          	
          	//RichDrawEditor.prototype.onTransform(event);
          	
             
           //} 
        
    }   
 // Update selection tracker
 //this.renderer.remove(this.container.ownerDocument.getElementById('tracker'));
  
  //this.renderer.remove(this.container.ownerDocument.getElementById('tracker'));

// hide_tracker();
};


RichDrawEditor.prototype.onResize = function(event) {
  var offset = Ext.get(this.container).getXY();
  var snappedX = Math.round((event.getXY()[0] - offset[0]) / this.gridX) * this.gridX;
  var snappedY = Math.round((event.getXY()[1] - offset[1]) / this.gridY) * this.gridY;

  var deltaX = snappedX - this.mouseDownX;
  var deltaY = snappedY - this.mouseDownY;

  this.renderer.track(handle, deltaX, deltaY);

  // Update selection tracker
  show_tracker();
//  hide_tracker();
};


RichDrawEditor.prototype.onDraw = function(event) {
  if (this.selected == null)
   {
       return;
   }else{
        var offset = Ext.get(this.container).getXY()
        var snappedX = Math.round((event.getXY()[0] - offset[0]) / this.gridX) * this.gridX;
        var snappedY = Math.round((event.getXY()[1] - offset[1]) / this.gridY) * this.gridY;
        this.renderer.resize(this.selected, this.mouseDownX, this.mouseDownY, snappedX, snappedY);
  }
};

RichDrawEditor.prototype.onRotate = function(event) {
  if (this.selected == null)
   {
     
   }else{      
         //   this.renderer.remove(this.container.ownerDocument.getElementById('tracker')); 
        //document.getElementById('richdraw').style.cursor='e-resize';
         
         //alert('chao');
         //inout=false; 
          
        //return;
   }
};

RichDrawEditor.prototype.onScale = function(event) {
  if (this.selected == null)
   {
     
   }else{      
         //document.getElementById('richdraw').style.cursor='e-resize';
         //alert('chao');
         //inout=false; 
          
        //return;
   }
};

RichDrawEditor.prototype.onTransform = function(event) {
  if (this.selected == null)
   {
     
   }else{  
     	//if(typeTransform=="rotate") {this.renderer.rotate(this.selected, this.selectedBounds.x + deltaX, this.selectedBounds.y + deltaY);}
  	//if(typeTransform=="scale") {this.renderer.scale(this.selected, this.selectedBounds.x + deltaX, this.selectedBounds.y + deltaY); }
  
  }
};

RichDrawEditor.prototype.onTranslate = function(event) {
  if (this.selected == null)
   {
    
   }else{  
      // document.getElementById('richdraw').style.cursor='move';
        //alert('hello');
         //inout=true;    
      
        //return;
   } 
   var offset = Ext.get(this.container).getXY()
          // var offset = Ext.get(this.container).getXY();
        var x = Math.round(event.getXY()[0] - offset[0]);
        var y = Math.round(event.getXY()[1] - offset[1]);

   //var x= parseFloat(event.getXY()[0]); 
   //var y= parseFloat(event.getXY()[1]); 
   

   this.inputxy = [x,y]
   this.onInputXY(x,y); 
   
   //Ext.get(this.container).getXY(); ;//
};                                       


RichDrawEditor.prototype.onHit = function(event) {
//console.log("AAH HIT!!!!")
 if(this.mode == 'select') 
  {   
    ;
    //event.cancelBubble =false;
    // We've handled this event.  Don't let anybody else see it.  
   if (event.stopPropagation) event.stopPropagation(); // DOM Level 2
   else event.cancelBubble = true; // IE
   // Now prevent any default action.
   if (event.preventDefault) event.preventDefault(); // DOM Level 2
   else event.returnValue = false; // IE      
   
   if(inout=='multiSelect')
    {   
      //Ext.get(this.container).on( "mousemove", this.onDrag,this);   
      //Ext.get(this.container).on( "mouseup", this.onMouseUp,this);   
 
    }
     else
    { 
    
      Ext.get(this.container).un("mousemove", this.onDrag); 
      //this.unselect();    
     typeTransform="Translate";
     
    /* //this.previusBox=this.selected;      
     this.select(Event.element(event));
     this.selectedBounds = this.renderer.bounds(this.selected);
     //document.forms[0].code.value=shape(c,this.selected);
     var offset = Ext.get(this.container).getXY();
     this.mouseDownX = Math.round((event.getXY()[0] - offset[0]) / this.gridX) * this.gridX;
     this.mouseDownY = Math.round((event.getXY()[1] - offset[1]) / this.gridY) * this.gridY;
     this.renderer.info(this.selected);
     Ext.get(this.container).on( "mousemove", this.onDrag,this);    
     //Ext.get(this.container).on( "mouseover", noselect);  
     Ext.get(this.container).on( "mouseout", this.onMouseUp,this); 
     //Ext.get(this.container).on( "mouseup", this.onMouseUp,this); 
     //typeTransform=="Translate";  
     //if(typeTransform=="Rotate") {this.renderer.rotate(this.selected, this.previusBox,2, 2);}
    */
        //var width = parseFloat(widths.options[widths.selectedIndex].value);   
       
     contmove=0;
     //this.setGrid(this.lineWidth, width);  
     var width=this.gridWidth;
         
     this.setGrid(width, width);  
     
    this.select(event.getTarget()); 
    this.previusBox=this.selected;     
    
    //++
    this.renderer.getProperties(this.selected);
    
    this.selectedBounds = this.renderer.bounds(this.selected);
    //document.forms[0].code.value=shape(c,this.selected);
    var offset = Ext.get(this.container).getXY(); 
    
    this.mouseDownX = Math.round((event.getXY()[0] - offset[0]) / this.gridX) * this.gridX;
    this.mouseDownY = Math.round((event.getXY()[1] - offset[1]) / this.gridY) * this.gridY;
    this.log(this.gridX);
    this.renderer.info(this.selected); 
    if(this.container.ownerDocument.getElementById('tracker'))
    {
     this.renderer.remove(this.container.ownerDocument.getElementById('tracker')); 
    } 
    Ext.get(this.container).on( "mousemove", this.onDrag,this);   

    
    }
  }
   else
  {
       
  }
};
RichDrawEditor.prototype.onClic = function(event) {
 if(this.mode == 'controlpath') 
  { 
     
    //Ext.get(this.container).on( "mouseout", this.onMouseUp,this);     
  
    //Ext.get(this.container).on( "mousemove", this.onDrag,this);   

     //Ext.get(this.container).on( "mouseout", this.onDrag,this); 
  }
   else
  {
       
  }
};    


RichDrawEditor.prototype.onEndLine = function(event) {   
  
 if(this.mode == 'controlpath') 
  {      // alert('hello');   
        numClics=0;
         //this.selected = null; 

         //Event.stopObserving(this.container, "mousemove", this.onDraw,this); 
            
            

            //Event.observe(this.selected, "mousedown", this.onHit,this);  
            //Ext.get(this.container).on( "mousemove", this.onDraw,this);  
          
            //Event.stopObserving(this.selected, "dblclick", this.onEndLine,this);
            //Event.stopObserving(this.container, "mousemove", this.onDraw,this);  
 
//*
 //try{

	// }catch(err){}     
//*/	  

this.selected = null;

         //this.unselect(); 
         
  }
   else
  {
  this.nowDraw=false;     
  }
};
function noselect(){
    //typeTransform="";    
}

if (!Array.prototype.map)
{
  Array.prototype.map = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array(len);
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
        res[i] = fun.call(thisp, this[i], i, this);
    }

    return res;
  };
}


function createUUID()
{
	var uuid = [];
for(var x = 0; x < 5; x++){
	uuid.push("");
    for (var i=0; i<[4, 2, 2, 2, 6][x]; i++) {
      var uuidchar = parseInt((Math.random() * 256)).toString(16);
      if (uuidchar.length == 1)
        uuidchar = "0" + uuidchar;
      uuid[x] += uuidchar;
    }
}
return uuid.join("-")

}


//----------------------------------------------------------------------------
// AbstractRenderer
//
// Abstract base class defining the drawing API. Can not be used directly.
//----------------------------------------------------------------------------

function AbstractRenderer() {

};

AbstractRenderer.prototype.init = function(elem) {};
AbstractRenderer.prototype.bounds = function(shape) { return { x:0, y:0, width:0, height: 0 }; };
AbstractRenderer.prototype.create = function(shape, fillColor, lineColor, lineWidth, left, top, width, height, textMessaje, textSize, textFamily, imageHref, transform) {};
AbstractRenderer.prototype.datacreate = function(fillColor, lineColor, lineWidth, fillOpac, strokeOpac, left, top, width, height,data) {};
AbstractRenderer.prototype.index = function(shape, order) {};
AbstractRenderer.prototype.remove = function(shape) {}; 
AbstractRenderer.prototype.copy = function(shape) {};
AbstractRenderer.prototype.paste = function(left,top) {};
AbstractRenderer.prototype.duplicate = function(shape) {};
AbstractRenderer.prototype.move = function(shape, left, top) {};  
AbstractRenderer.prototype.endmove = function(shape) {};
AbstractRenderer.prototype.transform= function(shape, left, top) {};
AbstractRenderer.prototype.scale = function(shape, left, top) {};
AbstractRenderer.prototype.rotate = function(shape, left, top) {};
AbstractRenderer.prototype.track = function(shape) {}; 
AbstractRenderer.prototype.restruct = function(shape) {};
AbstractRenderer.prototype.resize = function(shape, fromX, fromY, toX, toY) {};
AbstractRenderer.prototype.editCommand = function(shape, cmd, value) {};
AbstractRenderer.prototype.queryCommand = function(shape, cmd) {};
AbstractRenderer.prototype.showTracker = function(shape,value) {};
AbstractRenderer.prototype.getMarkup = function() { return null; };
AbstractRenderer.prototype.info = function(shape){}; 
AbstractRenderer.prototype.editShape = function(shape,data){};
AbstractRenderer.prototype.onKeyPress = function(){};

AbstractRenderer.prototype.getshapes = function(){};


//-----------------------------
// Geometry
//-----------------------------   

//two point angle  deg
function ang2v(x1,y1,x2,y2)
{
     /*
      var k=0;

      var sum1=u1+v1; 
      var sum2=u2+v2;    

      var res1=u1-v1;  
      var res2=u2-v2;   

     var ku1=k*u1; 
      var ku2=k*u2;   

       var mu= Math.sqrt(u1*u1+u2*u2); 
       var mv= Math.sqrt(v1*v1+v2*v2);

       var pesc= u1*v1+u2*v2; 
       //var ang=Math.acos(pesc/(mu*mv))*180/Math.PI;
       var ang=Math.acos(pesc/(mu*mv));  
       */ 
        var resx=x2-x1;  
      var resy=y2-y1;   
       var ang=Math.atan2(resy,resx); 
       //alert(ang);
       return ang;
}     

function dist2p(a,b,c,d) 
 {
   with (Math) 
    {
        //var d2p=sqrt(abs(((d-b)*(d-b) )+((c-a)*(c-a))));   //decimas(d2p,3);     return d2p;
          return sqrt(abs((d-b)*(d-b)+ (c-a)*(c-a)));

    }
 }
function pmd2pb(a,b,c,d,q) {
	pmdx= (1-q)*a+c*q;
	pmdy= (1-q)*b+d*q;
//pmdx=decimas(pmdx,3);
//pmdy=decimas(pmdy,3);
var cad=pmdx+','+pmdy;
var sol= new Array();
sol= [cad,pmdx,pmdy];
return sol

} 

function getAngle(dx,dy) {
  var angle = Math.atan2(dy, dx);
  //angle *= 180 / Math.PI;
  return angle;  
  
}

/*

A = y2-y1
B = x1-x2
C = A*x1+B*y1
Regardless of how the lines are specified, you should be able to generate two different points along the line, and then generate A, B and C. Now, lets say that you have lines, given by the equations:
A1x + B1y = C1
A2x + B2y = C2
To find the point at which the two lines intersect, we simply need to solve the two equations for the two unknowns, x and y.

    double det = A1*B2 - A2*B1
    if(det == 0){
        //Lines are parallel
    }else{
        double x = (B2*C1 - B1*C2)/det
        double y = (A1*C2 - A2*C1)/det
    }




*/  
// interseccion 2 rectas
function ntrsccn2rb(a,b,c,d,e,f,g,h){
 var solution= new Array();
 var i2rx=0;var i2ry=0;
 var w= (c-a)*(f-h)-(e-g)*(d-b);
 if(w==0){
  n=1;
  i2rx= (1-n)*a+n*c;
  i2ry= (1-n)*b+n*d;
  solution= ['',i2rx,i2ry];  
  //Lines are parallel
  return solution
  //return (i2rx+' '+i2ry);
 }
 var n = (((e-a)*(f-h))-((e-g)*(f-b)))/w;
 i2rx=(1-n)*a+n*c;
 i2ry=(1-n)*b+n*d;
 //return (i2rx+' '+i2ry);
 solution= ['',i2rx,i2ry];
 return solution

}

//ecuacion implicita de la recta
function ccnmplct(a,b,c,d) { 
  var solution= new Array();
  //a1 a2, b1 b2    vector direccion b1-a1 , b2-a2
  var v1m=c-a;
  var v1n=d-b;
  var c1x= v1m;
  var c1y= v1n;
  // ecuacion continua (x - a) /c -a =  (y - b)/d - b
  //(x - a) * v1n =  (y - b) * v1m 
  //x * v1n - v1n*a = y * v1m - b* v1m
  eia= v1n ;
  eib= - v1m;
  eic=  (b* v1m) - ( v1n*a)
  solution= [eia,eib,eic];
  return solution
}
function GetString(source, start, end){
var st = source.indexOf(start) + start.length;
var en = source.indexOf(end, start);
 return source.substring(st, en);//trimAll(source.substring(st, en));
} 
function deg2rad(angle){
return (angle/180) * Math.PI;
}


 /*JS File: ../js/drawing/onlypaths/op_view.js*/ 


 //who would have known that prior, this file was actually pretty big. I mean.. look, this is barely 5 lines now!

function RichDrawViewer(elem, renderer) {
 this.container = elem;
 this.renderer = renderer;
 this.renderer.init(this.container);
 this.renderer.editor = this;
}


 /*JS File: ../js/drawing/onlypaths/svgrenderer.js*/ 


 /*----------------------------------------------------------------------------
 SVGRENDERER 1.0
 SVG Renderer For RichDraw
 -----------------------------------------------------------------------------
 Created by Mark Finkle (mark.finkle@gmail.com)
 Implementation of SVG based renderer.
 -----------------------------------------------------------------------------
 Copyright (c) 2006 Mark Finkle

 This program is  free software;  you can redistribute  it and/or  modify it
 under the terms of the MIT License.

 Permission  is hereby granted,  free of charge, to  any person  obtaining a
 copy of this software and associated documentation files (the "Software"),
 to deal in the  Software without restriction,  including without limitation
 the  rights to use, copy, modify,  merge, publish, distribute,  sublicense,
 and/or  sell copies  of the  Software, and to  permit persons to  whom  the
 Software is  furnished  to do  so, subject  to  the  following  conditions:
 The above copyright notice and this  permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS",  WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED,  INCLUDING BUT NOT LIMITED TO  THE WARRANTIES  OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR  COPYRIGHT  HOLDERS BE  LIABLE FOR  ANY CLAIM,  DAMAGES OR OTHER
 LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT OR  OTHERWISE,  ARISING
 FROM,  OUT OF OR  IN  CONNECTION  WITH  THE  SOFTWARE OR THE  USE OR  OTHER
 DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------
 Dependencies:
 History:
 2006-04-05 | Created
 --------------------------------------------------------------------------*/


function SVGRenderer() {
	this.base = AbstractRenderer;
	this.svgRoot = null;
}


SVGRenderer.prototype = new AbstractRenderer;


SVGRenderer.prototype.init = function(elem) {
  this.container = elem;

  this.container.style.MozUserSelect = 'none';
    
  var svgNamespace = 'http://www.w3.org/2000/svg'; 
  
  this.svgRoot = this.container.ownerDocument.createElementNS(svgNamespace, "svg");
  this.svgRoot.setAttributeNS(null,'viewBox', zoominit);
  this.svgRoot.setAttributeNS(null,'preserveAspectRatio','none');
  this.container.appendChild(this.svgRoot);
}


SVGRenderer.prototype.bounds = function(shape) {
  var rect = new Object();
  var box = shape.getBBox();
  rect['x'] = box.x;
  rect['y'] = box.y;
  rect['width'] =  box.width-18;
  rect['height'] = box.height-18;
  return rect;
}
SVGRenderer.prototype.create = function(shape, fillColor, lineColor, fillOpac, lineOpac, lineWidth, left, top, width, height, textMessaje, textSize, textFamily, imageHref, points, transform, parent) {
  var svgNamespace = 'http://www.w3.org/2000/svg'; 
  var xlinkNS="http://www.w3.org/1999/xlink"; 
 
  var svg;  
  
  if (shape == 'rect') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'rect');
    svg.setAttributeNS(null, 'x', left + 'px');
    svg.setAttributeNS(null, 'y', top + 'px');
    svg.setAttributeNS(null, 'width', width + 'px');
    svg.setAttributeNS(null, 'height', height + 'px');  
    //svg.setAttributeNS(null,'transform', "translate(0,0)");
    //svg.setAttributeNS(null,'transform', "translate('+left+','+top+')");   
    svg.style.position = 'absolute';
  }
  else if (shape == 'ellipse' || shape == 'circle') {
    
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'ellipse');
    svg.setAttributeNS(null, 'cx', (left + width / 2) + 'px');
    svg.setAttributeNS(null, 'cy', (top + height / 2) + 'px');
    if(shape == 'circle'){
     svg.setAttributeNS(null, 'rx', (width / 2) + 'px');
     svg.setAttributeNS(null, 'ry', (width / 2) + 'px');   
    }else{
     svg.setAttributeNS(null, 'rx', (width / 2) + 'px');
     svg.setAttributeNS(null, 'ry', (height / 2) + 'px');   
    
    }
   //svg.setAttributeNS(null,'transform', "translate('+left+','+top+')");  
    svg.style.position = 'absolute';
  }
  else if (shape == 'roundrect') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'rect');
    svg.setAttributeNS(null, 'x', left + 'px');
    svg.setAttributeNS(null, 'y', top + 'px');
    svg.setAttributeNS(null, 'rx', '20px');
    svg.setAttributeNS(null, 'ry', '20px');
    svg.setAttributeNS(null, 'width', width + 'px');
    svg.setAttributeNS(null, 'height', height + 'px');   
   //svg.setAttributeNS(null,'transform', "translate('+left+','+top+')");  
    svg.style.position = 'absolute';
  }
  else if (shape == 'line') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'line');
    svg.setAttributeNS(null, 'x1', left + 'px');
    svg.setAttributeNS(null, 'y1', top + 'px');
    svg.setAttributeNS(null, 'x2', left + width + 'px');
    svg.setAttributeNS(null, 'y2', top + height + 'px');  
    //svg.setAttributeNS(null,'transform', "translate('+left+','+top+')");  
    svg.style.position = 'absolute';
  } 
  else if (shape == 'polyline') {
    var xcenterpoly=xpArray;
    var ycenterpoly=ypArray;
    var thispath=''+xpArray[1]+','+ypArray[1];
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'polyline');  
    svg.setAttributeNS(null, 'points', points);
    svg.style.position = 'absolute';
  }
  else if (shape == 'path')
    {
    var k = (Math.sqrt(2)-1)*4/3;
    var circle="M 0,1 L 0.552,1 1,0.552  1,0  1,-0.552  0.552,-1 0,-1 -0.552,-1 -1,-0.552 -1,0  -1,0.552  -0.552,1  0,1z"  // 4th
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'path');   
    //svg.setAttributeNS(null, 'd', 'M '+thispath+' C'+thispath);
    svg.setAttributeNS(null, 'd', points);  	
    //svg.setAttributeNS(null,'transform', "translate(-80,-80)"); 
    svg.style.position = 'absolute';  
    } 
     else if (shape == 'controlpath')
    {
    var point='M '+left+','+top+' L '+(left+1)+','+(top+1)+'z'  // 4th
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'path');   
    //svg.setAttributeNS(null, 'd', 'M '+thispath+' C'+thispath);
    svg.setAttributeNS(null, 'd', point);  	
    svg.setAttributeNS(null,'transform', "translate(0,0)"); 
    svg.style.position = 'absolute';  
    } 
 else if (shape == 'text') {
    var data = this.container.ownerDocument.createTextNode(textMessaje);
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'text');
    svg.setAttributeNS(null, 'x', parseFloat(left) + 'px');
    svg.setAttributeNS(null, 'y', parseFloat(top) + 'px');
    svg.setAttributeNS(null, 'font-family', textFamily );
    svg.setAttributeNS(null, 'font-size', parseFloat(textSize)); 
    svg.style.position = 'absolute';  
    svg.appendChild(data);   
 } 
  else if (shape == 'clipPath') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'clipPath');
     

 }  
 else if (shape == 'linearGradient') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'linearGradient');
    svg.setAttributeNS(null, 'x1', parseFloat(left));
    svg.setAttributeNS(null, 'y1', parseFloat(top ));
    svg.setAttributeNS(null, 'x2', parseFloat(width));
    svg.setAttributeNS(null, 'y2', parseFloat(height));  

 }  
 else if (shape == 'stop') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'stop');
    svg.setAttributeNS(null, 'stop-color', fillColor);
    svg.setAttributeNS(null, 'stop-opacity', parseFloat(fillOpac));
    svg.setAttributeNS(null, 'offset', parseFloat(lineOpac));  

 } 
  else if (shape == 'group') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'g');
    svg.setAttributeNS(null, 'x', left + 'px');
    svg.setAttributeNS(null, 'y', top + 'px');
    svg.setAttributeNS(null, 'width', width + 'px');
    svg.setAttributeNS(null, 'height', height + 'px');  
    svg.setAttributeNS(null, 'fill-opacity', parseFloat(fillOpac));  
    svg.setAttributeNS(null, 'fill', fillColor);
 //} 

  //else if (shape == 'linearGradient') {
    //return false
 } 
 else if (shape == 'image') { 
   /* svg = this.container.ownerDocument.createElementNS(svgNamespace, 'g');
    svg.setAttributeNS(null, 'x', left + 'px');
    svg.setAttributeNS(null, 'y', top + 'px');
    svg.setAttributeNS(null, 'width', width + 'px');
    svg.setAttributeNS(null, 'height', height + 'px');  
    */
    var svg = this.container.ownerDocument.createElementNS(svgNamespace, 'image');
    svg.setAttributeNS(xlinkNS,'href', imageHref);
    svg.setAttributeNS(null, 'x', left  + 'px');
    svg.setAttributeNS(null, 'y', top + 'px');
    svg.setAttributeNS(null, 'width', width + 'px');
    svg.setAttributeNS(null, 'height', height + 'px');  
    svg.setAttributeNS(null, 'opacity', parseFloat(fillOpac));
    svg.setAttributeNS(null, 'preserveAspectRatio','none');//xMinYMin slice  
    //svg.setAttributeNS(null, 'viewbox', left+' '+top+' '+width+' '+height); 
    //Ext.get(this.container).removeAllListeners(isvg)   
    //svg.appendChild(isvg);
    /* 
    var rsvg = this.container.ownerDocument.createElementNS(svgNamespace, 'rect');
    rsvg.setAttributeNS(null, 'x', left + 'px');
    rsvg.setAttributeNS(null, 'y', top + 'px');
    rsvg.setAttributeNS(null, 'width', width + 'px');
    rsvg.setAttributeNS(null, 'height', height + 'px');  
    rsvg.style.fill = fillColor;  
    rsvg.style.stroke = lineColor;  
    rsvg.style.strokeWidth = lineWidth; 
    rsvg.setAttributeNS(null, 'opacity', '0.1');
    rsvg.style.strokOpacity = lineOpac;
    // Ext.get(this.container).removeAllListeners(rsvg)
     svg.appendChild(rsvg);   

     */
    //svg.setAttributeNS(null, 'color-rendering', fillColor);   
    //svg.setAttributeNS(null, 'display', 'inherit'); 
    
      //alert(fillOpac+'lkjlkj'); 
    //svg.setAttributeNS(null, 'fill-opacity', parseFloat(fillOpac));

    /* if (fillColor.length == 0){fillColor = 'none';}
    if (lineColor.length == 0){lineColor = 'none';}
    svg.style.fill = fillColor;  
    svg.style.stroke = lineColor;  
    svg.style.strokeWidth = lineWidth; 
    svg.style.fillOpacity = fillOpac;
    svg.style.strokOpacity = lineOpac;
     svg.style.setAttributeNS(null, 'fill', fillColor);
          svg.style.setAttributeNS(null, 'stroke', lineColor);
          svg.style.setAttributeNS(null, 'stroke-width', lineWidth);
          svg.style.setAttributeNS(null, 'fill-opacity', fillOpac);  
          svg.style.setAttributeNS(null, 'stroke-opacity',lineOpac);
    
   */
 } 
 
 if(shape == 'zoom') 
  {
        
  }else
  {                                          
       if(transform!='')
        {
         svg.setAttributeNS(null, 'transform', transform);      
        }
        /*
             var render=true;
        if(shape.indexOf('image')>=0){render=false;}
        if(shape.indexOf('group')>=0){render=false;}
        if(shape.indexOf('linearGradient')>=0){render=false;}
        if(shape.indexOf('stop')<=0){render=false;}
        if(render==true) 
        */
       if(shape != 'image' || shape != 'group' || shape != 'stop' )

        { 
                                                               
           //var set = this.container.ownerDocument.createElementNS(svgNamespace, "style");
            
           if (lineColor.length == 0){lineColor = 'none';} 
           if (fillColor.length == 0){fillColor = 'none';} 
          // set.setAttributeNS(null, 'stroke', lineColor);
          //set.setAttributeNS(null, 'stroke-width', lineWidth);
          //set.setAttributeNS(null, 'fill-opacity', fillOpac);  
          //set.setAttributeNS(null, 'stroke-opacity',lineOpac);
            //svg.appendChild(set);
           //svg.setAttributeNS(null, "style","fill:"+ fillColor+";stroke:"+lineColor+";strokeWidth:"+lineWidth+";fill-opacity:"+fillOpac+";stroke-opacity:"+lineOpac);  
           // 
          svg.setAttributeNS(null, 'fill', fillColor);
          svg.setAttributeNS(null, 'stroke', lineColor);
          svg.setAttributeNS(null, 'stroke-width', parseFloat(lineWidth));
          svg.setAttributeNS(null, 'fill-opacity', parseFloat(fillOpac));  
          svg.setAttributeNS(null, 'stroke-opacity',parseFloat(lineOpac));
          svg.setAttributeNS(null, 'stroke-linejoin','round')         
      
          /*     
          <a xlink:href="http://www.w3.org">
                <ellipse cx="2.5" cy="1.5" rx="2" ry="1"  fill="red" />
          </a>
          svg.style.stroke = lineColor;  
           svg.style.strokeWidth = lineWidth; 
           svg.style.fillOpacity = fillOpac;
           svg.style.strokOpacity = lineOpac;   
          if (fillColor.length == 0){fillColor = 'none';}
          
          if (lineColor.length == 0){lineColor = 'none';}
          */
         }   
         
         
     if(parent==''){
       this.svgRoot.appendChild(svg);
     }else{  
       if(document.getElementById(parent)){   
         var parentShape = document.getElementById(parent);
         parentShape.appendChild(svg);
        } 
     }   

          return svg;   
             
   }        
  
};   

SVGRenderer.prototype.create01 = function(shape, fillColor, lineColor, fillOpac, lineOpac, lineWidth, left, top, width, height, textMessaje, textSize, textFamily, imageHref, transform) {
  var svgNamespace = 'http://www.w3.org/2000/svg'; 
  var xlinkNS="http://www.w3.org/1999/xlink"; 
  
  var svg;  
  if (shape == 'rect') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'rect');
    svg.setAttributeNS(null, 'x', left + 'px');
    svg.setAttributeNS(null, 'y', top + 'px');
    svg.setAttributeNS(null, 'width', width + 'px');
    svg.setAttributeNS(null, 'height', height + 'px');  
    //svg.setAttributeNS(null,'transform', "translate(0,0)");
    //svg.setAttributeNS(null,'transform', "translate('+left+','+top+')");   
    svg.style.position = 'absolute';
  }
  else if (shape == 'ellipse') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'ellipse');
    svg.setAttributeNS(null, 'cx', (left + width / 2) + 'px');
    svg.setAttributeNS(null, 'cy', (top + height / 2) + 'px');
    svg.setAttributeNS(null, 'rx', (width / 2) + 'px');
    svg.setAttributeNS(null, 'ry', (height / 2) + 'px');   
   //svg.setAttributeNS(null,'transform', "translate('+left+','+top+')");  
    svg.style.position = 'absolute';
  }
  else if (shape == 'roundrect') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'rect');
    svg.setAttributeNS(null, 'x', left + 'px');
    svg.setAttributeNS(null, 'y', top + 'px');
    svg.setAttributeNS(null, 'rx', '20px');
    svg.setAttributeNS(null, 'ry', '20px');
    svg.setAttributeNS(null, 'width', width + 'px');
    svg.setAttributeNS(null, 'height', height + 'px');   
   //svg.setAttributeNS(null,'transform', "translate('+left+','+top+')");  
    svg.style.position = 'absolute';
  }
  else if (shape == 'line') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'line');
    svg.setAttributeNS(null, 'x1', left + 'px');
    svg.setAttributeNS(null, 'y1', top + 'px');
    svg.setAttributeNS(null, 'x2', left + width + 'px');
    svg.setAttributeNS(null, 'y2', top + height + 'px');  
    //svg.setAttributeNS(null,'transform', "translate('+left+','+top+')");  
    svg.style.position = 'absolute';
  } 
  else if (shape == 'polyline') {
    var xcenterpoly=xpArray;
    var ycenterpoly=ypArray;
    var thispath=''+xpArray[1]+','+ypArray[1];
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'polyline');  
    svg.setAttributeNS(null, 'points', thispath);
    svg.style.position = 'absolute';
  }
  else if (shape == 'path')
    {
    var k = (Math.sqrt(2)-1)*4/3;
    var circle="M 0,1 L 0.552,1 1,0.552  1,0  1,-0.552  0.552,-1 0,-1 -0.552,-1 -1,-0.552 -1,0  -1,0.552  -0.552,1  0,1z"  // 4th
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'path');   
    //svg.setAttributeNS(null, 'd', 'M '+thispath+' C'+thispath);
    svg.setAttributeNS(null, 'd', circle);  	
    svg.setAttributeNS(null,'transform', "translate(0,0)"); 
    svg.style.position = 'absolute';  
    } 
     else if (shape == 'controlpath')
    {
    var point='M '+left+','+top+' L '+(left+1)+','+(top+1)+'z'  // 4th
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'path');   
    //svg.setAttributeNS(null, 'd', 'M '+thispath+' C'+thispath);
    svg.setAttributeNS(null, 'd', point);  	
    svg.setAttributeNS(null,'transform', "translate(0,0)"); 
    svg.style.position = 'absolute';  
    } 
 else if (shape == 'text') {
    var data = this.container.ownerDocument.createTextNode(textMessaje);
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'text');
    svg.setAttributeNS(null, 'x', parseFloat(left) + 'px');
    svg.setAttributeNS(null, 'y', parseFloat(top) + 'px');
    svg.setAttributeNS(null, 'font-family', textFamily );
    svg.setAttributeNS(null, 'font-size', parseFloat(textSize)); 
    svg.style.position = 'absolute';  
    svg.appendChild(data);   
 } 
  else if (shape == 'clipPath') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'clipPath');
     

 }  

  else if (shape == 'group') {
    svg = this.container.ownerDocument.createElementNS(svgNamespace, 'g');
    svg.setAttributeNS(null, 'x', left + 'px');
    svg.setAttributeNS(null, 'y', top + 'px');
    svg.setAttributeNS(null, 'width', width + 'px');
    svg.setAttributeNS(null, 'height', height + 'px');  

 //} 

  //else if (shape == 'linearGradient') {
    //return false
 } 
 else if (shape == 'image') { 
   /* svg = this.container.ownerDocument.createElementNS(svgNamespace, 'g');
    svg.setAttributeNS(null, 'x', left + 'px');
    svg.setAttributeNS(null, 'y', top + 'px');
    svg.setAttributeNS(null, 'width', width + 'px');
    svg.setAttributeNS(null, 'height', height + 'px');  
    */
    var svg = this.container.ownerDocument.createElementNS(svgNamespace, 'image');
    svg.setAttributeNS(xlinkNS,'href', imageHref);
    svg.setAttributeNS(null, 'x', left  + 'px');
    svg.setAttributeNS(null, 'y', top + 'px');
    svg.setAttributeNS(null, 'width', width + 'px');
    svg.setAttributeNS(null, 'height', height + 'px');  
    svg.setAttributeNS(null, 'opacity', parseFloat(fillOpac));
    svg.setAttributeNS(null, 'preserveAspectRatio','none');//xMinYMin slice  
    //svg.setAttributeNS(null, 'viewbox', left+' '+top+' '+width+' '+height); 
    //Ext.get(this.container).removeAllListeners(isvg)   
    //svg.appendChild(isvg);
    /* 
    var rsvg = this.container.ownerDocument.createElementNS(svgNamespace, 'rect');
    rsvg.setAttributeNS(null, 'x', left + 'px');
    rsvg.setAttributeNS(null, 'y', top + 'px');
    rsvg.setAttributeNS(null, 'width', width + 'px');
    rsvg.setAttributeNS(null, 'height', height + 'px');  
    rsvg.style.fill = fillColor;  
    rsvg.style.stroke = lineColor;  
    rsvg.style.strokeWidth = lineWidth; 
    rsvg.setAttributeNS(null, 'opacity', '0.1');
    rsvg.style.strokOpacity = lineOpac;
    // Ext.get(this.container).removeAllListeners(rsvg)
     svg.appendChild(rsvg);   

     */
    //svg.setAttributeNS(null, 'color-rendering', fillColor);   
    //svg.setAttributeNS(null, 'display', 'inherit'); 
    
      //alert(fillOpac+'lkjlkj'); 
    //svg.setAttributeNS(null, 'fill-opacity', parseFloat(fillOpac));

    /* if (fillColor.length == 0){fillColor = 'none';}
    if (lineColor.length == 0){lineColor = 'none';}
    svg.style.fill = fillColor;  
    svg.style.stroke = lineColor;  
    svg.style.strokeWidth = lineWidth; 
    svg.style.fillOpacity = fillOpac;
    svg.style.strokOpacity = lineOpac;
     svg.style.setAttributeNS(null, 'fill', fillColor);
          svg.style.setAttributeNS(null, 'stroke', lineColor);
          svg.style.setAttributeNS(null, 'stroke-width', lineWidth);
          svg.style.setAttributeNS(null, 'fill-opacity', fillOpac);  
          svg.style.setAttributeNS(null, 'stroke-opacity',lineOpac);
    
   */
 } 
 
 if(shape == 'zoom') 
  {
        
  }else
  {                                          
       if(transform!='')
        {
         svg.setAttributeNS(null, 'transform', transform);      
        }
  
        if(shape != 'image')
         { 
                                                               
           //var set = this.container.ownerDocument.createElementNS(svgNamespace, "style");
            
           if (lineColor.length == 0){lineColor = 'none';} 
           if (fillColor.length == 0){fillColor = 'none';} 
          // set.setAttributeNS(null, 'stroke', lineColor);
          //set.setAttributeNS(null, 'stroke-width', lineWidth);
          //set.setAttributeNS(null, 'fill-opacity', fillOpac);  
          //set.setAttributeNS(null, 'stroke-opacity',lineOpac);
            //svg.appendChild(set);
           //svg.setAttributeNS(null, "style","fill:"+ fillColor+";stroke:"+lineColor+";strokeWidth:"+lineWidth+";fill-opacity:"+fillOpac+";stroke-opacity:"+lineOpac);  
           // 
          svg.setAttributeNS(null, 'fill', fillColor);
          svg.setAttributeNS(null, 'stroke', lineColor);
          svg.setAttributeNS(null, 'stroke-width', parseFloat(lineWidth));
          svg.setAttributeNS(null, 'fill-opacity', parseFloat(fillOpac));  
          svg.setAttributeNS(null, 'stroke-opacity',parseFloat(lineOpac));
          svg.setAttributeNS(null, 'stroke-linejoin','round')         
      
          /*     
          <a xlink:href="http://www.w3.org">
                <ellipse cx="2.5" cy="1.5" rx="2" ry="1"  fill="red" />
          </a>
          svg.style.stroke = lineColor;  
           svg.style.strokeWidth = lineWidth; 
           svg.style.fillOpacity = fillOpac;
           svg.style.strokOpacity = lineOpac;   
          if (fillColor.length == 0){fillColor = 'none';}
          
          if (lineColor.length == 0){lineColor = 'none';}
          */
         }
          this.svgRoot.appendChild(svg);
     
          return svg;        
   }        
  
};  

SVGRenderer.prototype.zoom = function(clicx,clicy){ 
/* 
function(direction, amount) { 
var viewBox = this.rootNode.getAttribute('viewBox');
    var viewVals = viewBox.split(' ');
    if (amount == null) {
        amount = SVGElement.panFactor;
    }
    switch (direction) {
        case 'left':
            amount = 0 - amount;
            // intentionally fall through
        case 'right':
            var currentPosition = parseFloat(viewVals[0]);
            currentPosition += amount;
            viewVals[0] = currentPosition;
            break;
        case 'up':
            amount = 0 - amount;
            // intentionally fall through
        case 'down':
            var currentPosition = parseFloat(viewVals[1]);
            currentPosition += amount;
            viewVals[1] = currentPosition;
            break;
        case 'origin':
            // reset everything to initial values
            viewVals[0] = 0;
            viewVals[1] = 0;
            this.rootNode.currentScale = 1;
            this.rootNode.currentTranslate.x = 0;
            this.rootNode.currentTranslate.y = 0;
            break;
    }
    this.rootNode.setAttribute('viewBox', viewVals.join(' '));        
 */
 
      
      
      //canvasWidth
      //canvasheight
   if(zoommode=='frame')
    {   
       var viewBox = this.svgRoot.getAttributeNS(null,'viewBox'); 
     
       //alert(viewBox);
      
       var viewBox = zoominit;  
       var viewVals = viewBox.split(' ');
       
       var corner1x = parseFloat(viewVals[0]); 
       var corner1y = parseFloat(viewVals[1]);  
       var corner2x = parseFloat(viewVals[2]); 
       var corner2y = parseFloat(viewVals[3]);  
    }
     else
    {   
       
       var viewBox = this.svgRoot.getAttributeNS(null,'viewBox'); 
      
       var viewVals = viewBox.split(' ');
       var prevCorner1x = parseFloat(viewVals[0]); 
       var prevCorner1y = parseFloat(viewVals[1]);  
       var prevCorner2x = parseFloat(viewVals[2]); 
       var prevCorner2y = parseFloat(viewVals[3]); 
       var prevWidth=prevCorner2x-prevCorner1x;  
       var prevHeight=prevCorner2y-prevCorner1y;   
        
    }
   
      if(zoommode=='more')
       {  
        var corner1x = prevCorner1x; 
        var corner1y = prevCorner1y;  
        var corner2x = prevCorner2x*0.95; 
        var corner2y = prevCorner2y*0.95;  
       }
      if(zoommode=='minus') 
       {
        var corner1x = prevCorner1x; 
        var corner1y = prevCorner1y;  
        var corner2x = prevCorner2x*1.05; 
        var corner2y = prevCorner2y*1.05;  
       }       
       var direction=0;
      if(zoommode=='hand') 
       {        
        var viewBox = zoominit;  
       var viewVals = viewBox.split(' ');
       
       
       var width = parseFloat(viewVals[2]); 
       var height = parseFloat(viewVals[3]); 
       
       var prevZoomCenterx=centerZoomx 
       var prevZoomCentery=centerZoomy 
       centerZoomx=clicx;
       centerZoomy=clicy; 
        direction=ang2v(prevZoomCenterx,prevZoomCentery,centerZoomx,centerZoomy);
       var distance=dist2p(prevZoomCenterx,prevZoomCentery,centerZoomx,centerZoomy);
       //alert(direction);  
       
       var corner1x = prevCorner1x+distance*Math.cos(direction+Math.PI); 
       var corner1y = prevCorner1y+distance*Math.sin(direction+Math.PI); 
       var corner2x = prevCorner2x+distance*Math.cos(direction+Math.PI); 
       var corner2y = prevCorner2y+distance*Math.sin(direction+Math.PI);   
       
       }
       direction=direction*180/Math.PI;
        //this.svgRoot.currentScale = zoomscale+0.1;
        //this.svgRoot.currentTranslate.x = 0;
        //this.svgRoot.currentTranslate.y = 0; 
        //var resultPosx=clicx-((prevscalex-posx)/2);//-Math.abs(posx+clicx)
        //var resultPosy=clicy-((prevscalex-posy)/2);//-Math.abs(posy+clicy)
        //var resultPosx=-Math.abs(posx+clicx);
        //var resultPosy=-Math.abs(posy+clicy);        

  this.svgRoot.setAttributeNS(null,'viewBox', (corner1x)+' '+(corner1y)+' '+corner2x+' '+corner2y+'');
  var viewBox = this.svgRoot.getAttributeNS(null,'viewBox'); 
  //$('status').innerHTML=' '+viewBox; 
  //alert(direction+'__'+prevZoomCenterx+' '+prevZoomCentery+' '+centerZoomx+' '+centerZoomy);
}  

//this.mode, this.fillColor, this.lineColor, this.fillOpac, this.lineOpac, this.lineWidth, this.mouseDownX, this.mouseDownY, 1, 1,'',''
SVGRenderer.prototype.datacreate = function(fillColor, lineColor, fillOpac, lineOpac, lineWidth, left, top, width, height, textMessaje, textSize, textFamily, imageHref, transform) {
  var svgNamespace = 'http://www.w3.org/2000/svg';
  var svg;
  svg = this.container.ownerDocument.createElementNS(svgNamespace, 'path');   
  svg.setAttributeNS(null, 'd', data);  	
  svg.setAttributeNS(null,'transform', "translate(0,0)"); 
  svg.style.position = 'absolute';  
  if (fillColor.length == 0){fillColor = 'none';}
  svg.setAttributeNS(null, 'fill', fillColor);
  if (lineColor.length == 0){lineColor = 'none';}
  svg.setAttributeNS(null, 'stroke', lineColor);
  svg.setAttributeNS(null, 'stroke-width', lineWidth); 
  this.svgRoot.appendChild(svg);
  return svg;
};

SVGRenderer.prototype.index = function(shape,order) {  
 
     if(order==-1)
      {
        this.svgRoot.appendChild( shape );
      }
      if(order==0){
     
         this.svgRoot.insertBefore( shape, shape.parentNode.firstChild );
      } 
 
   if(order==1 || order==2)
    {
         var id=shape.getAttributeNS(null, 'id');
        //alert(id);
        
        
        var numNodes=this.svgRoot.childNodes.length;
        //alert(numNodes);
          
        var num=0;
        for(var i = 1; i < numNodes; i++)
         {                                                   
           
           var etiq=this.svgRoot.childNodes[i].getAttributeNS(null, 'id');
           if (etiq==id)
            { 
                num=i; 
               
            }                                                    
          } 
          //alert(num);    
          if(order==1) 
           {   
              if((num-1)>=-1)
               {  
                this.svgRoot.insertBefore( shape, this.svgRoot.childNodes[num-1]);
               } 
           }
          if(order==2){ 
               if((num+1)<numNodes)
               {
                  this.svgRoot.insertBefore( shape, this.svgRoot.childNodes[num+2]);
               }
          } 
          
    } 
    
    
   /*var contshapes =  shape.parentNode.childNodes.length;       
   var elem1 = shape;//this.svgRoot.childNodes[1]; 
   var elem2 = shape.parentNode.childNodes[parseInt(contshapes-9)];
    var tmp = elem1.cloneNode( true );
    shape.parentNode.replaceChild( tmp, elem2 );
    shape.parentNode.replaceChild( elem2, elem1 ); 
    */
    //alert(elem2+' '+ elem1 ) 
    //return  elem2;
    
}
SVGRenderer.prototype.remove = function(shape) {
  //shape.parentNode.removeChild(shape);
  try{
  this.svgRoot.removeChild(shape);
  }catch(err){
  	//OMG!
  }
}

SVGRenderer.prototype.removeAll = function() {  
 while( this.svgRoot.hasChildNodes () ){
   this.svgRoot.removeChild( this.svgRoot.firstChild );
 }
   /*var contshapes =  this.svgRoot.childNodes.length;       
    
                          
    var cad=contshapes+'   ';
    for(var i = 0; i < contshapes; i++)
    {                                  
        //alert(i); 
        //cad+=i+'_'+this.svgRoot.childNodes[i].tagName+' ';
        if(this.svgRoot.childNodes[i].id) {
             this.svgRoot.removeChild(this.svgRoot.childNodes[i]);
         }else{
            //cad+=i+'_'+this.svgRoot.childNodes[i].id+' ';
         }
    } 
    //alert(cad);  
*/ 
}

SVGRenderer.prototype.copy = function(shape) 
 {
   var svg;
   svg =shape.cloneNode(false); 
    
    //svg.setAttributeNS(null, 'fill', "#aa00aa");
   return svg;
 };


SVGRenderer.prototype.paste = function(clipboard,left,top) 
 {
   //var svg;
   //svg =shape;
   //clipboard.setAttributeNS(null, 'fill', "#0000aa");
   //clipboard.setAttributeNS(null,'transform', "translate("+left+","+top+")"); 
   this.svgRoot.appendChild(clipboard);
  return clipboard;
 };


SVGRenderer.prototype.duplicate = function(shape) 
 {
   var svg;
   svg =shape.cloneNode(false);
   svg.setAttributeNS(null, 'fill', "#aa00aa");
   this.svgRoot.appendChild(svg);
  return svg;
 };

SVGRenderer.prototype.undo = function() 
 {
  this.svgRoot.removeChild( this.svgRoot.lastChild );
 };
 
 /* 
 function zSwap(parent, elem1, elem2)
{
   var tmp = elem1.cloneNode( true );
   parent.replaceChild( tmp, elem2 );
   parent.replaceChild( elem2, elem1 );
}

SVGRenderer.prototype.moveToTop( svgNode )
{
   this.svgRoot.appendChild( svgNode );
}


SVGRenderer.prototype.moveToBottom( svgNode )
{
   this.svgRoot.insertBefore( svgNode, svgNode.parentNode.firstChild );
}

*/




     
var xshe=0; //bad
var yshe=0;  
var isArc=false;
var contArc=0;
SVGRenderer.prototype.move = function(shape, left, top,fromX,fromY) {  
 //typeTransform='Translate';   
 
 var box = shape.getBBox(); 
 var angle=0;
 var dist=0;  
 var rotated=false;

  if (shape.hasAttributeNS(null,'transform')) { 
    var tran=shape.getAttributeNS(null, 'transform'); 
    //var h=shape.getAttributeNS(null, SVG_TRANSFORM_ROTATE ); 
    var rot= GetString(tran, 'rotate(', ',');
   
   var xy= GetString(tran, ',', ')');
     xy +=')';
   var x= GetString(xy, ' ', ', '); 
   var y= GetString(xy, x+', ', ')');      
   x= parseFloat(x); 
    y= parseFloat(y);  
    angle=parseFloat(rot);
    var centerx=box.x+(box.width/2);
    var centery=box.y+(box.height/2);  
    shape.setAttributeNS(null,'transform', 'rotate('+(angle)+', '+centerx+', '+centery+')'); 
   
    var angleRad=angle*Math.PI/180; 
   
   
      
   //dist=dist2p(x,y,left, top) ;
   dist=dist2p(x,y,left, top) ;
   rotated=true;
   
 }
 
    contmove++;

  if (shape.tagName == 'rect'){ 
  /* var dudy= shape.parentNode;  
   if(dudy.tagName=='g'){
      document.forms[0].code.value= 'this g ============ '; 
           shape.setAttributeNS(null, 'x', left);
           shape.setAttributeNS(null, 'y', top); 
 
           dudy.setAttributeNS(null, 'x', left);
           dudy.setAttributeNS(null, 'y', top); 
           dudy.childNodes[0].setAttributeNS(null, 'x', left);
           dudy.childNodes[0].setAttributeNS(null, 'y', top);
           
    }else{
     //document.forms[0].code.value= box.x+' '+box.y+' formX  Y'+ fromX+'_'+fromY+'  left '+left+'_'+top+'==============';     
     //document.forms[0].code.value+= tran+' rot '+ angle+'_'+x+'_'+y+' dist '+dist;   
     if(rotated){
          //shape.setAttributeNS(null, 'x', box.x*Math.cos(angleRad)) ;
         //shape.setAttributeNS(null, 'y', box.y*Math.sin(angleRad)) ;  
           shape.setAttributeNS(null, 'x', left);
           shape.setAttributeNS(null, 'y', top); 
  

     }else{ 
     */
      shape.setAttributeNS(null, 'x', left);
      shape.setAttributeNS(null, 'y', top); 
     //}
    //$('option_rect_trx').value= left;  
    //$('option_rect_try').value= top;    
       // var h=shape.getAttributeNS(null, 'height');   
       //var w=shape.getAttributeNS(null, 'width'); 
       //document.forms[0].code.value= h+' '+w;
   //}    
  } 
  if (shape.tagName == 'g')
   { 
   this.editor.log(shape.tagName+' ==============');  
   
    shape.setAttributeNS(null, 'x', left);
    shape.setAttributeNS(null, 'y', top);
    shape.childNodes[0].setAttributeNS(null, 'x', left + 'px');
    shape.childNodes[0].setAttributeNS(null, 'y', top + 'px');
    shape.childNodes[1].setAttributeNS(null, 'x', left + 'px');
    shape.childNodes[1].setAttributeNS(null, 'y', top + 'px');
    
   }
  if (shape.tagName == 'image'){
    shape.setAttributeNS(null, 'x', left + 'px');
    shape.setAttributeNS(null, 'y', top + 'px');
    //$('option_img_trx').value= left;  
    //$('option_img_try').value= top;
     var h=shape.getAttributeNS(null, 'height');   
     var w=shape.getAttributeNS(null, 'width'); 
     this.editor.log( h+' '+w);
  }
  if (shape.tagName == 'text'){  
   var size=parseFloat(shape.getAttributeNS(null, 'font-size')); 
   //$('code').value=size;
    shape.setAttributeNS(null, 'x', left + 'px');
    shape.setAttributeNS(null, 'y', parseFloat(top+size) + 'px');
    //$('option_text_trx').value= left;  
    //$('option_text_try').value= top;

  }
  if (shape.tagName == 'line'){ 
    var deltaX = shape.getBBox().width;
    var deltaY = shape.getBBox().height;
    shape.setAttributeNS(null, 'x1', left + 'px');
    shape.setAttributeNS(null, 'y1', top + 'px');

    shape.setAttributeNS(null, 'x2', left + deltaX + 'px');
    shape.setAttributeNS(null, 'y2', top + deltaY + 'px');   
    //$('option_line_trx').value= left;  
    //$('option_line_try').value= top;

  }   
  if (shape.tagName == 'ellipse'){  
    var putx=left + (shape.getBBox().width / 2)    
    var puty= top + (shape.getBBox().height / 2)
    shape.setAttributeNS(null, 'cx', putx + 'px');
    shape.setAttributeNS(null, 'cy', puty + 'px');
    //$('option_ellipse_trx').value= putx;  
    //$('option_ellipse_try').value= puty;

  }
  if (shape.tagName == 'path' || shape.tagName == 'polyline' ) {

   if(contmove==1){ 
      xshe=left;
      yshe=top; 
   }    
 var path=shape.getAttributeNS(null, 'd');
 path=path.replace(/, /g, ','); 
 path=path.replace(/ ,/g, ',');
 var ps =path.split(" ")
 var pcc = "";
 var point =ps[0].split(","); 


 var num0= parseFloat(point[0].substring(1));
 var num1= parseFloat(point[1]); 
 
 var ang= ang2v(box.x,box.y,left,top) ;
 var angle = Math.round((ang/Math.PI* 2)* 360);
 var angx = Math.cos(ang); 
 var angy = Math.sin(ang);          
 var dist= dist2p(left,top,box.x,box.y);
 var xinc=dist*angx;
 var yinc=dist*angy;   
    var re = /^[-]?\d*\.?\d*$/;
 for(var i = 0; i < ps.length; i++)
  { 
   if(ps[i].indexOf(',')>0){  
     
      var point =ps[i].split(","); 
       var char1=point[0].substring(0,1); 
       if(char1=='A' || char1=='a'){isArc=true; contArc=0;}
       if(isArc==true){contArc++}
       if(contArc==4){contArc=0; isArc=false}
       
       //if (isNaN(valnum)) 
      if (!char1.match(re))        
       { 
           var num0= parseFloat(point[0].substring(1));
           var text=char1;
       }else{ 
         if(isArc==true && contArc==2  )
          {
            var num0= point[0];
          }else{  
            var num0= parseFloat(point[0]);
          }  
         var text='';

       }
 
       
       if(isArc==true && contArc==2)
        {   
           point[1]= point[1].toString() ;
        }
        else
        {    
         
          num0+=xinc;    
          point[1]= parseFloat(point[1]);
          point[1]+=yinc;

        }  
        var cx=num0; 
         
        var cy=point[1]; 
        pcc+=text+cx+','+cy+' ';
   }else{
      pcc+=ps[i]+' ';
   }
  }
  
  shape.setAttributeNS(null,'d', pcc);

 }                                                                                                                            
                                                                                                                           
  
//$('status').innerHTML=typeTransform+': '+left+' '+top;
//$('option_select_trx').value= left;  
//$('option_select_try').value= top;  



};



SVGRenderer.prototype.track = function(shape) {
  // TODO
};


SVGRenderer.prototype.clic = function(shape) {
         var end='';
	if(data_path_close==true){end='z';}
        var maxcont=setPoints.length;
        var thispath='M'+setPoints[0]+' ';  
        //$('someinfo').value=maxcont;
      
        for(var conta=1;conta< maxcont;conta++){        
          thispath+='L'+setPoints[conta]+' ';
        }
              //var pointshape=shape.getAttributeNS(null,"d");
         	//shape.setAttributeNS(null,'d',thispath+end);
         	var path=thispath+end;
       
         	shape.setAttributeNS(null,'d',path);
          //      $('control_codebase').value=path;
 
}


SVGRenderer.prototype.resize = function(shape, fromX, fromY, toX, toY) {

   var deltaX = toX - fromX;
  var deltaY = toY - fromY;  
  
     /*      if (lineColor.length == 0){lineColor = 'none';} 
           if (fillColor.length == 0){fillColor = 'none';}
           shape.style.fill = fillColor;  
           shape.style.stroke = lineColor;  
           shape.style.strokeWidth = lineWidth; 
           shape.style.fillOpacity = fillOpac;
           shape.style.strokOpacity = lineOpac;        
      */     
  if (shape.tagName == 'rect' ) 
   { 
    
 
      if (deltaX < 0) {
         shape.setAttributeNS(null, 'x', toX + 'px');
         shape.setAttributeNS(null, 'width', -deltaX + 'px');
       }
        else
       {
         shape.setAttributeNS(null, 'width', deltaX + 'px');
       }
  
      if (deltaY < 0) 
       {
        shape.setAttributeNS(null, 'y', toY + 'px');
        shape.setAttributeNS(null, 'height', -deltaY + 'px');
       }
        else 
       {
        shape.setAttributeNS(null, 'height', deltaY + 'px');
       }
      /*shape.style.fill = fillColor;  
      shape.style.stroke = lineColor;  
      shape.style.strokeWidth = lineWidth; 
      shape.style.fillOpacity = fillOpac;
      shape.style.strokOpacity = lineOpac;         
      */
      
    }
    
  /*  if ( shape.tagName == 'simage' ) 
    {   
        var img=shape.firstChild;//nodeName;//nodparseFloatue;//nodes.item(0);
        //alert(img);
      if (deltaX < 0) {
         shape.setAttributeNS(null, 'x', parseFloat(toX) + 'px');
         shape.setAttributeNS(null, 'width', parseFloat(-deltaX) + 'px');
         
       }
        else
       {
         shape.setAttributeNS(null, 'width', parseFloat(deltaX) + 'px');
       }
  
      if (deltaY < 0) 
       {
        shape.setAttributeNS(null, 'y', parseFloat(toY) + 'px');
        shape.setAttributeNS(null, 'height', parseFloat(-deltaY) + 'px');
       }
        else 
       {
        shape.setAttributeNS(null, 'height', parseFloat(deltaY) + 'px');
       }  
       var h=shape.getAttributeNS(null, 'height');   
       var w=shape.getAttributeNS(null, 'width'); 
       document.forms[0].code.value= h+' '+w;    
       
       
       
    }*/ 
   if (shape.tagName == 'g' || shape.tagName == 'image') 
    {
          

       if (deltaX < 0) 
        {  
          shape.setAttributeNS(null, 'x', parseFloat(toX) + 'px' );
          shape.setAttributeNS(null, 'width', parseFloat(-deltaX)  + 'px');


        }
         else
        {
          shape.setAttributeNS(null, 'width', parseFloat(deltaX)  + 'px');
         }
  
       if (deltaY < 0) 
        {
         shape.setAttributeNS(null, 'y', parseFloat(toY)  + 'px');
         shape.setAttributeNS(null, 'height', parseFloat(-deltaY) + 'px' );
        }
         else 
        {
         shape.setAttributeNS(null, 'height', parseFloat(deltaY) + 'px');
 
        }
     
   } 
  if (shape.tagName == 'ellipse') {
            if (deltaX < 0) {
              shape.setAttributeNS(null, 'cx', (fromX + deltaX / 2) + 'px');
              shape.setAttributeNS(null, 'rx', (-deltaX / 2) + 'px');
            }
            else {
              shape.setAttributeNS(null, 'cx', (fromX + deltaX / 2) + 'px');
              shape.setAttributeNS(null, 'rx', (deltaX / 2) + 'px');
            }
          
            if (deltaY < 0) {
              shape.setAttributeNS(null, 'cy', (fromY + deltaY / 2) + 'px');
              shape.setAttributeNS(null, 'ry', (-deltaY / 2) + 'px');
            }
            else {
              shape.setAttributeNS(null, 'cy', (fromY + deltaY / 2) + 'px');
              shape.setAttributeNS(null, 'ry', (deltaY / 2) + 'px');
            }
  }
  if (shape.tagName == 'line') {
          shape.setAttributeNS(null, 'x2', toX);
          shape.setAttributeNS(null, 'y2', toY);
  } 
  if (shape.tagName == 'polyline') {    
        
       xpArray.push(toX);
          ypArray.push(toY);  
                   var thispath=''+xpArray[1]+','+ypArray[1];  
 		    var thispath1=''; 
		    var thispath2='';
                  var maxcont=xpArray.length;
      
        for(var conta=2;conta< maxcont;conta++){        
          thispath1+=' '+xpArray[conta]+' '+ypArray[conta];
          thispath2+=' '+xpArray[conta]+', '+ypArray[conta];  
	
        }

       
		shape.setAttributeNS(null,'points',thispath+thispath1);
	
	
    }    
    
  if (shape.tagName == 'path') {
        
    if (selectmode == 'controlpath')
     {   
                var end='';
	if(data_path_close==true){end='z';}

        var thispath='M'+setPoints[0]+' ';  
        var maxcont=setPoints.length;
      
        for(var conta=1;conta< maxcont;conta++){        
          thispath+='L'+setPoints[conta]+' ';
          
	
        }                               
        var path=thispath+'L'+toX+','+toY+end;
          //var pointshape=shape.getAttributeNS(null,"d");
         	shape.setAttributeNS(null,'d',path);
               //document.forms[0].control_codebase.value=path;
     }
      else
     { 
  
	  xpArray.push(toX);
          ypArray.push(toY);  
  
                    var thispath=''+xpArray[1]+','+ypArray[1];  
 		    var thispath1=''; 
		    var thispath2='';
                  var maxcont=xpArray.length;
      
        for(var conta=2;conta< maxcont;conta++){        
          //thispath1+=' '+xpArray[conta]+' '+ypArray[conta];
          thispath2+=' '+xpArray[conta]+','+ypArray[conta];  
	  //if((conta+2)%3==0){thispath2+=' C';}
        }
        var end='';
	if(data_path_close==true){end='z';}
		shape.setAttributeNS(null,'d','M '+thispath+ ' L'+thispath2+end);
       
       
          
      /*      
  
           var pointshape=shape.getAttributeNS(null,"points");
          var thispoint=' '+toX+' '+toY;  
             $('status').innerHTML =pointshape; 
        shape.setAttributeNS(null,'points',pointshape+thispoint)
        shape.setAttributeNS(null, 'stroke-width', "25");  
        shape.setAttributeNS(null, 'fill', "#FFFF00");
    
    //shape.points.push(toX);
    //shape.points.push(toY);
    //shape.setAttribute("points",pointshape+);      
         // var maxcont=xpArray.length-1;
          var thispath=''+xpArray[1]+','+ypArray[1];  
       var maxcont=xpArray.length;
       //alert(maxcont);
        for(var conta=2;conta< maxcont;conta++){        
          thispath+=','+xpArray[conta]+','+ypArray[conta]; 
        }
        //alert(shape.points[1]);
    //shape.setAttribute("points",thispath);       
    //points.Value = thispath;       
      var thispath=''+xpArray[1]+','+ypArray[1];  
       var maxcont=xpArray.length;
       //alert(maxcont);
        for(var conta=1;conta< maxcont;conta++){        
          thispath+=','+xpArray[conta]+','+ypArray[conta];
        }
        
        shape.points.Value = thispath;
        */  
          
          
     
  
        /*
 
          
       //this.renderer.move(this.selected, this.selectedBounds.x + deltaX, this.selectedBounds.y + deltaY); 
       // shape.setAttributeNS(null,'transform', "translate("+(toX)+","+(toy)+")");

        
       
         var thispath=''+xpArray[0]+','+ypArray[0]; 
       var maxcont=xpArray.length;
        //shape.setAttributeNS(null,'transform', "translate("+toX+","+toY+")");
        for(var conta=1;conta< maxcont;conta++){        
          thispath+=','+xpArray[conta]+','+ypArray[conta];
        }
           
        shape.setAttributeNS(null, 'x', toX);
        shape.setAttributeNS(null, 'y', toY);
     shape.setAttributeNS(null, 'points', thispath);
      */
    }  
  } 
  if (shape == 'text') {}  
    
}; 
SVGRenderer.prototype.tocurve = function()  
{
  var points=$('control_codebase').value.split('L');
     var chain='';
     chain+=points[0]+'C';
     var numpoints=points.length-1;
     for(var a=1;a<numpoints;a++)
      {
       if(a%3==0)
        { 
         chain+=points[a]+'C';
        }
         else
        {
         chain+=points[a];       
        } 
      } 
      if(numpoints%3==0){
        chain+=points[numpoints]+'';
      } 
      if(numpoints%3==2){
        chain+=points[numpoints-1]+'';
        chain+=points[numpoints]+'';
      } 
      if(numpoints%3==1){ 
        chain+=points[numpoints-1]+'';
        chain+=points[numpoints-1]+'';
        chain+=points[numpoints]+'';
      } 
      if(numpoints%3==3){ 
        chain+=points[numpoints-1]+'';
        chain+=points[numpoints-1]+'';
        chain+=points[numpoints-1]+'';
        chain+=points[numpoints]+'';
      } 

//       $('someinfo').value=numpoints+ ' '+ numpoints%3;
//       $('control_codebase').value=chain; 
      setShape(); 
 }; 
SVGRenderer.prototype.info = function(shape)
{   
 var shInfo = {};
if(shape.id != "tracker"){
 //shInfo.id = shape.id.substr(6); 
 shInfo.id =shape.getAttribute('id');
 shInfo.type = shape.tagName;
 if (shape.hasAttributeNS(null,'transform')) { 
     shInfo.transform = shape.getAttribute('transform');
  }else{
     shInfo.transform ='';
  }   
 
  if(shape.tagName == "text"){   
 
   shInfo.textFamily = shape.getAttribute('font-family')
   shInfo.textSize = parseInt(shape.getAttribute('font-size'))
   shInfo.top = parseFloat(shape.getAttribute('y'))
   shInfo.left = parseFloat(shape.getAttribute('x'))
   shInfo.text = shape.textContent 
   shInfo.lineWidth = parseFloat(shape.getAttribute('stroke-width'))

   //shInfo.text = shape.nodparseFloatue;
   }
      
 
 if(shape.tagName !='image' || shape.tagName !='g' || shape.tagName !='stop')
  {
    shInfo.fillColor = shape.getAttribute('fill')
    shInfo.lineColor = shape.getAttribute('stroke')  
    shInfo.fillOpac = parseFloat(shape.getAttribute('fill-opacity'))
    shInfo.lineOpac = parseFloat(shape.getAttribute('stroke-opacity'))
    shInfo.lineWidth = parseFloat(shape.getAttribute('stroke-width'))
    
    var mystyle= shape.getAttribute('style'); 
    
    if(mystyle!= null && mystyle.indexOf('<![CDATA[')>=0)
     {
      
     }
      else
     {
      // shInfo.style=shape.getAttribute('style');
     
    if(mystyle!= null){
      //var estilo=shape.getAttribute('style');

   
      var estilo=generateJSON(mystyle);
      var data = eval("("+estilo+")");
      //var data=eval('"'+estilo+'"'); 
      //var data=estilo.evalJSON(); 
    
      (data["font-size"])?shInfo.textSize=data["font-size"]:shInfo.textSize; 
      (data["font-family"])?shInfo.textFamily=data["font-family"]:shInfo.textFamily; 
      
      (data.fill)?shInfo.fillColor=data.fill:shInfo.fillColor; 
      (data.stroke)?shInfo.lineColor=data.stroke:shInfo.lineColor;
      (data.transform)?shInfo.transform=data.transform:shInfo.transform;
      (data["fill-opacity"])?shInfo.fillOpac=data["fill-opacity"]:shInfo.fillOpac; 
       //shInfo.fillColor=data.fill;
      //document.getElementById("someinfo").value +=data.fill+' ';//estilo ;//data['fill']+' ';//
    }
   }
  }  
 
 
 if (shape.tagName == 'rect') 
   {
   if(shape.getAttribute('rx') || shape.getAttribute('ry')){
   shInfo.type = "roundrect";
   shInfo.rx = parseFloat(shape.getAttribute('rx'))
   shInfo.ry = parseFloat(shape.getAttribute('rx'))
   }
    shInfo.left = parseFloat(shape.getAttribute( 'x'));
    shInfo.top = parseFloat(shape.getAttribute( 'y'));
    shInfo.width = parseFloat(shape.getAttribute('width'));
    shInfo.height = parseFloat(shape.getAttribute('height'));  
   }
  else if (shape.tagName == 'ellipse' || shape.tagName == 'circle') 
   {     
    if(shape.tagName == 'circle'){
      shInfo.width = parseFloat(shape.getAttribute('r'))*2; 
      shInfo.height = parseFloat(shape.getAttribute('r'))*2; 
     }else{
      shInfo.width = parseFloat(shape.getAttribute('rx'))*2;
      shInfo.height = parseFloat(shape.getAttribute('ry'))*2;   
     }
    
    shInfo.left =    parseFloat(shape.getAttribute('cx')) - (shInfo.width/2);
    shInfo.top =  parseFloat(shape.getAttribute('cy')) - (shInfo.height/2)  ;
   }
   else if(shape.tagName == 'linearGradient') {   
    shInfo.left = (shape.getAttribute( 'x1'));
    shInfo.top = parseFloat(shape.getAttribute( 'y1'));
    shInfo.width = parseFloat(shape.getAttribute('x2'));
    shInfo.height = parseFloat(shape.getAttribute('y2'));  

   }
   else if(shape.tagName == 'stop') {
    shInfo.fillColor = shape.getAttribute('stop-color');
    shInfo.fillOpac = shape.getAttribute('stop-opacity');
    shInfo.lineOpac = shape.getAttribute('offset');
    var mystyle= shape.getAttribute('style');
    if(mystyle!= null && mystyle.indexOf('<![CDATA[')>=0)
     {
      
     }
      else
     {
    if(mystyle!= null){
      
      var estilo=generateJSON(mystyle);
      var data = eval("("+estilo+")");
      (data["stop-color"])?shInfo.fillColor=data["stop-color"]:shInfo.fillColor;
      (data["stop-opacity"])?shInfo.fillOpac=data["stop-opacity"]:shInfo.fillOpac;
      document.getElementById("someinfo").value +=data["stop-color"]+' '; 
     } 
     
    }
   }
  else if (shape.tagName == 'line') 
   {
    shInfo.left = parseFloat(shape.getAttribute('x1'));
    shInfo.top = parseFloat(shape.getAttribute('y1'));
    shInfo.width = parseFloat(shape.getAttribute('x2')) -shInfo.left;
    shInfo.height = parseFloat(shape.getAttribute('y2')) -shInfo.top;
   } 
  else if (shape.tagName == 'polyline') 
   {
    shInfo.points = shape.getAttribute('points');
   } 
  else if (shape.tagName == 'g') 
   { 
    shInfo.type = "group";
    shInfo.left = parseFloat(shape.getAttribute( 'x'));
    shInfo.top = parseFloat(shape.getAttribute( 'y'));
    shInfo.width = parseFloat(shape.getAttribute('width'));
    shInfo.height = parseFloat(shape.getAttribute('height'));  
    shInfo.fillColor = shape.getAttribute('fill')

   }   
  else if (shape.tagName == 'path')
   {
    shInfo.points = shape.getAttribute('d');     
    //shInfo.transform = shape.getAttribute('transform'); 
 
    //alert(shInfo.transform);
    //document.forms[0].codebase.value=shape.getAttribute('d'); 
   
   }
  else 
  
 
  if (shape.tagName == 'image')
   {                                     
    
    shInfo.left = parseFloat(shape.getAttribute( 'x'));
    shInfo.top = parseFloat(shape.getAttribute( 'y'));
    shInfo.width = parseFloat(shape.getAttribute('width'));
    shInfo.height = parseFloat(shape.getAttribute('height'));   
    shInfo.fillOpac = parseFloat(shape.getAttribute('opacity'));   
    shInfo.href = shape.getAttribute('href');  
     
  } 
  if(shape.parentNode.tagName != 'svg'){
    //shInfo.width = parseFloat(shape.getAttribute('width'));
    //shInfo.height = parseFloat(shape.getAttribute('height'));   
    //shInfo.viewBox = parseFloat(shape.getAttribute('viewBox'));   
    shInfo.parent=shape.parentNode.getAttribute('id');

  }
    return shInfo;  
  }else{
   //do nothing if its the tracker
   }
  
   	
   	
};     
SVGRenderer.prototype.info01 = function(shape)
{   

var shInfo = {};
if(shape.id != "tracker"){
shInfo.id = shape.id.substr(6);
 shInfo.type = shape.tagName;
 if (shape.hasAttributeNS(null,'transform')) { 
     shInfo.transform = shape.getAttribute('transform');
  }else{
     shInfo.transform ='';
  }   
     
 
 if(shape.tagName !='image')
  {
    shInfo.fillColor = shape.getAttribute('fill')
    shInfo.lineColor = shape.getAttribute('stroke')  
    shInfo.fillOpac = parseFloat(shape.getAttribute('fill-opacity'))
    shInfo.lineOpac = parseFloat(shape.getAttribute('stroke-opacity'))
    shInfo.lineWidth = parseFloat(shape.getAttribute('stroke-width'))
  }  
 
 
 if (shape.tagName == 'rect') 
   {
   if(shape.getAttribute('rx') || shape.getAttribute('ry')){
   shInfo.type = "roundrect";
   shInfo.rx = parseFloat(shape.getAttribute('rx'))
   shInfo.ry = parseFloat(shape.getAttribute('rx'))
   }
    shInfo.left = parseFloat(shape.getAttribute( 'x'));
    shInfo.top = parseFloat(shape.getAttribute( 'y'));
    shInfo.width = parseFloat(shape.getAttribute('width'));
    shInfo.height = parseFloat(shape.getAttribute('height'));  
   }
  else if (shape.tagName == 'ellipse') 
   {
    shInfo.width = parseFloat(shape.getAttribute('rx'))*2;
    shInfo.height = parseFloat(shape.getAttribute('ry'))*2;   
    shInfo.left =    parseFloat(shape.getAttribute('cx')) - (shInfo.width/2);
    shInfo.top =  parseFloat(shape.getAttribute('cy')) - (shInfo.height/2)  ;
 
   }
  else if (shape.tagName == 'line') 
   {
    shInfo.left = parseFloat(shape.getAttribute('x1'));
    shInfo.top = parseFloat(shape.getAttribute('y1'));
    shInfo.width = parseFloat(shape.getAttribute('x2')) -shInfo.left;
    shInfo.height = parseFloat(shape.getAttribute('y2')) -shInfo.top;
   } 
  else if (shape.tagName == 'polyline') 
   {
    shInfo.points = shape.getAttribute('points');
   }
  else 
  
  if (shape.tagName == 'path')
   {
    shInfo.d = shape.getAttribute('d');     
    //shInfo.transform = shape.getAttribute('transform'); 
 
    //alert(shInfo.transform);
    //document.forms[0].codebase.value=shape.getAttribute('d'); 
   
   }
  else 
  
  if(shape.tagName == "text"){   
 
   shInfo.textFamily = shape.getAttribute('font-family')
   shInfo.textSize = parseInt(shape.getAttribute('font-size'))
   shInfo.top = parseFloat(shape.getAttribute('y'))
   shInfo.left = parseFloat(shape.getAttribute('x'))
   shInfo.text = shape.textContent 
   shInfo.lineWidth = parseFloat(shape.getAttribute('stroke-width'))

   //shInfo.text = shape.nodparseFloatue;
   }
  else
 
  if (shape.tagName == 'image')
   {                                     
    
    shInfo.left = parseFloat(shape.getAttribute( 'x'));
    shInfo.top = parseFloat(shape.getAttribute( 'y'));
    shInfo.width = parseFloat(shape.getAttribute('width'));
    shInfo.height = parseFloat(shape.getAttribute('height'));   
    shInfo.fillOpac = parseFloat(shape.getAttribute('opacity'));   
    shInfo.href = shape.getAttribute('href');  
     
  }
  
    return shInfo;  
  }else{
   //do nothing if its the tracker
   }

   	
}





SVGRenderer.prototype.transformShape = function(shape,data,transform)
{      
  var svgNamespace = 'http://www.w3.org/2000/svg'; 
  var xlinkNS="http://www.w3.org/1999/xlink"; 
   //
 
 if(shape.tagName == 'rect')
  { 
    var box = shape.getBBox();
    var sdata=data.split(';'); 
    
    //alert(data[0]);     
    shape.setAttributeNS(null,'x',parseFloat(sdata[0]));
    shape.setAttributeNS(null,'y',parseFloat(sdata[1]));   
    shape.setAttributeNS(null, 'width', parseFloat(sdata[2]));     
    shape.setAttributeNS(null, 'height', parseFloat(sdata[3])); 
    var centerx=parseFloat(sdata[0])+parseFloat(box.width/2);
    var centery=parseFloat(sdata[1])+parseFloat(box.height/2);    
    shape.setAttributeNS(null, 'transform','rotate('+parseFloat(sdata[4])+','+centerx+','+centery+')');
    
   //shape.nodparseFloatue=data;
  }
   else 
 if(shape.tagName == 'text')
  {    
    if(data.indexOf('<;>',0)==-1 )
     {  
      shape.textContent = data;  
     }
      else
     {  
       var sdata=data.split('<;>'); //?????????
       shape.textContent = sdata[0]; 
       shape.setAttributeNS(null,'font-size',parseFloat(sdata[1])); 
        shape.setAttributeNS(null,'font-family',sdata[2]);
     }
   //shape.nodparseFloatue=data;
  }
   else
 if (shape.tagName == 'polyline') 
  {
    shape.setAttributeNS(null,'points',data);
  }
   else 
 if (shape.tagName == 'image') 
  {   
    //alert(data);  
    if(data.indexOf(';',0)==-1 )
     {  
      shape.setAttributeNS(xlinkNS,'href',data);
     }
      else
     {  
        var box = shape.getBBox();
        var sdata=data.split(';');
        shape.setAttributeNS(null,'x',parseFloat(sdata[0]));
        shape.setAttributeNS(null,'y',parseFloat(sdata[1]));   
        shape.setAttributeNS(null, 'width', parseFloat(sdata[2])); 
        shape.setAttributeNS(null, 'height',parseFloat(sdata[3]));  
        var centerx=parseFloat(sdata[0])+parseFloat(box.width/2);
        var centery=parseFloat(sdata[1])+parseFloat(box.height/2);    
        shape.setAttributeNS(null, 'transform',' rotate('+parseFloat(sdata[4])+','+centerx+','+centery+')');


     } 
      
  }
   else 
 if (shape.tagName == 'path')
  {     
    if(data.indexOf(';',0)==-1 )
     {  
    	shape.setAttributeNS(null, 'd', data);  
    	shape.setAttributeNS(null, 'transform', transform);  
     }
      else
     {  
        var box = shape.getBBox();
        var sdata=data.split(';');
        var centerx=parseFloat(sdata[0])+parseFloat(box.width/2);
        var centery=parseFloat(sdata[1])+parseFloat(box.height/2);    
        shape.setAttributeNS(null, 'transform','scale('+parseFloat(sdata[2])+','+parseFloat(sdata[3])+')'+' rotate('+parseFloat(sdata[4])+','+centerx+','+centery+')'+' translate('+parseFloat(sdata[0])+','+parseFloat(sdata[1])+')');


     } 
  }  
   	                             
	                             
}
SVGRenderer.prototype.editShape = function(shape,data)
{   
 if(shape.tagName == 'text'){
   shape.textContent = data
 }else
   if (shape.tagName == 'polyline') 
   {
    shape.setAttributeNS(null,'points',data);
   }
  else 
  
  if (shape.tagName == 'path')
   {
    	shape.setAttributeNS(null, 'd', data);  
    	
   }  
	
}
SVGRenderer.prototype.editCommand = function(shape, cmd, value)
{
  if (shape != null) {
    if (cmd == 'fillcolor') {
      if (value != '')
        shape.setAttributeNS(null, 'fill', value);
      else
        shape.setAttributeNS(null, 'fill', 'none');
    }
    else if (cmd == 'linecolor') {
      if (value != '')
        shape.setAttributeNS(null, 'stroke', value);
      else
        shape.setAttributeNS(null, 'stroke', 'none');
    }
    else if (cmd == 'linewidth') {
      shape.setAttributeNS(null, 'stroke-width', parseInt(value) + 'px');
    } 
    else if (cmd == 'fillopacity') {
           if(shape.tagName=='image')
            {
             shape.setAttributeNS(null, 'opacity', parseFloat(value));
            }
             else
            {
                shape.setAttributeNS(null, 'fill-opacity', parseFloat(value));
            }    
      
    }
    else if (cmd == 'lineopacity') {         
      
      shape.setAttributeNS(null, 'stroke-opacity', parseFloat(value));
      
    }

  }
}


SVGRenderer.prototype.queryCommand = function(shape, cmd)
{
  var result = '';
  
  if (shape != null) {
    if (cmd == 'fillcolor') {
      result = shape.getAttributeNS(null, 'fill');
      if (result == 'none')
        result = '';
    }
    else if (cmd == 'linecolor') {
      result = shape.getAttributeNS(null, 'stroke');
      if (result == 'none')
        result = '';
    }
    else if (cmd == 'linewidth') {
      result = shape.getAttributeNS(null, 'stroke');
      if (result == 'none')
        result = '';
      else
        result = shape.getAttributeNS(null, 'stroke-width');
    }
    else if (cmd == 'fillopacity') {
           if(shape.tagName=='image')
            {
             shape.setAttributeNS(null, 'opacity', parseFloat(value));
            }
             else
            {
                shape.setAttributeNS(null, 'fill-opacity', parseFloat(value));
            }    
      
    }
    else if (cmd == 'lineopacity') {         
      
      shape.setAttributeNS(null, 'stroke-opacity', parseFloat(value));
      
    }

  }
  
  return result;
}

SVGRenderer.prototype.getProperties = function(shape){}


SVGRenderer.prototype.showMultiSelect = function(iniX,iniY) { 
  var tracker = document.getElementById('trackerMultiSelect');
  if (tracker) {
    this.remove(tracker);
  }
  
  var coord=this.editor.inputxy;
	toX=parseFloat(coord[0]);
	toY=parseFloat(coord[1]); 
	
    tracker = document.createElementNS(svgNamespace, 'rect'); 
      
    tracker.setAttributeNS(null, 'x', iniX);
    tracker.setAttributeNS(null, 'y', iniY);    
  tracker.setAttributeNS(null, 'width', toX);
  tracker.setAttributeNS(null, 'height', toY);
  tracker.setAttributeNS(null, 'fill', '#ffffff');
  tracker.setAttributeNS(null, 'stroke', 'green');
  tracker.setAttributeNS(null, 'stroke-width', '1');  
  
   this.svgRoot.appendChild(tracker);     
}


function mouseCoord()
{                                           
   var coord=this.editor.inputxy;
   coord[0]=parseFloat(coord[0]);
   coord[1]=parseFloat(coord[1]); 
   return coord
} 
/*
function nodeHit(node)
{                                           
   node.addEventListener("mousemove", function(event) {nodeMove(node)}, false);            
  
}

function nodeUp(node)
{                                           
   //node.stopObserving("mousemove");
}                                                                             

function nodeMove(node)
{                                           
   var mypath=$('control_codebase').value; 
   var  x= $('option_path_x').value;
   var y= $('option_path_y').value; 
   var precoord=x+','+y; 
    var coord=mouseCoord(); 
   node.setAttributeNS(null, 'x', coord[0]-2); 
   node.setAttributeNS(null, 'y', coord[1]-2); 

   $('option_path_x').value=parseFloat(node.getAttributeNS(null,'x'))+2; 
   $('option_path_y').value=parseFloat(node.getAttributeNS(null,'y'))+2; 
   
    var  cadx= $('option_path_x').value;
    var cady= $('option_path_y').value; 
    var coord=cadx+','+cady;
          var cad1=new RegExp(precoord,"g");
      
      
      var result=mypath.replace(cad1, coord);
      
     
      $('control_codebase').value=result; 
      
      $('someinfo').value=precoord;
      setShape();

    
    
} 
*/                                                                              
var memoNode=null; 
var memoPrevControl=new Array();
var memoNextControl=new Array();
SVGRenderer.prototype.nodeMove = function(newx,newy) { 
    var mypath=$('control_codebase').value; 
   var  x= $('option_path_x').value;
   var y= $('option_path_y').value; 
   var precoord=x+','+y; 
   
   $('option_path_x').value=newx; 
   $('option_path_y').value=newy; 
    
      var  cadx= newx;
      var cady= newy; 
  
      var coord=cadx+','+cady;
          var cad1=new RegExp(precoord,"g");
      
      
      var result=mypath.replace(cad1, coord);
      
     
      //$('control_codebase').value=result; 
      
      //$('someinfo').value=precoord;
      setShape();

}

function drawNodeControl(svg,numId){

      var svgNamespace = 'http://www.w3.org/2000/svg';
      var color1='#0066ff';          
           // if(parseInt(memoNode.id)==a){   
                   
                   var pointprev=memoPrevControl[numId].split(',');
            
                  var controlNode1 = document.createElementNS(svgNamespace, 'rect'); 
                  controlNode1.setAttributeNS(null, 'x', pointprev[0]-2);
                  controlNode1.setAttributeNS(null, 'y', pointprev[1]-2);
          
                  controlNode1.setAttributeNS(null, 'width', 4);
                  controlNode1.setAttributeNS(null, 'height', 4);
                  controlNode1.setAttributeNS(null, 'fill', color1);
                  controlNode1.setAttributeNS(null, 'stroke', '#000000');
                  controlNode1.setAttributeNS(null, 'stroke-width', '0'); 
                  controlNode1.setAttributeNS(null, 'id', 'controlNode1'); 
                  controlNode1.addEventListener("mousedown", function(event) {if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );} memoNode=this; this.setAttributeNS(null, 'fill-color', '#ffff00' );this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2;  }, false);
                  svg.appendChild(controlNode1);  
                  
                   var pointnext=memoNextControl[numId].split(',');
                  
               
                  var controlNode2 = document.createElementNS(svgNamespace, 'rect'); 
                  controlNode2.setAttributeNS(null, 'x', pointnext[0]-2);
                  controlNode2.setAttributeNS(null, 'y', pointnext[1]-2);
          
                  controlNode2.setAttributeNS(null, 'width', 4);
                  controlNode2.setAttributeNS(null, 'height', 4);
                  controlNode2.setAttributeNS(null, 'fill', color1);
                  controlNode2.setAttributeNS(null, 'stroke', '#000000');
                  controlNode2.setAttributeNS(null, 'stroke-width', '0'); 
                  controlNode2.setAttributeNS(null, 'id', 'controlNode1'); 
                  controlNode2.addEventListener("mousedown", function(event) {if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );} memoNode=this; this.setAttributeNS(null, 'fill-color', '#ffff00' );this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2;  }, false);
                  svg.appendChild(controlNode2);  

            //}


}  
                                                                   
SVGRenderer.prototype.showNodesCurve = function(path,controlNodeNum){ 
     memoNextControl=new Array();
     memoPrevControl=new Array();
     var svgNamespace = 'http://www.w3.org/2000/svg';
    // tracker = document.createElementNS(svgNamespace, 'g');   
     var svg = this.container.ownerDocument.createElementNS(svgNamespace, 'g'); 
      svg.setAttributeNS(null, 'id', 'editNodesPath'); 

     /* var group = document.getElementById('editNodesPath');
      if (group) 
       {
           this.remove(group);
       }
       */

  var points=path.split(' ');
     var chain='';
     var segment=' ';  
     prevControl=' ';
     nextControl=' ';
     nodePoint=' ';
      var init=points[0].split('M'); 
      var allcoords=init[1].split(' ');
      var point=allcoords[0].split(',');
          var rect1 = document.createElementNS(svgNamespace, 'rect');  
        rect1.setAttributeNS(null, 'x', point[0]-2);
        rect1.setAttributeNS(null, 'y', point[1]-2);
          
        rect1.setAttributeNS(null, 'width', 4);
        rect1.setAttributeNS(null, 'height', 4);
        rect1.setAttributeNS(null, 'fill', '#ff7700');
        rect1.setAttributeNS(null, 'stroke', '#000000');
        rect1.setAttributeNS(null, 'stroke-width', '0');  
        rect1.setAttributeNS(null, 'id', '0'); 
        //rect1.addEventListener("mouseover", function(event) {this.setAttributeNS(null, 'stroke-width', 1 ); }, false);
      rect1.addEventListener("mousedown", function(event) {if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );} memoNode=this; this.setAttributeNS(null, 'fill-color', '#ffff00' );this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2;  }, false);

        //rect1.addEventListener("mouseout", function(event) {this.setAttributeNS(null, 'stroke-width', 0 );}, false);

        svg.appendChild(rect1);                                    
      
          if(controlNodeNum==0){ var color='#ffff00';}  
         if(controlNodeNum==1){var color='#00ffff';}  
         if(controlNodeNum==2){var color='#00cc00';}  
         var color1='#ffff00';
      
     var numpoints=points.length-1;  
     var recalls='';
     var re = /^[-]?\d*\.?\d*$/;
     for(var a=1;a<=numpoints;a++)
      { 
        
        var ini=points[a].substring(0,1);
        if (!ini.match(re))        
        {                          
          var end=points[a].substring(1); 
          color='#0000ff';
          if(ini=='L' || ini=='M')
           {
             color='#ffff00';
           }
          
          if(ini=='C')
          { 
             recall=a+2;
             //color='#ffff00';
          }

        }else
        { 
          var end=points[a];
          var ini='';  
          color='#ff00ff'; 
          if(a==recalls)
          { 
             color='#ffff00';
          }
        } 
        
            
        //segment=points[a].split(',');
         /*prevControl=segment[0]+' '; 
         nextControl=segment[1]+' '; 
         nodePoint=segment[2]+' ';     
         memoPrevControl[a]=prevControl;
         memoNextControl[a]=nextControl;
         if(controlNodeNum==0){chain+=prevControl; var point=prevControl.split(',');}  
         if(controlNodeNum==1){chain+=nextControl; var point=nextControl.split(',');}  
         if(controlNodeNum==2){chain+=nodePoint; var point=nodePoint.split(',');}  
         if(controlNodeNum==3){chain+=nodePoint; var point=nodePoint.split(',');}
           
         */    
               //if (isNaN(valnum))         

         //if(ini=='C'){color='#ff00ff';}
         
         var point=end.split(',');
         if(memoNode!=null){
         }
          var rect1 = document.createElementNS(svgNamespace, 'rect');  
        rect1.setAttributeNS(null, 'x', point[0]-2);
        rect1.setAttributeNS(null, 'y', point[1]-2);
          
        rect1.setAttributeNS(null, 'width', 4);
        rect1.setAttributeNS(null, 'height', 4);
        rect1.setAttributeNS(null, 'fill', color);
        rect1.setAttributeNS(null, 'stroke', '#000000');
        rect1.setAttributeNS(null, 'stroke-width', '0'); 
        rect1.setAttributeNS(null, 'id', ''+a); 
        rect1.addEventListener("mousedown", function(event) {if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );}drawNodeControl(svg,this.getAttributeNS(null,'id')); memoNode=this; this.setAttributeNS(null, 'fill-color', '#ffff00' );this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2;  }, false);

        //rect1.addEventListener("mouseover", function(event) {this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2; }, false);
        // rect1.addEventListener("mousedown", function(event) {nodeHit(this);if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );} memoNode=this; this.setAttributeNS(null, 'fill-color', '#ffff00' );this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2; document.forms[0].option_path_x.focus(); }, false);
         //rect1.addEventListener("mousedown", function(event) { if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );} nodeHit(this); memoNode=this;this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2; }, false);
         //rect1.addEventListener("mousedown", function(event) {if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );} addControlPoints(segment[0],segment[1],svg); memoNode=this; this.setAttributeNS(null, 'fillColor', '#ffff00' );this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2; }, false);
         //rect1.addEventListener("mouseup", function(event) {nodeUp(this); }, false);
         //rect1.addEventListener("mouseover", function(event) {this.setAttributeNS(null, 'fillColor', '#ffcc00' ); }, false);
         //rect1.addEventListener("mouseout", function(event) {this.setAttributeNS(null, 'fillColor', '#00cc00' ); }, false);
         

         //rect1.addEventListener("mouseout", function(event) {this.setAttributeNS(null, 'stroke-width', 0 ); }, false);

        svg.appendChild(rect1);                                    
         
      }                     
      var info='';
       
         if(controlNodeNum==0){info='prev Control'}  
         if(controlNodeNum==1){info='next Control'}  
         if(controlNodeNum==2){info='points node'}   
        // $('someinfo').value=numpoints+ ' '+info+':'+ chain;
//         $('someinfo').value='Crtl+Arrow to move';
    //return chain;                                          
    

      //this.svgRoot.appendChild(svg);   
    
    return svg;  
        
};

SVGRenderer.prototype.showNodesCurve1 = function(path,controlNodeNum){ 
     memoNextControl=new Array();
     memoPrevControl=new Array();
     var svgNamespace = 'http://www.w3.org/2000/svg';
    // tracker = document.createElementNS(svgNamespace, 'g');   
     var svg = this.container.ownerDocument.createElementNS(svgNamespace, 'g'); 
      svg.setAttributeNS(null, 'id', 'editNodesPath'); 

     /* var group = document.getElementById('editNodesPath');
      if (group) 
       {
           this.remove(group);
       }
       */

  var points=path.split('C');
     var chain='';
     var segment=' ';  
     prevControl=' ';
     nextControl=' ';
     nodePoint=' ';
      var init=points[0].split('M'); 
      var allcoords=init[1].split(' ');
      var point=allcoords[0].split(',');
          var rect1 = document.createElementNS(svgNamespace, 'rect');  
        rect1.setAttributeNS(null, 'x', point[0]-2);
        rect1.setAttributeNS(null, 'y', point[1]-2);
          
        rect1.setAttributeNS(null, 'width', 4);
        rect1.setAttributeNS(null, 'height', 4);
        rect1.setAttributeNS(null, 'fill', '#ff7700');
        rect1.setAttributeNS(null, 'stroke', '#000000');
        rect1.setAttributeNS(null, 'stroke-width', '0');  
        rect1.setAttributeNS(null, 'id', '0'); 
        //rect1.addEventListener("mouseover", function(event) {this.setAttributeNS(null, 'stroke-width', 1 ); }, false);
        rect1.addEventListener("mousedown", function(event) {if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );} memoNode=this; this.setAttributeNS(null, 'fill-color', '#ffff00' );this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2;  }, false);

        //rect1.addEventListener("mouseout", function(event) {this.setAttributeNS(null, 'stroke-width', 0 );}, false);

        svg.appendChild(rect1);                                    
      
          if(controlNodeNum==0){ var color='#ffff00';}  
         if(controlNodeNum==1){var color='#00ffff';}  
         if(controlNodeNum==2){var color='#00cc00';}  
         var color1='#ffff00';
      
     var numpoints=points.length-1;
     for(var a=1;a<=numpoints;a++)
      { 
        
        
            
        segment=points[a].split(' ');
         prevControl=segment[0]+' '; 
         nextControl=segment[1]+' '; 
         nodePoint=segment[2]+' ';     
         memoPrevControl[a]=prevControl;
         memoNextControl[a]=nextControl;
         if(controlNodeNum==0){chain+=prevControl; var point=prevControl.split(',');}  
         if(controlNodeNum==1){chain+=nextControl; var point=nextControl.split(',');}  
         if(controlNodeNum==2){chain+=nodePoint; var point=nodePoint.split(',');}  
         if(controlNodeNum==3){chain+=nodePoint; var point=nodePoint.split(',');}  
      
         if(memoNode!=null){
         }
          var rect1 = document.createElementNS(svgNamespace, 'rect');  
        rect1.setAttributeNS(null, 'x', point[0]-2);
        rect1.setAttributeNS(null, 'y', point[1]-2);
          
        rect1.setAttributeNS(null, 'width', 4);
        rect1.setAttributeNS(null, 'height', 4);
        rect1.setAttributeNS(null, 'fill', color);
        rect1.setAttributeNS(null, 'stroke', '#000000');
        rect1.setAttributeNS(null, 'stroke-width', '0'); 
        rect1.setAttributeNS(null, 'id', ''+a); 
        rect1.addEventListener("mousedown", function(event) {if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );}drawNodeControl(svg,this.getAttributeNS(null,'id')); memoNode=this; this.setAttributeNS(null, 'fill-color', '#ffff00' );this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2;  }, false);

        //rect1.addEventListener("mouseover", function(event) {this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2; }, false);
        // rect1.addEventListener("mousedown", function(event) {nodeHit(this);if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );} memoNode=this; this.setAttributeNS(null, 'fill-color', '#ffff00' );this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2; document.forms[0].option_path_x.focus(); }, false);
         //rect1.addEventListener("mousedown", function(event) { if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );} nodeHit(this); memoNode=this;this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2; }, false);
         //rect1.addEventListener("mousedown", function(event) {if(memoNode != null){memoNode.setAttributeNS(null, 'stroke-width', 0 );} addControlPoints(segment[0],segment[1],svg); memoNode=this; this.setAttributeNS(null, 'fillColor', '#ffff00' );this.setAttributeNS(null, 'stroke-width', 1 );$('option_path_num').value=this.getAttributeNS(null,'id'); $('option_path_x').value=parseFloat(this.getAttributeNS(null,'x'))+2; $('option_path_y').value=parseFloat(this.getAttributeNS(null,'y'))+2; }, false);
         //rect1.addEventListener("mouseup", function(event) {nodeUp(this); }, false);
         //rect1.addEventListener("mouseover", function(event) {this.setAttributeNS(null, 'fillColor', '#ffcc00' ); }, false);
         //rect1.addEventListener("mouseout", function(event) {this.setAttributeNS(null, 'fillColor', '#00cc00' ); }, false);
         

         //rect1.addEventListener("mouseout", function(event) {this.setAttributeNS(null, 'stroke-width', 0 ); }, false);

        svg.appendChild(rect1);                                    
         
      }                     
      var info='';
       
         if(controlNodeNum==0){info='prev Control'}  
         if(controlNodeNum==1){info='next Control'}  
         if(controlNodeNum==2){info='points node'}   
        // $('someinfo').value=numpoints+ ' '+info+':'+ chain;
       // $('someinfo').value='Crtl+Arrow to move';
    //return chain;                                          
    

      //this.svgRoot.appendChild(svg);   
    
    return svg;  
        
};
SVGRenderer.prototype.showTracker = function(shape,pathsEdit) {  

  var box = shape.getBBox();
 var matrix = shape.getScreenCTM();
  var trshape= shape.getAttributeNS(null, 'transform');  
  var shap=1; 
  var T = shape.getCTM();
  //a,b,c,d,e,f

    
 
 
    //var thisTransform = {  sx: s[0], r: shape.vRotate, t: shape.vTranslate };
    //if (currentTransform != null) alert(currentTransform.t);
 
  if (shape.tagName == 'rect') { 
     
//      $('option_rect_rot').value= T.b* (Math.PI * 2 / 360); 
//      $('option_rect_trx').value= box.x;  
//      $('option_rect_try').value= box.y;
//      $('option_rect_sclx').value= box.width;  
//      $('option_rect_scly').value= box.height;

  }  

  if (shape.tagName == 'image'){
//     $('option_img_trx').value= box.x; 
//     $('option_img_try').value= box.y;
//     $('option_img_sclx').value= box.width;  
//     $('option_img_scly').value= box.height;
//     $('option_img_rot').value= T.b* (Math.PI * 2 / 360);
  }
  if (shape.tagName == 'text'){
   /* f$('option_text_trx').value= box.x; 
    $('option_text_try').value= box.y;
    $('option_text_sclx').value= box.width;  
    $('option_text_scly').value= box.height;
    $('option_text_rot').value= T.b* (Math.PI * 2 / 360);
   */
  }
  if (shape.tagName == 'line'){ 
    /*
    $('option_line_trx').value= box.x;  
    $('option_line_try').value= box.y;
    */
  }   
  if (shape.tagName == 'ellipse'){  
    /*$('option_ellipse_trx').value= putx;  
    $('option_ellipse_try').value= puty;
    $('option_ellipse_sclx').value= box.width;  
    $('option_ellipse_scly').value= box.height;
    $('option_ellipse_rot').value= T.b* (Math.PI * 2 / 360);
    */
  }
  
  
  
 /* if (shape.getAttributeNS(null, 'transform') ) { 
        
        
        shap=2; }else{
  }*/ 
  var tracker = document.getElementById('tracker');
  if (tracker) {
    this.remove(tracker);
  }

  var svgNamespace = 'http://www.w3.org/2000/svg';
  
     tracker = document.createElementNS(svgNamespace, 'g');    
      tracker.setAttributeNS(null, 'id', 'tracker'); 
      
    var controlPoints=null;
    if (shape.tagName == 'path') { shap=2; 
    
    /* $('option_path_trx').value= box.x;  
     $('option_path_try').value= box.y;
     $('option_path_sclx').value= T.a;   
     $('option_path_scly').value= T.d; 
     $('option_path_rot').value= T.b* (Math.PI * 2 / 360);
     */                                        
     var path=shape.getAttributeNS(null, 'd');
//       $('control_codebase').value=path;  
       
       //controlPoints=this.showNodesCurve(path,0);
       //controlPoints=this.showNodesCurve(path,1); 
       controlPoints=this.showNodesCurve(path,2);
       
           
        /*   controlPoints=this.showNodesCurve(path,1); 
   
           tracker.appendChild(controlPoints);     
           
           controlPoints=this.showNodesCurve(path,0); 
   
           tracker.appendChild(controlPoints); 
        */   
   }        
      
     var svg = this.container.ownerDocument.createElementNS(svgNamespace, 'g'); 
      svg.setAttributeNS(null, 'id', 'transformSquares'); 
   
          
       //var rect = document.createElementNS(svgNamespace, 'rect');   
       var border = document.createElementNS(svgNamespace, 'path');  
       
       var trshape='translate (0,0) rotate(0) translate(0,0) '; 
       var trshape_split=trshape.split(') ');    
       
      // get_between (trshape, s1, s2) ;
     if(shape.getAttributeNS(null, 'transform')){ 
         var trshape=shape.getAttributeNS(null, 'transform') ;   
         //var spl=trshape.replace(', ',' ');  
         //var spl1=spl.replace(')',' ');    
         var trshape_split=trshape.split(') '); 
         

    }
                                         
  var corners = [];
  var point = createPoint(box.x, box.y, box.width, box.height);
 //point = {x:box.x, y:box.y, width: box.width, height:box.height};
//point = createPoint(box.x, box.y, box.width, box.height);    
  //1
  corners.push( createPoint(box.x + box.width, box.y, box.width, box.height) );
  point.x = box.x + box.width;
  point.y = box.y;
  //2
  corners.push( createPoint(box.x + box.width, box.y + box.height, box.width, box.height) );
  point.x = box.x + box.width;
  point.y = box.y + box.height;
  //3
  //corners.push( point.matrixTransform(matrix) );
  corners.push( createPoint(box.x , box.y + box.height, box.width, box.height) );
  point.x = box.x;
  point.y = box.y + box.height;
  //4
  corners.push( createPoint(box.x + box.width, box.y, box.width, box.height) );   
  
  var max = createPoint(corners[0].x, corners[0].y);
  var min = createPoint(corners[0].x, corners[0].y);

  // identify the new corner coordinates of the
  // fully transformed bounding box
  for (var i = 1; i < corners.length; i++) {
    var x = corners[i].x;
    var y = corners[i].y;
    if (x < min.x) {
      min.x = x;
    }
    else if (x > max.x) {
      max.x = x;
    }
    if (y < min.y) {
      min.y = y;
    }
    else if (y > max.y) {
      max.y = y;
    }
  }
  
  // return the bounding box as an SVGRect object
  //rect = document.createElementNS(svgNamespace, 'rect');
   //rect.setAttributeNS(null, 'x', min.x-10);
    //rect.setAttributeNS(null, 'y', min.y-10);   
    
    //rect.setAttributeNS(null, 'width', max.x - min.x+20);
    //rect.setAttributeNS(null, 'height', max.y - min.y+20);   
     
     border.setAttributeNS(null, 'd', "M"+(min.x-10)+","+ (min.y-10)+' h'+(box.width+20)+','+(0)+' v'+(0)+','+(box.height+20)+' h'+(-box.width-20)+','+(0)+' z M'+(box.x+box.width+10)+","+ (box.y+(box.height/2)+' h'+(25)+',0 '));   
     
     
     border.setAttributeNS(null, 'fill', 'none');
     border.setAttributeNS(null, 'stroke', '#cccccc');
     border.setAttributeNS(null, 'stroke-width', '1'); 
       
// createRect(min.x, min.y, max.x - min.x, max.y - min.y);

      var circle1 = document.createElementNS(svgNamespace, 'ellipse');  
      circle1.setAttributeNS(null, 'cx', (box.x + box.width+40) + 'px');
    circle1.setAttributeNS(null, 'cy', (box.y + box.height / 2) + 'px');
    circle1.setAttributeNS(null, 'rx', (5) + 'px');
    circle1.setAttributeNS(null, 'ry', (5) + 'px');   
   circle1.setAttributeNS(null, 'fill', '#ffffff');
  circle1.setAttributeNS(null, 'stroke', 'green');
  circle1.setAttributeNS(null, 'stroke-width', '1');   

      var circleCenter = document.createElementNS(svgNamespace, 'ellipse');  
      circleCenter.setAttributeNS(null, 'cx', (box.x + (box.width/2)) + 'px');
    circleCenter.setAttributeNS(null, 'cy', (box.y + (box.height /2)) + 'px');
    circleCenter.setAttributeNS(null, 'rx', (10) + 'px');
    circleCenter.setAttributeNS(null, 'ry', (10) + 'px');   
   circleCenter.setAttributeNS(null, 'fill', '#ffffff');
  circleCenter.setAttributeNS(null, 'stroke', 'green');
  circleCenter.setAttributeNS(null, 'stroke-width', '1');   

     var rect1 = document.createElementNS(svgNamespace, 'rect');  
  rect1.setAttributeNS(null, 'width', 10);
  rect1.setAttributeNS(null, 'height', 10);
  rect1.setAttributeNS(null, 'fill', '#ffffff');
  rect1.setAttributeNS(null, 'stroke', 'green');
  rect1.setAttributeNS(null, 'stroke-width', '1');  

  var rect2 = document.createElementNS(svgNamespace, 'rect');  
  rect2.setAttributeNS(null, 'width', 10);
  rect2.setAttributeNS(null, 'height', 10);
  rect2.setAttributeNS(null, 'fill', '#ffffff');
  rect2.setAttributeNS(null, 'stroke', 'green');
  rect2.setAttributeNS(null, 'stroke-width', '1');  

  var rect3 = document.createElementNS(svgNamespace, 'rect');  
  rect3.setAttributeNS(null, 'width', 10);
  rect3.setAttributeNS(null, 'height', 10);
  rect3.setAttributeNS(null, 'fill', '#ffffff');
  rect3.setAttributeNS(null, 'stroke', 'green');
  rect3.setAttributeNS(null, 'stroke-width', '1'); 
  
  var rect4 = document.createElementNS(svgNamespace, 'rect');  
  rect4.setAttributeNS(null, 'width', 10);
  rect4.setAttributeNS(null, 'height', 10);
  rect4.setAttributeNS(null, 'fill', '#ffffff');
  rect4.setAttributeNS(null, 'stroke', 'green');
  rect4.setAttributeNS(null, 'stroke-width', '1');  
 
  var rectmid12 = document.createElementNS(svgNamespace, 'rect');  
  rectmid12.setAttributeNS(null, 'width', 10);
  rectmid12.setAttributeNS(null, 'height', 10);
  rectmid12.setAttributeNS(null, 'fill', '#ffffff');
  rectmid12.setAttributeNS(null, 'stroke', 'green');
  rectmid12.setAttributeNS(null, 'stroke-width', '1');  

  var rectmid23 = document.createElementNS(svgNamespace, 'rect');  
  rectmid23.setAttributeNS(null, 'width', 10);
  rectmid23.setAttributeNS(null, 'height', 10);
  rectmid23.setAttributeNS(null, 'fill', '#ffffff');
  rectmid23.setAttributeNS(null, 'stroke', 'green');
  rectmid23.setAttributeNS(null, 'stroke-width', '1');  

  var rectmid34 = document.createElementNS(svgNamespace, 'rect');  
  rectmid34.setAttributeNS(null, 'width', 10);
  rectmid34.setAttributeNS(null, 'height', 10);
  rectmid34.setAttributeNS(null, 'fill', '#ffffff');
  rectmid34.setAttributeNS(null, 'stroke', 'green');
  rectmid34.setAttributeNS(null, 'stroke-width', '1'); 
  
  var rectmid41 = document.createElementNS(svgNamespace, 'rect');  
  rectmid41.setAttributeNS(null, 'width', 10);
  rectmid41.setAttributeNS(null, 'height', 10);
  rectmid41.setAttributeNS(null, 'fill', '#ffffff');
  rectmid41.setAttributeNS(null, 'stroke', 'green');
  rectmid41.setAttributeNS(null, 'stroke-width', '1');   
   // rect.setAttributeNS(null, 'x', box.x - 10);
   // rect.setAttributeNS(null, 'y', box.y - 10);    
    
    rect1.setAttributeNS(null, 'x', box.x - 10-5);
    rect1.setAttributeNS(null, 'y', box.y - 10-5);  
   
    
    rect2.setAttributeNS(null, 'x', box.x + box.width +5 );
    rect2.setAttributeNS(null, 'y', box.y -10 -5);   

    rect3.setAttributeNS(null, 'x', box.x + box.width+5 );
    rect3.setAttributeNS(null, 'y', box.y + box.height+5);
                                                       
    rect4.setAttributeNS(null, 'x', box.x -10-5 );
    rect4.setAttributeNS(null, 'y', box.y + box.height+5);    

    

    rectmid12.setAttributeNS(null, 'x', box.x + (box.width/2) -5);
    rectmid12.setAttributeNS(null, 'y', box.y - 10-5);  

    rectmid23.setAttributeNS(null, 'x', box.x + box.width +5 );
    rectmid23.setAttributeNS(null, 'y', box.y + (box.height/2)-5);   
    
    rectmid34.setAttributeNS(null, 'x', box.x + (box.width/2)-5 );
    rectmid34.setAttributeNS(null, 'y', box.y + box.height+5);
                                                           
    rectmid41.setAttributeNS(null, 'x', box.x -10-5 );
    rectmid41.setAttributeNS(null, 'y', box.y + (box.height/2)-5);
     
    svg.appendChild(border); 
    //tracker.appendChild(getScreenBBox (shape));
    //currentTranslate
    //currentScale
   // shape.setAttributeNS(null,'transform', "translate("+(box.x+(box.width/2))+","+(box.y+(box.height/2))+") rotate("+rotatexxx+") translate("+(-box.x-(box.width/2))+","+(-box.y-(box.height/2))+") ");

   //var trshape=shape.getAttributeNS(null, 'transform') ; 
  //----tracker.setAttributeNS(null,'transform', "translate("+(box.x+(box.width/2))+","+(box.y+(box.height/2))+") "+trshape_split[1]+") translate("+(-box.x-(box.width/2))+","+(-box.y-(box.height/2))+") ");

    
    
  //}  
   // tracker.appendChild(getScreenBBox (shape));
     var colorin="#ff0000";
      var colorout="#ffffff" 
      
        circle1.addEventListener("mouseover", function(event) {circle1.setAttributeNS(null, 'cursor', 's-resize');  circle1.setAttributeNS(null, 'fill', colorin ); typeTransform='Rotate'; scaleType='nw'; }, false);
     circle1.addEventListener("mouseout", function(event) {circle1.setAttributeNS(null, 'cursor', 'default');  circle1.setAttributeNS(null, 'fill', colorout ); typeTransform='Rotate'; }, false); //typeTransform='rotate'
     circleCenter.addEventListener("mouseover", function(event) {circleCenter.setAttributeNS(null, 'cursor', 'move');  circleCenter.setAttributeNS(null, 'fill', colorin ); typeTransform='spÃ¯Â¿Â½nCenter'; scaleType='nw'; }, false);
     circleCenter.addEventListener("mouseout", function(event) {circleCenter.setAttributeNS(null, 'cursor', 'default');  circleCenter.setAttributeNS(null, 'fill', colorout ); typeTransform=''; }, false); //typeTransform='rotate'
 
      
     //rect1.addEventListener("mouseover", cursore1in, false);    
     rect1.addEventListener("mouseover", function(event) {rect1.setAttributeNS(null, 'cursor', 'nw-resize');  rect1.setAttributeNS(null, 'fill', colorin ); typeTransform='Scale'; scaleType='nw';}, false);
     rect1.addEventListener("mouseout", function(event) {rect1.setAttributeNS(null, 'cursor', 'default');  rect1.setAttributeNS(null, 'fill', colorout ); typeTransform='Scale'; }, false); //typeTransform='rotate'
     //rect1.addEventListener("click", function(event) { rect1.setAttributeNS(null, 'fill', '#00ff00' ); typeTransform='Scale'; }, false);
    
     rect2.addEventListener("mouseover", function(event) {rect2.setAttributeNS(null, 'cursor', 'ne-resize');  rect2.setAttributeNS(null, 'fill', colorin ); typeTransform='Scale'; scaleType='ne';}, false);  
     rect2.addEventListener("mouseout", function(event) {rect2.setAttributeNS(null, 'cursor', 'default');  rect2.setAttributeNS(null, 'fill', colorout ); typeTransform='Scale'; }, false);
      
     rect3.addEventListener("mouseover", function(event) {rect3.setAttributeNS(null, 'cursor', 'se-resize');  rect3.setAttributeNS(null, 'fill', colorin ); typeTransform='Scale'; scaleType='se';}, false);  
     rect3.addEventListener("mouseout", function(event) {rect3.setAttributeNS(null, 'cursor', 'default');  rect3.setAttributeNS(null, 'fill', colorout ); typeTransform='Scale'; }, false);
     
     rect4.addEventListener("mouseover", function(event) {rect4.setAttributeNS(null, 'cursor', 'sw-resize');  rect4.setAttributeNS(null, 'fill', colorin ); typeTransform='Scale'; scaleType='sw';}, false);  
     rect4.addEventListener("mouseout", function(event) {rect4.setAttributeNS(null, 'cursor', 'default');  rect4.setAttributeNS(null, 'fill', colorout ); typeTransform='Scale'; }, false);
                                                    
     rectmid12.addEventListener("mouseover", function(event) {rectmid12.setAttributeNS(null, 'cursor', 'n-resize');  rectmid12.setAttributeNS(null, 'fill', colorin ); typeTransform='Scale'; scaleType='n';}, false);  
     rectmid12.addEventListener("mouseout", function(event) {rectmid12.setAttributeNS(null, 'cursor', 'default');  rectmid12.setAttributeNS(null, 'fill', colorout ); typeTransform='Scale'; }, false); 

     rectmid23.addEventListener("mouseover", function(event) {rectmid23.setAttributeNS(null, 'cursor', 'e-resize');  rectmid23.setAttributeNS(null, 'fill', colorin ); typeTransform='Scale'; scaleType='e';}, false);  
     rectmid23.addEventListener("mouseout", function(event) {rectmid23.setAttributeNS(null, 'cursor', 'default');  rectmid23.setAttributeNS(null, 'fill', colorout ); typeTransform='Scale'; }, false); 
     
     rectmid34.addEventListener("mouseover", function(event) {rectmid34.setAttributeNS(null, 'cursor', 's-resize');  rectmid34.setAttributeNS(null, 'fill', colorin ); typeTransform='Scale'; scaleType='s';}, false);  
     rectmid34.addEventListener("mouseout", function(event) {rectmid34.setAttributeNS(null, 'cursor', 'default');  rectmid34.setAttributeNS(null, 'fill', colorout ); typeTransform='Scale'; }, false); 

     rectmid41.addEventListener("mouseover", function(event) {rectmid41.setAttributeNS(null, 'cursor', 'w-resize');  rectmid41.setAttributeNS(null, 'fill', colorin ); typeTransform='Scale'; scaleType='w'; }, false);  
     rectmid41.addEventListener("mouseout", function(event) {rectmid41.setAttributeNS(null, 'cursor', 'default');  rectmid41.setAttributeNS(null, 'fill', colorout ); typeTransform='Scale'; }, false); 
     
     //////////
     svg.setAttributeNS(null, 'transform',trshape); 
  
    svg.appendChild(circle1);    
    //tracker.appendChild(circleCenter);  
   if (shape.tagName == 'text'){   
    svg.appendChild(rect1); 
    svg.appendChild(rect2);   
    svg.appendChild(rect3); 
    svg.appendChild(rect4);  
  }else{
    svg.appendChild(rect1); 
    svg.appendChild(rect2);   
    svg.appendChild(rect3); 
    svg.appendChild(rect4);  
    svg.appendChild(rectmid12);  
    svg.appendChild(rectmid23);
    svg.appendChild(rectmid34);
    svg.appendChild(rectmid41);                                    

  }  
    if(pathsEdit)
     {    
        controlPoints.setAttributeNS(null, 'transform',trshape); 
        tracker.appendChild(controlPoints);      
     }else{   
        tracker.appendChild(svg); 
     }   
  this.svgRoot.appendChild(tracker);  
      
}


SVGRenderer.prototype.getMarkup = function() { 
       
  return this.container.innerHTML;
}   


/////////////////////////////////
var rotatexxx=0; 
 
var scaleType=''; 
var xrot=0;
var yrot=0;  

var point = {x:0, y:0, width: 0, height:0};

function createPoint (x, y, width, height) {
    //var point = {x:34, y:22, width: 22, height:23};
    //point.x = x;
    //point.y = y;   
    point = {x:x, y:y, width: width, height:height};
    return point;
  }

///////////////////////////////

SVGRenderer.prototype.restruct= function(shape)
{
 //alert('end');       
 //forceRedraw(); 
//clearWorkspace();  
//document.getElementById('richdraw').style.cursor='default';    
};        



SVGRenderer.prototype.transform = function() {
    //document.forms[0].code.value='Im tranforming';
};

SVGRenderer.prototype.scaleShape = function(shape,previus, toX, toY) {

	 var box = shape.getBBox();  
	 var prevbox=previus.getBBox();
	var centerx= box.x+(box.width/2);
	var centery= box.y+(box.height/2); 
	var coord=this.editor.inputxy;
	toX=parseFloat(coord[0]);
	toY=parseFloat(coord[1]); 
	var d2p_center=dist2p(centerx,centery,toX,toY);       

	var d2p=dist2p(box.x,box.y,toX,toY);

	var shareScale=box.width/d2p;

	var trans_ShareScale='';
	var tx, ty, tw, yh;
	
	

	if(scaleType.length==1){
		if(scaleType== 'w')
		 {
			trans_ShareScale=shareScale+",1";  
			tx=toX; 
			ty=prevbox.y; 
			var dist=prevbox.x-toX;
			var w=dist+prevbox.width;
			if(w<1){w=1;}
			tw=w;
			th=prevbox.height;
			//document.forms[0].code.value=box.x+' '+toX+' '+dist+''; 
		 }        
		if(scaleType== 'e')
		 {
		        trans_ShareScale=shareScale+",1"; 
			tx=prevbox.x; 
			ty=prevbox.y; 
			var dist=toX-(prevbox.x+prevbox.width); //dist2p(toX,b,c,d);
			var w=dist+prevbox.width;
			if(w<1){w=1;}
			tw=w;
			th=prevbox.height;
 
		 }        
		if(scaleType== 'n')
		 {
			trans_ShareScale="1,"+shareScale; 
			
			tx=prevbox.x; 
			ty=toY; 
			var dist=prevbox.y-toY;
			var h=dist+prevbox.height;
			if(h<1){h=1;}
			tw=prevbox.width;
			th=h;

		 }
                if( scaleType== 's')
                 {
                        trans_ShareScale="1,"+shareScale;  

			tx=prevbox.x; 
			ty=prevbox.y; 
			var dist=toY-(prevbox.y+prevbox.height); //dist2p(toX,b,c,d);
			var h=dist+prevbox.height;
			if(h<1){h=1;}
			tw=prevbox.width;
			th=h;

	         }
        }
	if(scaleType.length==2){
		if(scaleType== 'nw'){
			trans_ShareScale=shareScale+","+shareScale; 
          
      			//var angle_diagonal=getAngle(prevbox.width,prevbox.height);
      			  var angle_diagonal=ang2v(prevbox.x,prevbox.y,prevbox.x+prevbox.width,prevbox.y+prevbox.height)
            
                        var ax= prevbox.x;
                        var ay= prevbox.y;
                        var bx= prevbox.x+prevbox.width; 
                        var by= prevbox.y+prevbox.height; 
                        
                        var cx= toX;
                        var cy= toY;
                        var dx= toX+10*Math.cos(angle_diagonal+(Math.PI/2)); 
                        var dy= toY+10*Math.sin(angle_diagonal+(Math.PI/2));  
                        
                        var section_a=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);   
                 this.editor.log(angle_diagonal* 180 / Math.PI);       
                    
                var tx= section_a[1];
                var ty= section_a[2];
                
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= 0;
                        var by= section_a[2] ; 
                        
                        var cx=prevbox.x+prevbox.width; 
                        var cy= prevbox.y;

                        var dx= prevbox.x+prevbox.width;  
                        var dy= 0;
                        
                      
                var section_b=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);

                var distx=dist2p(section_a[1],section_a[2],section_b[1],section_b[2]);         

              
                
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= section_a[1] 
                        var by= 0; 
                        
                        var cx= prevbox.x; 
                        var cy= prevbox.y+prevbox.height; 

                        var dx= 0; 
                        var dy= prevbox.y+prevbox.height;
                        
                      
                var section_c=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
                var disty=dist2p(section_a[1],section_a[2],section_c[1],section_c[2]);         
                
                

                    
                        if(distx<1){distx=1;}    
			
         		
			if(disty<1){disty=1;}
                        //document.forms[0].code.value=distx+' '+disty;
			tw=distx;
			th=disty;

			
		}                  
		
	//////////////////// SE
		
           if( scaleType== 'se'){
			trans_ShareScale=shareScale+","+shareScale;   
			
	          
      			//var angle_diagonal=getAngle(prevbox.width,prevbox.height);
       			var angle_diagonal=ang2v(prevbox.x,prevbox.y,prevbox.x+prevbox.width,prevbox.y+prevbox.height)
		
			
			
                        var ax= prevbox.x;
                        var ay= prevbox.y;
                        var bx= prevbox.x+prevbox.width; 
                        var by= prevbox.y+prevbox.height; 
                        
                        var cx= toX;
                        var cy= toY;   
                        var dx= toX+10*Math.cos(angle_diagonal+(Math.PI/2)); 
                        var dy= toY+10*Math.sin(angle_diagonal+(Math.PI/2)); 
      
                var section_a=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);   
                
                                         
                 var svgNamespace = 'http://www.w3.org/2000/svg';  
                 var tracker = document.getElementById('tracker');

                //////////
                var tx= prevbox.x;
                var ty= prevbox.y;
                
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= 0;
                        var by= section_a[2] ; 
                        
                        var cx=prevbox.x; 
                        var cy= prevbox.y;

                        var dx= prevbox.x;  
                        var dy= 0;
                        
                      
                var section_b=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
               
               /////////////////
               
               
                var distx=dist2p(section_a[1],section_a[2],section_b[1],section_b[2]);         

             
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= section_a[1] 
                        var by= 0; 
                        
                        var cx= prevbox.x; 
                        var cy= prevbox.y; 

                        var dx=0;
                        var dy= prevbox.y;
                        
                      
                var section_c=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
               
               ///////////////
               
                var disty=dist2p(section_a[1],section_a[2],section_c[1],section_c[2]);         
                
   
                    
                        if(distx<1){distx=1;}    
			
         		
			if(disty<1){disty=1;}
                        
			tw=distx;
			th=disty;

			
		}

		if(scaleType== 'ne'){  
		        
			trans_ShareScale=shareScale+","+shareScale;   
			
	                var angle_diagonal=ang2v(prevbox.x,prevbox.y+prevbox.height,prevbox.x+prevbox.width,prevbox.y)
      			//var angle_diagonal=getAngle(prevbox.width,prevbox.height);
 		
			
				
			
                        var ax= prevbox.x;
                        var ay= prevbox.y+prevbox.height;
                        var bx= prevbox.x+prevbox.width; 
                        var by= prevbox.y;
                       
                        var cx= toX;
                        var cy= toY;   
                        var dx= toX+10*Math.cos(angle_diagonal+(Math.PI/2)); 
                        var dy= toY+10*Math.sin(angle_diagonal+(Math.PI/2)); 


                      this.editor.log(angle_diagonal);

      
                var section_a=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);   
                
                                         
                 var svgNamespace = 'http://www.w3.org/2000/svg';  
                 var tracker = document.getElementById('tracker');

                //////////
                var tx= prevbox.x;
                var ty= section_a[2];
                
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= 0;
                        var by= section_a[2] ; 
                        
                        var cx=prevbox.x; 
                        var cy= prevbox.y;

                        var dx= prevbox.x;  
                        var dy= 0;
                        
                      
                var section_b=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
               
               /////////////////
               
               
                var distx=dist2p(section_a[1],section_a[2],section_b[1],section_b[2]);         

             
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= section_a[1]; 
                        var by= 0; 
                        
                        var cx= prevbox.x; 
                        var cy= prevbox.y+prevbox.height; 

                        var dx=0;
                        var dy= prevbox.y+prevbox.height;
                        
                      
                var section_c=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
               
               ///////////////
               
                var disty=dist2p(section_a[1],section_a[2],section_c[1],section_c[2]);         
                

                    
                        if(distx<1){distx=1;}    
			
         		
			if(disty<1){disty=1;}
                        //document.forms[0].code.value=distx+' '+disty;
			tw=distx;
			th=disty;
			
			
			
			
			
		}
		if(scaleType== 'sw'){
			trans_ShareScale=shareScale+","+shareScale;  
			
			
				
			
	                var angle_diagonal=ang2v(prevbox.x,prevbox.y+prevbox.height,prevbox.x+prevbox.width,prevbox.y)
      			//var angle_diagonal=getAngle(prevbox.width,prevbox.height);
 		
			
				
			
                        var ax= prevbox.x;
                        var ay= prevbox.y+prevbox.height;
                        var bx= prevbox.x+prevbox.width; 
                        var by= prevbox.y;
                       
                        var cx= toX;
                        var cy= toY;   
                        var dx= toX+10*Math.cos(angle_diagonal+(Math.PI/2)); 
                        var dy= toY+10*Math.sin(angle_diagonal+(Math.PI/2)); 


                      this.editor.log(angle_diagonal);

      
                var section_a=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);   
                
                                         
                 var svgNamespace = 'http://www.w3.org/2000/svg';  
                 var tracker = document.getElementById('tracker');

                //////////
                var tx= section_a[1];
                var ty= prevbox.y;
                
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= 0;
                        var by= section_a[2] ; 
                        
                        var cx=prevbox.x+prevbox.width; 
                        var cy= prevbox.y+prevbox.height;

                        var dx= prevbox.x+prevbox.width;  
                        var dy= 0;
                        
                      
                var section_b=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
                var distx=dist2p(section_a[1],section_a[2],section_b[1],section_b[2]);         

               /////////////////             
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= section_a[1];
                        var by= 0; 
                          
                        var cx= prevbox.x; 
                        var cy= prevbox.y; 

                        var dx=0;
                        var dy= prevbox.y;
                        
                      
                var section_c=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
                  var disty=dist2p(section_a[1],section_a[2],section_c[1],section_c[2]);         
              ///////////////
                
   
                    
                        if(distx<1){distx=1;}    
			
         		
			if(disty<1){disty=1;}
                        //document.forms[0].code.value=distx+' '+disty;
			tw=distx;
			th=disty;
			
		}

	}  



 if(shape.tagName == 'rect')
  { 
    //alert(data[0]);     
   shape.setAttributeNS(null,'x',tx);
    shape.setAttributeNS(null,'y',ty);   
    shape.setAttributeNS(null, 'width', tw);     
    shape.setAttributeNS(null, 'height', th); 
    
   //shape.nodparseFloatue=data;
  }
   else 
 if(shape.tagName == 'text')
  { 
    
    var tsize=shape.getAttributeNS(null, 'font-size') ;
    tsize=parseFloat(tsize);
    //shape.setAttributeNS(null, 'x', tx + 'px');
    //shape.setAttributeNS(null, 'y', ty + 'px'); 
    //var mysize=box.height+1 ;
    var mysize=parseInt(Math.round(th));
    
    if(scaleType== 'ne'){ shape.setAttributeNS(null, 'font-size',tsize+1);}  
      //shape.setAttributeNS(null, 'font-size', mysize);  
      
   
   /*
    shape.setAttributeNS(null,'x',tx);
    shape.setAttributeNS(null,'y',ty);   
    shape.setAttributeNS(null, 'width', tw);     
    shape.setAttributeNS(null, 'height', th); 
    
    //previus.setAttributeNS(null,'transform', "scale("+trans_ShareScale+")");
    shape.setAttributeNS(null, 'x', tx + 'px');
    shape.setAttributeNS(null, 'y', ty + 'px');

    shape.setAttributeNS(null, 'textLength', parseInt(Math.round(tw)));    
    
     */
  } 
   else 
 if(shape.tagName == 'ellipse')
  {
    //shape.getAttributeNS(null, 'transform)
    shape.setAttributeNS(null, 'cx', (tx + (box.width / 2)) + 'px');
    shape.setAttributeNS(null, 'cy', (ty + (box.height / 2)) + 'px');
    shape.setAttributeNS(null, 'rx', (tw / 2) + 'px');
    shape.setAttributeNS(null, 'ry', (th / 2) + 'px');   
 
        
  }
   else 
 if(shape.tagName == 'line')
  { 
    shape.setAttributeNS(null, 'x1', tx + 'px');
    shape.setAttributeNS(null, 'y1', ty + 'px');
    shape.setAttributeNS(null, 'x2', tx + tw + 'px');
    shape.setAttributeNS(null, 'y2', ty + th + 'px');  
         
  }
   else
 if (shape.tagName == 'polyline') 
  {
   
  }
   else 
 if (shape.tagName == 'image') 
  {   
    shape.setAttributeNS(null,'x',tx);
    shape.setAttributeNS(null,'y',ty);   
    shape.setAttributeNS(null, 'width', tw);     
    shape.setAttributeNS(null, 'height', th); 
      
  }
   else 
 if (shape.tagName == 'path')
  {     
     // var xscale=  box.width/tw;
     // var yscale=  box.height/th;  
      var xscale=  tw/box.width;
      var yscale=  th/box.height;  
      var xinc=xscale;//dist*angx;
      var yinc=yscale/ty;//dist*angy;   

   if(scaleType== 'n')
    {
       tx=box.x+(box.width/2);
       ty=box.y+box.height; 
       var xinc=1;
       var yinc=box.y/toY;//dist*angy;   

    } 
   if(scaleType== 's')
    {
       tx=box.x+(box.width/2);
       ty=box.y; 
       var xinc=1;
       var yinc=toY/(box.y+box.height);//dist*angy;   
    }    
   if(scaleType== 'e')
    {
       tx=box.x;
       ty=box.y+(box.height/2);  
       var xinc=toX/(box.x+box.width);
       var yinc=1;   

    }         
   if(scaleType== 'w')
    {
       tx=box.x+box.width;
       ty=box.y+(box.height/2); 
       var xinc=box.x/toX;
       var yinc=1;   

    }
   if(scaleType== 'ne')
    {
       tx=box.x;
       ty=box.y+box.height; 
       var xinc=toX/(box.x+box.width);
       var yinc=xinc;   
    }  
  if(scaleType== 'nw')
    {
       tx=box.x+box.width;
       ty=box.y+box.height; 
       var xinc=box.x/toX;
       var yinc=xinc;   
    } 
   if(scaleType== 'se')
    {
       tx=box.x;
       ty=box.y; 
       var xinc=toX/(box.x+box.width);
       var yinc=xinc;   
    }    
   if(scaleType== 'sw')
    {
       tx=(box.x+box.width);
       ty=box.y; 
       var xinc=box.x/toX;
       var yinc=xinc;   
    }        
      if(xinc==0){ xinc= 0.0000001;}
      if(yinc==0){ yinc= 0.0000001; }
      var prevpath=previus.getAttributeNS(null, 'd');
     var path=shape.getAttributeNS(null, 'd');
////////////


      //xshe=left;
      //yshe=top;
       
 path=path.replace(/, /g, ','); 
 path=path.replace(/ ,/g, ',');
 var ps =path.split(" ")
 var pcc = "";
 var point =ps[0].split(","); 


 var num0= parseFloat(point[0].substring(1));
 var num1= parseFloat(point[1]);     
 

 var ang= ang2v(box.x,box.y,tx,ty) ;
 var angle = Math.round((ang/Math.PI* 2)* 360);
 var angx = Math.cos(ang); 
 var angy = Math.sin(ang);          
 var dist= dist2p(tx,ty,box.x,box.y);
 //var xinc=xscale;//dist*angx;
 //var yinc=yscale;//dist*angy;   
    var re = /^[-]?\d*\.?\d*$/; 
    var axis = $V([tx,ty]);
 for(var i = 0; i < ps.length; i++)
  { 
   if(ps[i].indexOf(',')>0){  
     
      var point =ps[i].split(","); 
       var char1=point[0].substring(0,1); 
       if(char1=='A' || char1=='a'){isArc=true; contArc=0;}
       if(isArc==true){contArc++}
       if(contArc==4){contArc=0; isArc=false}
       
       //if (isNaN(valnum)) 
      if (!char1.match(re))        
       { 
           var num0= parseFloat(point[0].substring(1));
           var text=char1;
       }else{ 
         if(isArc==true && contArc==2  )
          {
            var num0= point[0];
          }else{  
            var num0= parseFloat(point[0]);
          }  
         var text='';

       }
 
       
       if(isArc==true && contArc==2)
        {   
           point[1]= point[1].toString() ;
        }
        else
        {    
         
          //num0*=xinc;    
          point[1]= parseFloat(point[1]);
          //point[1]*=yinc;
          var pointIni=$V([num0,point[1],1]);
          var matrT = $M([[1,0,-tx],[0,1,-ty],[0,0,1]]);
          var matrS = $M([[xinc,0,0],[0,yinc,0],[0,0,1]]); 
          var matrR = $M([[1,0,tx],[0,1,ty],[0,0,1]]);
          var matr1= matrT.x(pointIni);  
          var matr2= matrS.x(matr1);
          //var pointR=pointIni.Random(1) 
          //var pointR=pointIni.rotate(Math.PI/180,axis);
          //var pointRc=pointIni.cross(axis); 
          //var pointR=matr2;
          var pointR=matrR.x(matr2);  
          num0=pointR.elements[0];
           point[1]=pointR.elements[1];
//           $('code').value=pointIni.elements[0]+','+pointR.elements[1]+' ';
        }  
       var cx=num0; 
        var cy=point[1];   
        pcc+=text+cx+','+cy+' ';
        //pcc+=text+cx+','+cy+' '; 
       
   }else{
      pcc+=ps[i]+' ';
   }
  }
  
  shape.setAttributeNS(null,'d', pcc);



//////////////
/*
 path=path.replace(/, /g, ','); 
 path=path.replace(/ ,/g, ',');
 var ps =path.split(" ")
 var pcc = "";

 var xinc=tx-prevbox.x;
 var yinc=ty-prevbox.y;
  
    var re = /^[-]?\d*\.?\d*$/;
 for(var i = 0; i < ps.length; i++)
  { 
   if(ps[i].indexOf(',')>0){  
     
      var point =ps[i].split(","); 
       var char1=point[0].substring(0,1);
       point[1]= parseFloat(point[1]); 
       
       // var valnum =char1.charAt(0); 
       //if (isNaN(valnum))
       if (!char1.match(re)) 
        
       {
         var num0= parseFloat(point[0].substring(1));
         var text=char1;
       }else{
         var num0= parseFloat(point[0]);
         var text='';

       }
       //num0+=dist*angx;
       //point[1]+=dist*angy;
         num0*=xscale;
        point[1]*=yscale;   
        
      // num0+=xinc;
      // point[1]+=yinc;
       
      
        
        var cx=num0;
        var cy=point[1]; 
        pcc+=text+cx+','+cy+' ';
   }else{
      pcc+=ps[i]+' ';
   }
  }


   
    
  
   // $('code').value=dist+' '+ ang+' '+'__'+x+'= '+left+'/ '+y+'= ' +top+'';
    
       //shape.setAttributeNS(null,'transform', "rotate("+left+")");
       
       // shape.setAttributeNS(null,'transform', "translate("+trax+","+tray+") rotate("+0+") scale(1,1)");
         shape.setAttributeNS(null,'d', pcc);

    
    
    
    
    
    
       //document.forms[0].code.value='';
       //shape.setAttributeNS(null,'transform', "scale("+trans_ShareScale+")"); 
 */      

  }  
   	                             







	
	
	
	
	
//$('status').innerHTML=typeTransform+': '+shareScale;  
       
  
};


SVGRenderer.prototype.rotateShape = function(shape, previus, toX, toY) {
 
    //document.getElementById('richdraw').style.cursor='e-resize';
     	 var box = shape.getBBox();  
	 var prevbox=previus.getBBox();
	var centerx= box.x+(box.width/2);
	var centery= box.y+(box.height/2); 
	var coord=this.editor.inputxy;

       var actual_angle=ang2v(centerx,centery,coord[0], coord[1]);
       
       if(xrot<toX) { rotatexxx+=1;}else{rotatexxx-=1;}
       xrot=toX;
       yrot=toY;  
       
	var xtr=0;
        var ytr=0;
                
        var box= shape.getBBox();  
        var tr1x=  box.x;  
         var tr1y=  box.y;

 
 
    toX+=xtr;
        toY+=xtr;

      //var trax=parseFloat(toX-box.x);   var tray= parseFloat(toY-box.y);      
      var trax=parseFloat(box.x/2);   var tray= parseFloat(box.y/2); 
       var angler=Math.atan2(toX,toY);
         var angle=angler*180/Math.PI;  
          var T = shape.getCTM(); 
          var rotini=T.a*(180 / Math.PI);
                   var angle=rotini*180/Math.PI;
          var rot_angle=actual_angle*180/Math.PI;  
          this.editor.log(centerx+' '+centery+' '+coord[0]+' '+coord[1]+'____ '+rot_angle+' '+actual_angle*180/Math.PI);
          
          
         // matrix( a, b, c, d, e, f )
         // a c e
         // b d f
         // 0 0 1
         //a scale factor of 2, a rotation of 30 deg and a translation of (500,50)
         //T     1.732   -1   500     1   1.732   50     0   0   1
         //T      1  ad-bc      d  -c -de+cf   -b  a  be-df    0   0   1
         
         //shape.setAttributeNS(null,'transform', "translate("+(-xshe)+","+(-yshe)+")");
 
         // shape.setAttributeNS(null,"transform", "  matrix( a, b, c, d, e, f )");
          // shape.setAttributeNS(null,'transform', "translate("+(box.x+(box.width/2))+","+(box.y+(box.height/2))+")  rotate("+rotatexxx+") ");
           //shape.setAttributeNS(null,'transform', "translate("+(box.x+(box.width/2))+","+(box.y+(box.height/2))+") rotate("+rotatexxx+") translate("+(-box.x-(box.width/2))+","+(-box.y-(box.height/2))+") ");
         //shape.setAttributeNS(null,'transform', "rotate("+rotatexxx+","+(box.x+(box.width/2))+","+(box.y+(box.height/2))+")");
         //shape.setAttributeNS(null,'transform', "rotate("+rotatexxx+","+(prevbox.x+(prevbox.width/2))+","+(prevbox.y+(prevbox.height/2))+")");
         shape.setAttributeNS(null,'transform', "rotate("+rot_angle+","+(prevbox.x+(prevbox.width/2))+","+(prevbox.y+(prevbox.height/2))+")");
                          
         
         //alert('[  ['+T.a+'  '+T.c+'  '+T.e+']  ['+T.b+'  '+T.d+'  '+T.f+']  [0  0  1]  ]');
        //a,b,c,d,e,f  
           
          // shape.setAttributeNS(null,'transform', 'matrix('+T.a+', '+T.b+', '+ T.c+', '+ T.d+', '+ T.e+', '+ T.f+')' );
          
          var x1=T.e;
          var y1=T.f;
          var sp = Math.sin(rotatexxx*(Math.PI / 180));
          var cp = Math.cos(rotatexxx*(Math.PI / 180));
          var x2 = 0 + r*rotatexxx*(Math.PI / 180);
          var y2 = 0;
          var r=0; 
           
          var a=cp;
          var c=sp;
          var e=T.e;
          var b=T.b;
          var d=(-x1*cp+y1*sp+x2); 
          var f=(-x1*sp-y1*cp+y2);
      
      var inv=T.inverse;  
      var inv_mat=T.multiply(inv); 
       //var matrix = "matrix(" + cp +"," + sp + "," + (-sp) + "," + cp + ","+ (-x1*cp+y1*sp+x2) + ","+ (-x1*sp-y1*cp+y2) + ")";
       //var matrix = "matrix(" + a +"," + c + "," + e + "," + b + ","+ d + ","+ f + ")";
      var matrix='matrix('+inv_mat.a+' '+inv_mat.b+' '+inv_mat.c+' '+inv_mat.d+' '+inv_mat.e+' '+inv_mat.f+')'
      
       //++ shape.setAttributeNS(null,'transform',matrix); 
        
        //shape.setAttributeNS(null,'transform', "rotate("+rotatexxx+")"); 
        // shape.setAttributeNS(null,'transform', "translate("+(box.x)+","+(box.y)+")");
        
         //shape.setAttributeNS(null,'transform', "rotate("+rotatexxx+")");
               //shape.setAttributeNS(null, 'x', -box.width/2 + 'px');
               //shape.setAttributeNS(null, 'y', -box.height/2 + 'px');
         //shape.setAttributeNS(null,"transform", "matrix("+Math.cos(angle)+", "+Math.sin(angle)+", "+Math.sin(-angle)+", "+Math.cos(angle)+", 0, 0 )");
           //shape.setAttributeNS(null,'transform', "rotate("+10+")"); 
   
               //shape.setAttributeNS(null, 'x', box.width/2 + 'px');
               //shape.setAttributeNS(null, 'y', box.height/2 + 'px');
      
                
  
          //$('status').innerHTML = 'Mode: Draw '+pointshape +'_'+xsh +' '+ ysh+' '+trshape;
          
  //$('status').innerHTML=typeTransform+': '+rotatexxx;  
    
};



// x(u) = x0*(1-u) + x1*u = x0 + (x1-x0)*u
// y(u) = y0*(1-u) + y1*u = y0 + (y1-y0)*u
      


SVGRenderer.prototype.getshapes = function(){
return this.svgRoot.childNodes;
} 


function generateJSON(cssEnv){
 var css = cssEnv.trim().split(";"), styleArray = [], currentStyle = "";
 for(var i = 0; i < css.length; i++){
 	currentStyle = css[i].trim().split(":");
	if (currentStyle[0] && currentStyle[1] && currentStyle[0].length > 1 && currentStyle[1].length > 1) {
		styleArray.push(['"', currentStyle[0].toString().trim(), '": "', currentStyle[1].toString().trim(), '"'].join(""))
	}
 }
 return "{"+styleArray.join(",")+"}";
}

//http://xml-utils.com/conferencia-svg.html#d0e527
//http://www.xml.com/lpt/a/1321
//http://phrogz.net/objjob/object.asp?id=101
//http://admisource.gouv.fr/plugins/scmcvs/cvsweb.php/Cassini-ihm/js-yosemite/mapApp.js?rev=1.1;cvsroot=cassini
//http://groups.google.com/group/prototype-graphic/msg/0547c0caea8869c6 
//http://sylvester.jcoglan.com/ 


 /*JS File: ../js/drawing/onlypaths/vmlrenderer.js*/ 


 /*----------------------------------------------------------------------------
 VMLRENDERER 1.0
 VML Renderer For RichDraw
 -----------------------------------------------------------------------------
 Created by Mark Finkle (mark.finkle@gmail.com)
 Implementation of VML based renderer.
 -----------------------------------------------------------------------------
 Copyright (c) 2006 Mark Finkle

 This program is  free software;  you can redistribute  it and/or  modify it
 under the terms of the MIT License.

 Permission  is hereby granted,  free of charge, to  any person  obtaining a
 copy of this software and associated documentation files (the "Software"),
 to deal in the  Software without restriction,  including without limitation
 the  rights to use, copy, modify,  merge, publish, distribute,  sublicense,
 and/or  sell copies  of the  Software, and to  permit persons to  whom  the
 Software is  furnished  to do  so, subject  to  the  following  conditions:
 The above copyright notice and this  permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS",  WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED,  INCLUDING BUT NOT LIMITED TO  THE WARRANTIES  OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR  COPYRIGHT  HOLDERS BE  LIABLE FOR  ANY CLAIM,  DAMAGES OR OTHER
 LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT, TORT OR  OTHERWISE,  ARISING
 FROM,  OUT OF OR  IN  CONNECTION  WITH  THE  SOFTWARE OR THE  USE OR  OTHER
 DEALINGS IN THE SOFTWARE.
 -----------------------------------------------------------------------------
 Dependencies:
 History:
 2006-04-05 | Created
 --------------------------------------------------------------------------*/


function VMLRenderer() {
	this.base = AbstractRenderer;
}


VMLRenderer.prototype = new AbstractRenderer;


VMLRenderer.prototype.init = function(elem) 
 {
  this.container = elem;
  // this.container.style.overflow = 'hidden';
  this.container.unselectable = "on";
  // Add VML includes and namespace
  elem.ownerDocument.namespaces.add("v", "urn:schemas-microsoft-com:vml");
  var style = elem.ownerDocument.createStyleSheet();
  style.addRule('v\\:*', "behavior: url(#default#VML);");
 }


VMLRenderer.prototype.bounds = function(shape) {
  var rect = new Object();
  rect['x'] = shape.offsetLeft;
  rect['y'] = shape.offsetTop;
  rect['width'] =  shape.offsetWidth;
  rect['height'] = shape.offsetHeight;
  return rect;
}

VMLRenderer.prototype.create = function(shape, fillColor, lineColor, fillOpac, lineOpac, lineWidth, left, top, width, height, textMessaje, textSize, textFamily, imageHref, points, transform, parent) {
  var vml;
    var shap=1;
     if (shape == 'rect') {
    vml = this.container.ownerDocument.createElement('v:rect');  
    vml.style.position = 'absolute';
    vml.style.left = left; 
    
    vml.style.top = top;
    vml.style.width = width;
    vml.style.height = height;
    if (fillColor != ''  || fillColor != 'none') {
      vml.setAttribute('filled', 'true');
      vml.setAttribute('fillcolor', fillColor); 
      
    }
    else {
      vml.setAttribute('filled', 'false');
    }
  }
  else if (shape == 'roundrect') {
            vml = this.container.ownerDocument.createElement('v:roundrect'); 
            vml.style.position = 'absolute';
            vml.style.left = left;
            vml.style.top = top;
            vml.style.width = width;    
            vml.style.height = height;
            vml.setAttribute('arcsize', '20%');
            if(fillColor != '') {
              vml.setAttribute('filled', 'true'  || fillColor != 'none');
              vml.setAttribute('fillcolor', fillColor);
            }
            else {
              vml.setAttribute('filled', 'false');
            }
  }
  else if (shape == 'ellipse') {
    vml = this.container.ownerDocument.createElement('v:oval');  
    vml.style.left = left;
    vml.style.top = top;
    vml.style.width = width; 
    vml.style.height = height;
    vml.style.position = 'absolute';
              if (fillColor != ''  || fillColor != 'none') {
              vml.setAttribute('filled', 'true');
              vml.setAttribute('fillcolor', fillColor);
            }
            else {
              vml.setAttribute('filled', 'false');
            }
  }
  else if (shape == 'line') {
    vml = this.container.ownerDocument.createElement('v:line'); 
    vml.style.position = 'absolute';
    vml.setAttribute('from', left + 'px,' + top + 'px');
    vml.setAttribute('to', (left+width) + 'px,' + (top+height) + 'px');

  }   
  else if (shape == 'polyline') {
    vml = this.container.ownerDocument.createElement('v:polyline');
    //vml = this.container.ownerDocument.createElement('v:path');    
    //var   thispath=''+xpArray[0]+','+ypArray[0];      
    var thispath='M '+xpArray[1]+', '+ypArray[1]+' l'; 
    var maxcont=xpArray.length;
    for(var conta=2;conta< maxcont;conta++)
     {        
         thispath+=' '+xpArray[conta]+', '+ypArray[conta];
     } 
    //vml.setAttribute("coordsize","800,600");
    vml.setAttribute("points", points); 
    //vml.setAttribute("coordorigin","0 0");   
    //vml.setAttribute("coordsize","200 200");
    //vml.setAttribute("path", "m 8,65 l 72,65, 92,11, 112,65, 174,65, 122,100, 142,155, 92,121, 42,155, 60,100 x e;
    //vml.setAttribute("path", "M320 32 c"+ thispath+" z ");     
    //vml.setAttribute("v", "m 10,70 l 85,10,160,70,160,160,10,160 x e");
    if (fillColor != '') {
      vml.setAttribute('filled', 'true'  || fillColor != 'none');
      vml.setAttribute('fillcolor', fillColor);
    }
    else {
      vml.setAttribute('filled', 'false');
    }
    
  }    
  else if (shape == 'path') 
   {
    vml = this.container.ownerDocument.createElement('v:shape');  
    //vml.setAttribute("top", "300");  
    //vml.setAttribute("left", "200");    
    var thispath2=' ';
    //var   thispath=''+xpArray[0]+','+ypArray[0];      
    var thispath=' '+xpArray[1]+','+ypArray[1]+' l'; 
    var maxcont=xpArray.length;
    for(var conta=2;conta< maxcont;conta++)
     {        
         thispath2+=' '+xpArray[conta]+','+ypArray[conta];
     } 
    //vml.setAttribute("coordsize","800,600");
    //vml.setAttribute("path", thispath); 
    //vml.v.Value ="M320 32 C"+ thispath+"  ";
    //vml.setAttribute("coordorigin","0 0");   
    //vml.setAttribute("coordsize","200 200");
    //vml.setAttribute("path", "m 8,65 l 72,65, 92,11, 112,65, 174,65, 122,100, 142,155, 92,121, 42,155, 60,100 x e;
    var path01 = this.container.ownerDocument.createElement('v:path');  
    path01.setAttribute("v", points);
    //path01.setAttribute("v", "m "+thispath+" c"+ thispath2+" e ");  
    vml.style.position="absolute";  
    vml.style.width= 700+"px";
    vml.style.height=500+"px";
    vml.style.left="0px";  
    vml.style.top="0px";    
    vml.setAttribute('coordsize', '700,500'); 
    //vml.setAttribute('margin-left', '300px');  
    //vml.setAttribute('margin-top', '200px');
    //vml.setAttribute("WIDTH", "700px");  
    //vml.setAttribute("HEIGHT", "500px");  
    //vml.setAttribute("coordorigin", "300 -200");   
    //vml.setAttribute("o:bullet","True");
    //vml.setAttribute("path", "M10,70 C 85,10 160,70 160,160 x e"); 
    //var resolution = this.getResolution();    
    // var resolution=33;
    //var size = 800/resolution + " " + (-600/resolution);
    //vml.setAttribute("coordsize", size);
    //vml.setAttribute("textpathok", "true");
    //vml.appendChild('');
    if (fillColor != ''  || fillColor != 'none') {
      vml.setAttribute('filled', 'true');
      vml.setAttribute('fillcolor', fillColor);
    }
    else {
      vml.setAttribute('filled', 'false');
    }
    
    vml.appendChild(path01)
    
   }
   
   else if (shape == 'controlpath')
   {
    
    vml = this.container.ownerDocument.createElement('v:shape');  
      vml.style.position="absolute";  
    vml.style.width= 700+"px";
    vml.style.height=500+"px";
    vml.style.left=left+"px";  
    vml.style.top=top+"px";  
    vml.setAttribute('coordsize', '700,500');   
     
    var path01 = this.container.ownerDocument.createElement('v:path');  
    path01.setAttribute('v', 'm '+left+','+top+' c'+(left+1)+','+(top+1)+' e ');  

     if (fillColor != ''  || fillColor != 'none') {
      vml.setAttribute('filled', 'true');
      vml.setAttribute('fillcolor', fillColor);
     }
      else 
     {
      vml.setAttribute('filled', 'false');
     }
    
    vml.appendChild(path01)
    } 
    else if (shape == 'image') {   
    var data =imageHref;//document.forms[0].option_text_message.value;
    vml = this.container.ownerDocument.createElement('v:image'); 
    vml.setAttribute('src',imageHref);
    vml.style.position="absolute";  
    vml.style.width=width+"px";
    vml.style.height=height+"px";
    vml.style.left=left+"px";  
    vml.style.top=top+"px";  
    vml.style.margin=0+"px";  
    vml.style.padding=0+"px";  
    if (fillColor != ''  || fillColor != 'none') {
      vml.setAttribute('filled', 'true');
      vml.setAttribute('fillcolor', fillColor);
    }
    else {
      vml.setAttribute('filled', 'false');
    }
    vml.setAttribute('strokeweight', parseFloat(lineWidth)+'px');
   vml.setAttribute('stroked', 'true');  
   vml.setAttribute('strokecolor',lineColor);
   
   
    }
    
 else if (shape == 'textpath') 
  {   
   
    var data =textMessaje;
    vml = this.container.ownerDocument.createElement('v:shape');
    vml.style.position="absolute";  
    //vml.setAttribute('coordorigin',left+', '+top);
     //vml.style.coorsize= '';
     coordorigin="0, 0"
    vml.style.width= 100+'px'
    vml.style.height=100+'px'
    vml.style.left=left+"px";  
    vml.style.top=top+"px";  
    vml.style.margin=0+"px"; 
    //vml.style.centerX=left+"px";  
    //vml.setAttribute('center-x',(left+300)+'px');  
    vml.style.padding=0+"px";  
    if (fillColor != ''  || fillColor != 'none') 
     {
      vml.setAttribute('filled', 'true');
      vml.setAttribute('fillcolor', fillColor);
     }
      else
     {
      vml.setAttribute('filled', 'false');
     }
    if(lineWidth==0 || lineWidth=='none' || lineColor== 'none' ) 
     {
         vml.setAttribute('stroked', 'false');  
     }
      else
     {   
         vml.setAttribute('stroked', 'true');
         vml.setAttribute('strokeweight', parseFloat(lineWidth)+'px');//document.forms[0].linewidth.options[document.forms[0].linewidth.selectedIndex].value+'px');
         vml.setAttribute('strokecolor',lineColor);//document.forms[0].linecolor.options[document.forms[0].linecolor.selectedIndex].value);
     }   
     vml.setAttribute('path','m '+0+' '+0+' r '+(700)+' '+0+' e'); 
     var textPathObj = this.container.ownerDocument.createElement("v:textpath");
     textPathObj.setAttribute('string', data); 
      textPathObj.setAttribute('fitshape','false'); 
     textPathObj.setAttribute('trim', 'false'); 
     textPathObj.setAttribute('fitpath', 'false');
     textPathObj.setAttribute('on','true');  
     textPathObj.style.fontFamily=textFamily;  
     textPathObj.style.fontSize=parseFloat(textSize)+'px'; 
     textPathObj.setAttribute('vTextKern','true');  
     textPathObj.setAttribute('text-align','right');   
     //? textPathObj.setAttribute('v-rotate-letters','true'); 
     var pathObj = this.container.ownerDocument.createElement("v:path");
     pathObj.setAttribute('textpathok', 'true');  
     
     //var textHandles = this.container.ownerDocument.createElement("v:handles");  
     //textHandles.setAttribute('position')='bottomRight';

     //vml.appendChild(textHandles);  
     vml.appendChild(textPathObj);  
     vml.appendChild(pathObj);  
    
    
  }    


    
 else if (shape == 'text') 
  { 
    //style="position: absolute; width: 500; height: 500; left:300; top:50;"   
    //coordorigin="-30 -30" coordsize="500 500"  
    vml = this.container.ownerDocument.createElement('v:shape');
    vml.style.position="absolute";  
    //vml.setAttribute('coordorigin',0+', '+0);
   
     vml.style.coordsize=1000+', '+1000;
     //vml.style.coorsize= '';
    // coordorigin="0, 0"
    vml.style.width= 1000;
    vml.style.height=1000;
    vml.style.left=left;  
    vml.style.top=top-parseFloat(textSize);  
 
    //vml.style.centerX=left+"px";  
    //vml.setAttribute('center-x',(left+300)+'px');  
    vml.style.padding=0;  
    var textBox = this.container.ownerDocument.createElement("v:textbox");



     /*<v:textbox> <div style="font-family: Verdana;" ><b style="color:purple">C</b>
            <b style="color:rgb(153, 50, 204)">U</b>
            <b style="color:rgb(255, 0, 255)">R</b>
            <b style="color:red; font-size:20;">V</b>
            <b style="color:rgb(255, 192, 203); font-size:20;">E</b>
            </div>
       */     
     //textBox.textContent='<div style="font-family: Verdana;">'+textMessaje+'</div>';
     var divtext = this.container.ownerDocument.createElement("div");  
     divtext.style.coordorigin=0+', '+(0);      
     divtext.style.margin=0;   
     divtext.style.fontFamily=textFamily; 
     divtext.style.margin=0; 
     divtext.style.padding=0;
     
     
     divtext.style.fontSize=parseFloat(textSize); 
     divtext.style.color="#000000";  
     divtext.innerHTML=textMessaje;
     //textBox.textContent='<div style="font-family: Verdana; font-size:40; color:rgb(255, 0, 255)">'+textMessaje+'</div>';              
     textBox.appendChild(divtext);       
    vml.appendChild(textBox);  
    
  }    
    else if (shape == 'group') {   
    vml = this.container.ownerDocument.createElement('v:group'); 
    vml.style.left=left+"px";  
    vml.style.top=top+"px";  
  }
 
  if(shape == 'zoom') 
  {
        
  }else
  {                                          
       if(transform!='')
        {
         //svg.setAttributeNS(null, 'transform', transform);      
        }
  
        if(shape != 'image' )
         {  
                if(lineWidth==0 || lineWidth=='none' || lineColor== 'none' )    
                {
                  vml.setAttribute('stroked', 'false');  
                }
                 else 
                {
                  vml.setAttribute('stroked', 'true');
                  vml.setAttribute('strokecolor', lineColor);
                  vml.setAttribute('strokeweight', lineWidth);
                  var stroke = this.container.ownerDocument.createElement('v:stroke'); 
                  stroke.setAttribute("opacity", parseFloat(lineOpac));
                  vml.appendChild(stroke);
                }

               if (fillColor != ''  || fillColor != 'none') 
                {
                  var fill = this.container.ownerDocument.createElement('v:fill'); 
                  fill.setAttribute("opacity", parseFloat(fillOpac));
                  vml.appendChild(fill);
                }
          }     
  } 
  if(parent==''){
   this.container.appendChild(vml);
  }else{     
   var parentShape = document.getElementById(parent);
   parentShape.appendChild(vml);
  }
  
  return vml;
};  


VMLRenderer.prototype.datacreate = function(fillColor, lineColor, lineWidth, left, top, width, height,data) {
  var vml; 
  var re_split = /[ ,]/;
  vml = this.container.ownerDocument.createElement('v:shape'); 
  var path01 = this.container.ownerDocument.createElement('v:path');  
  // adjust some SVG path commands to VML commands
  var path = data
  path = path.replace(/c/g,'v');
  path = path.replace(/z/g,'x'); //or e?
  // round all decimal points to integers
  // VML does not appear to parse them correctly
  if (path.search(/\./) > -1) 
   {
     pathitems = path.split(re_split);
     for (var i=0; i<pathitems.length; i++) 
      {
         if (isNaN(parseFloat(pathitems[i])) == false)
          {
              pathitems[i] = Math.round(pathitems[i]);
          }
      }
      path = pathitems.join(" ");
   }
  path01.setAttribute("v", path);  
  vml.style.position="absolute";  
  vml.style.width= '21600';//700+"px";
  vml.style.height='21600';//500+"px";
  vml.style.left="0px";  
  vml.style.top="0px";    
  //vml.setAttribute('coordsize',datasplit[0]+','+datasplit[1]);//700,500 
  vml.setAttribute('coordsize', '21600,21600');//('coordsize','700,500');//700,500 
  if (fillColor != '') 
   {
      vml.setAttribute('filled', 'true');
      vml.setAttribute('fillcolor', fillColor);
   }else {
      vml.setAttribute('filled', 'false');
   }    
  vml.appendChild(path01)
  this.container.appendChild(vml);
  return vml;

};   

VMLRenderer.prototype.index = function(shape,order) {  
 
     if(order==-1)
      {
        this.container.appendChild( shape );
      }
      if(order==0){
     
         this.container.insertBefore( shape, shape.parentNode.firstChild );
      } 
 
   if(order==1 || order==2)
    {
         var id=shape.getAttribute('id');
        //alert(id);
        
        
        var numNodes=this.container.childNodes.length;
        //alert(numNodes);
          
        var num=0;
        for(var i = 1; i < numNodes; i++)
         {                                                   
           
           var etiq=this.container.childNodes[i].getAttribute('id');
           if (etiq==id)
            { 
                num=i; 
               
            }                                                    
          } 
          //alert(num);    
          if(order==1) 
           {   
              if((num-1)>=-1)
               {  
                this.container.insertBefore( shape, this.container.childNodes[num-1]);
               } 
           }
          if(order==2){ 
               if((num+1)<numNodes)
               {
                  this.container.insertBefore( shape, this.container.childNodes[num+2]);
               }
          } 
          
    } 
    
    
    
}
VMLRenderer.prototype.remove = function(shape) {
  if(shape!=null){ shape.removeNode(true); }
}

VMLRenderer.prototype.removeAll = function() {  
 while( this.container.hasChildNodes () ){
   this.container.removeChild( this.container.firstChild );
   //this.container.removeNode( this.container.firstChild );
 }
   /*var contshapes =  this.container.childNodes.length;       
    
                          
    var cad=contshapes+'   ';
    for(var i = 0; i < contshapes; i++)
    {                                  
        //alert(i); 
        
        if(this.container.childNodes[i].id) {
             this.container.removeChild(this.container.childNodes[i]);
         }else{
            //cad+=i+'_'+this.svgRoot.childNodes[i].id+' ';
         }
    } 
    //alert(cad);  
*/ 
} 
VMLRenderer.prototype.copy = function(shape) 
 {
   var vml;
   vml =shape.cloneNode(false);
   //vml.setAttribute('fillcolor', "#aa00aa");
   return vml;
 };


VMLRenderer.prototype.paste = function(clipboard,left,top) 
 {
   //var svg;
   //svg =shape;
   
   //clipboard.setAttribute('fillcolor', "#0000aa");
   //clipboard.setAttribute('transform', "translate("+left+","+top+")"); 
   this.container.appendChild(clipboard);
  return clipboard;
 };


VMLRenderer.prototype.duplicate = function(shape) 
 {
   var vml;
   vml =shape.cloneNode(false);
   vml.setAttribute('fillcolor', "#aa00aa");
   this.container.appendChild(vml);
  return vml;
 };

VMLRenderer.prototype.undo = function() 
 {
   this.container.removeChild( this.container.lastChild );
 };
 

var left1=0;;
    var top1=0;   
var pati; 
var pathid, pathini;  
     
VMLRenderer.prototype.move = function(shape, left, top,fromX,FromY) {    
   typeTransform='Translate'; 
         //contmove++;
  if (shape.tagName == 'line') {
    shape.style.marginLeft = left;
    shape.style.marginTop = top;
  } 
   if (shape.tagName == 'polyline') {
    shape.style.marginLeft = left;
    shape.style.marginTop = top;

   }   
   if (shape.tagName == 'oval') {
    shape.style.left = left;
    shape.style.top = top;
  }      
  if (shape.tagName == 'rect') {
    shape.style.left = left;
    shape.style.top = top;
  } 
  
    if (shape.tagName == 'image') {
    shape.style.left = left;
    shape.style.top = top;
  }      
   if (shape.tagName == 'shape') { 
        
       shape.style.left=left+"px";  
        shape.style.top=top+"px";  
    
   }   
      

};


VMLRenderer.prototype.track = function(shape) {
  // TODO
};

VMLRenderer.prototype.clic = function(shape) {
         var end='';
	if(data_path_close==true){end=' ';}

        var thispath='m '+setPoints[0]+' l';  
        var maxcont=setPoints.length;
      
        for(var conta=1;conta< maxcont;conta++){        
          thispath+=setPoints[conta]+' ';
          
	
        }
       	var path=thispath+end+' e';
        shape.style.position="absolute";  
        shape.style.width= 700+"px";
	shape.style.height=500+"px";
        shape.style.left="0px";  
        shape.style.top="0px";    

       
         	shape.children[0].setAttribute("v",path);
              // document.forms[0].control_codebase.value=path;
 
}


VMLRenderer.prototype.resize = function(shape, fromX, fromY, toX, toY) {     
 //var vml;
  var deltaX = toX - fromX;
  var deltaY = toY - fromY; 
    var shap=1;
    if (shape.tagName == 'line') { shap=0; }   
   if (shape.tagName == 'polyline') { shap=2; } 
    
  if (shape.tagName == 'line') {
    shape.setAttribute('to', toX + 'px,' + toY + 'px');
  }
  if (shap == 1) {
    if (deltaX < 0) {
      shape.style.left = toX + 'px';
      shape.style.width = -deltaX + 'px';
    }
    else {
      shape.style.width = deltaX + 'px';
    }
  
    if (deltaY < 0) {
      shape.style.top = toY + 'px';
      shape.style.height = -deltaY + 'px';
    }
    else {
      shape.style.height = deltaY + 'px';
    }
  }
   if (shap == 2) {   
        xpArray.push(toX);
        ypArray.push(toY);
	
        //xpArray.push(finetoX);
        //ypArray.push(finetoY);    
    
       var thispath=' '+xpArray[1]+','+ypArray[1];  
       var maxcont=xpArray.length;
       //alert(maxcont);
        for(var conta=2;conta< maxcont;conta++){        
          thispath+=' '+xpArray[conta]+','+ypArray[conta]; 
        }
        //alert(shape.points[1]);
    //shape.setAttribute("points",thispath);       
    shape.points.Value = thispath;
      
        /*
        var thispath=''+xpArray[0]+','+ypArray[0]; 
        var thispatho=new Array();   
        thispatho.push(toX); 
          thispatho.push(toY);
       var maxcont=xpArray.length;
       //alert(maxcont);
        for(var conta=2;conta< maxcont;conta++){        
          thispath+=','+xpArray[conta]+','+ypArray[conta]; 
        }
        //alert(shape.points[1]);
    shape.setAttribute("points",thispath);   
          */
   }
  if(shape.tagName == 'shape')
   {    
          
      if (selectmode == 'controlpath')
     {    
        
                 var end='';
	if(data_path_close==true){end=' ';}

        var thispath='m '+setPoints[0]+' l';  
        var maxcont=setPoints.length;
      
        for(var conta=1;conta< maxcont;conta++){        
          thispath+=setPoints[conta]+' ';
          
	
        }
        var path=thispath+toX+','+toY+end+' e';
 
        shape.style.position="absolute";  
        shape.style.width= 700+"px";
	shape.style.height=500+"px";
        shape.style.left="0px";  
        shape.style.top="0px";    

         	shape.children[0].setAttribute("v",path);
               //document.forms[0].control_codebase.value=path;

          
     }
      else
     {  
      
      xpArray.push(toX);
      ypArray.push(toY);
	
        //xpArray.push(finetoX);
        //ypArray.push(finetoY);    
        var thispath2='';
       var thispath1=' '+xpArray[1]+','+ypArray[1];  
       var maxcont=xpArray.length;
       //alert(maxcont);
        for(var conta=2;conta< maxcont ;conta++){        
          thispath2+=''+xpArray[conta]+','+ypArray[conta]+',';
          if((conta+2)%3==0){thispath2+='';} 
        } 
        thispath2+=''+xpArray[maxcont]+','+ypArray[maxcont]+'';   
        
        //alert(shape.points[1]);   
        //appendChild(path01)
       //var path01=shape.getFirstChild();  
       var path01 = this.container.ownerDocument.createElement('v:path');  
       path01.setAttribute("v", "m"+thispath1+" l"+ thispath2+" e"); 
        //shape.margin-left="300px";  
        //shape.margin-top="200px";    
  
      //shape.setAttribute('path','m '+thispath1+ ' c'+thispath2+'  e'); 
       if(shape.children[0].tagName=='textpath')
        {      
                var path01 = this.container.ownerDocument.createElement('v:path');  
                path01.setAttribute("v", 'm 100 100 l 600 100 e'); 

            //if(xpArray.length>1)
             //{       shap.style.position="absolute";  
                    shape.style.width=100+"px";
                    shape.style.height=100+"px";
                    shape.style.left=toX+"px";  
                    shape.style.top=toY+"px";  
                    shape.style.margin=0+"px";  
                    shape.style.padding=0+"px";  
                    shape.appendChild(path01); 
             //}    
        }
         else
        {  
              shape.style.position="absolute";  
          shape.style.width= 700+"px";
	  shape.style.height=500+"px";
          shape.style.left="0px";  
          shape.style.top="0px";    
          //shape.setAttribute('coordsize', '700,500');  
          shape.appendChild(path01);  
          }
        
       //shape.setAttribute('position', 'absolute'); 
       //shape.translate(xpArray[conta+1]+','+ypArray[conta+1]); 
      //shape.setAttribute('coordsize', '700,500');
       // shape.v.Value ='M '+thispath1+ ' C'+thispath2+' x e';      
      //shape.v.Value = 'M '+thispath+ ' c '+thispath2;
      //shape.setAttribute("v", 'M '+thispath+ ' C '+thispath2);  
		//shape.setAttribute('path','M '+thispath+ ' C '+thispath2);
   } 	
  } 
  
};  


VMLRenderer.prototype.tocurve = function() {


};


VMLRenderer.prototype.info = function(shape)
{   
var shInfo = {};
shInfo.id = shape.id;
 shInfo.type = shape.tagName;
 if (shape.tagName == 'rect') 
   {
    shInfo.left = parseFloat(shape.style.left);
    shInfo.top = parseFloat(shape.style.top);
    shInfo.width = parseFloat(shape.style.width);
    shInfo.height = parseFloat(shape.style.height);   
    //++
    //shInfo.rotate = parseFloat(shape.getAttribute('rotation'));  
   }
  else if (shape.tagName == 'oval') 
   {
    shInfo.width = parseFloat(shape.getAttribute('rx'))*2;
    shInfo.height = parseFloat(shape.getAttribute('ry'))*2;   
    shInfo.left = (shInfo.width * 2)  - parseFloat(shape.getAttribute('rx'));
    shInfo.top = (shInfo.height * 2)  - parseFloat(shape.getAttribute('ry'));
 
   }
  else if (shape.tagName == 'roundrect') 
   {
    shInfo.left = parseFloat(shape.getAttribute('x'));
    shInfo.top = parseFloat(shape.getAttribute('y'));
    shInfo.width = parseFloat(shape.getAttribute('width'));
    shInfo.height = parseFloat(shape.getAttribute('height'));   
   
   }
  else if (shape.tagName == 'line') 
   {
    shInfo.left = parseFloat(shape.getAttribute('x1'));
    shInfo.top = parseFloat(shape.getAttribute('y1'));

   } 
  else if (shape.tagName == 'polyline') 
   {
    shInfo.points = shape.getAttribute('points');
   }
   else if (shape.tagName == 'image') 
   {
    shInfo.left = parseFloat(shape.getAttribute('x'));
    shInfo.top = parseFloat(shape.getAttribute('y'));
    shInfo.width = parseFloat(shape.getAttribute('width'));
    shInfo.height = parseFloat(shape.getAttribute('height'));   
    shInfo.src = shape.getAttribute('src');  
   } 
  else 
  
   if (shape.tagName == 'shape')
   {  
       if(shape.children[0].tagName=='path') {
              shInfo.d = shape.getAttribute('v'); 
             //document.forms[0].codebase.value=shape.getAttribute('v'); 
             
       }
       if(shape.children[0].tagName=='textpath') {
             shInfo['font-family'] = shape.children[0].getAttribute('font-family')
           shInfo['font-size'] = parseInt(shape.children[0].getAttribute('font-size'))
        shInfo.top = parseFloat(shape.children[0].getAttribute('y'))
        shInfo.left = parseFloat(shape.children[0].getAttribute('x'))
        shInfo.text = shape.textContent

       }
   }
   return shInfo;  
   	
   	
}
VMLRenderer.prototype.transformShape = function(shape,data,transform)
{   
 
 if(shape.tagName == 'rect')
  { 
    
    var box = this.bounds(shape);
    var sdata=data.split(';'); 
    
    //alert(data[0]); 
      shape.style.top = parseFloat(sdata[0]) + 'px';  
      shape.style.left = parseFloat(sdata[1]) + 'px';
      shape.style.width = parseFloat(sdata[2]) + 'px';    
      shape.style.height = parseFloat(sdata[3]) + 'px';
     
      
   
   // var centerx=parseFloat(sdata[0])+parseFloat(box.width/2);
   // var centery=parseFloat(sdata[1])+parseFloat(box.height/2);    
    shape.style.rotation=parseFloat(sdata[4]);
    
   //shape.nodparseFloatue=data;
  }
   else 
 if(shape.tagName == 'text')
  {    
    if(data.indexOf('<;>',0)==-1 )
     {  
      shape.textContent = data;  
     }
      else
     {  
       var sdata=data.split('<;>'); //?????????
       shape.textContent = sdata[0]; 
       shape.setAttribute('font-size',parseFloat(sdata[1])); 
        shape.setAttribute('font-family',sdata[2]);
     }
   //shape.nodparseFloatue=data;
  }
   else
 if (shape.tagName == 'polyline') 
  {
    shape.setAttribute('points',data);
  }
   else 
 if (shape.tagName == 'image') 
  {   
    //alert(data);  
    if(data.indexOf(';',0)==-1 )
     {  
      shape.setAttribute('src',data);
     }
      else
     {  
        var box = this.bounds(shape);
        var sdata=data.split(';');
        shape.style.top = parseFloat(sdata[0]) + 'px';  
        shape.style.left = parseFloat(sdata[1]) + 'px';
        shape.style.width = parseFloat(sdata[2]) + 'px';    
        shape.style.height = parseFloat(sdata[3]) + 'px';
        var centerx=parseFloat(sdata[0])+parseFloat(box.width/2);
        var centery=parseFloat(sdata[1])+parseFloat(box.height/2);    
        shape.style.rotation=parseFloat(sdata[4]);


     } 
      
  }
   else 
 if (shape.tagName == 'path')
  {     
    if(data.indexOf(';',0)==-1 )
     {  
    	//shape.setAttribute( 'd', data);  //????????
    	//shape.setAttribute( 'transform', transform);  
     }
      else
     {  
        var box = this.bounds(shape);
        var sdata=data.split(';');
        var centerx=parseFloat(sdata[0])+parseFloat(box.width/2);
        var centery=parseFloat(sdata[1])+parseFloat(box.height/2);    
        //++shape.setAttribute( 'transform','scale('+parseFloat(sdata[2])+','+parseFloat(sdata[3])+')'+' rotate('+parseFloat(sdata[4])+','+centerx+','+centery+')'+' translate('+parseFloat(sdata[0])+','+parseFloat(sdata[1])+')');


     } 
  }  
   	                   
   	
}
VMLRenderer.prototype.editShape = function(shape,data)
{   
if(shape.tagName == 'text'){
shape.textContent = data
}else
   if (shape.tagName == 'polyline') 
   {
    shape.setAttribute('points',data);
   }
  else 
  
  if (shape.tagName == 'path')
   {
    	shape.setAttribute('v', data);  
    	
   }  
   	 
   	
}
VMLRenderer.prototype.editCommand = function(shape, cmd, value)
{
  if (shape != null) {
    if (cmd == 'fillcolor') {
      if (value != '') {
        shape.filled = 'true';
        shape.fillcolor = value;
      }
      else {
        shape.filled = 'false';
        shape.fillcolor = '';
      }
    }
    else if (cmd == 'linecolor') {
      if (value != '') {
        shape.stroked = 'true';
        shape.strokecolor = value;
      }
      else {
        shape.stroked = 'false';
        shape.strokecolor = '';
      }
    }
    else if (cmd == 'linewidth') {
      shape.strokeweight = parseInt(value) + 'px';
    } 
     else if (cmd == 'fillopacity') {
           
             shape.fill.opacity= parseFloat(value);
            //shape.style.fill.setAttribute("opacity", parseFloat(value)); 
      
    }
  }
}


VMLRenderer.prototype.queryCommand = function(shape, cmd)
{
  if (shape != null) {
    if (cmd == 'fillcolor') {
      if (shape.filled == 'false')
        return '';
      else
        return shape.fillcolor;
    }
    else if (cmd == 'linecolor') {
      if (shape.stroked == 'false')
        return '';
      else
        return shape.strokecolor;
    }
    else if (cmd == 'linewidth') {
      if (shape.stroked == 'false') {
        return '';
      }
      else {
        // VML always transforms the pixels to points, so we have to convert them back
        return (parseFloat(shape.strokeweight) * (screen.logicalXDPI / 72)) + 'px';
      }
    }
  }
}

VMLRenderer.prototype.getProperties = function(shape)
{
 
}

VMLRenderer.prototype.showMultiSelect = function(iniX,iniY) { 
  var tracker = document.getElementById('trackerMultiSelect');
  if (tracker) {
    this.remove(tracker);
  } 
  var coord=this.editor.inputxy;
	toX=parseFloat(coord[0]);
	toY=parseFloat(coord[1]); 
	
   tracker = this.container.ownerDocument.createElement('v:rect');
  
  tracker.style.position = 'relative';
  tracker.style.left = iniX;
  tracker.style.top = iniY;
  tracker.style.width = toX ;
  tracker.style.height = toY;
  tracker.setAttribute('filled', 'false');
  tracker.setAttribute('stroked', 'true');
  tracker.setAttribute('strokecolor', 'blue');
  tracker.setAttribute('strokeweight', '1px');    
  
  this.container.appendChild(tracker);    
}

VMLRenderer.prototype.showNodesCurve = function(path){
  var points=path.split('c');
     var chain='';
     var segment=' ';
     var numpoints=points.length-1;
     for(var a=1;a<numpoints;a++)
      {   
        segment=points[a].split(' ');
         chain+=segment[0]+' ';       
      } 
      
         $('someinfo').value=numpoints+ ' nodes ';
    return chain;    
        
};



VMLRenderer.prototype.showTracker = function(shape) {
  var box = this.bounds(shape);
  var trshape = parseFloat(shape.getAttribute('rotation'));  
  var tracker = document.getElementById('tracker');
  if (tracker) {
    this.remove(tracker);
  }
  
  if (shape.tagName == 'shape') 
   { 
      shap=2; 
      if(shape.children[0].tagName == 'path') 
       {
      
            /* $('option_path_trx').value= box.x;  
             $('option_path_try').value= box.y;
             $('option_path_sclx').value= box.width;   
             $('option_path_scly').value= box.height; 
             $('option_path_rot').value= shape.style.rotation;
             */  
             var path=shape.children[0].getAttribute('v');
              $('control_codebase').value=path;
       }        
   }     
  if (shape.tagName == 'rect') { 
/*
     
     $('option_rect_rot').value= shape.getAttribute('rotation');
     $('option_rect_trx').value= box.x;  
     $('option_rect_try').value= box.y;
     $('option_rect_sclx').value= box.width;  
     $('option_rect_scly').value= box.height;

*/
  }  

  if (shape.tagName == 'image'){
  /*  $('option_img_trx').value= box.x; 
    $('option_img_try').value= box.y;
    $('option_img_sclx').value= box.width;  
    $('option_img_scly').value= box.height;
    $('option_img_rot').value= T.b* (Math.PI * 2 / 360);   
      */
  }
  if (shape.tagName == 'text'){
   /* f$('option_text_trx').value= box.x; 
    $('option_text_try').value= box.y;
    $('option_text_sclx').value= box.width;  
    $('option_text_scly').value= box.height;
    $('option_text_rot').value= T.b* (Math.PI * 2 / 360);
   */
  }
  if (shape.tagName == 'line'){ 
    /*
    $('option_line_trx').value= box.x;  
    $('option_line_try').value= box.y;
    */
  }   
  if (shape.tagName == 'oval'){  
    /*$('option_ellipse_trx').value= putx;  
    $('option_ellipse_try').value= puty;
    $('option_ellipse_sclx').value= box.width;  
    $('option_ellipse_scly').value= box.height;
    $('option_ellipse_rot').value= T.b* (Math.PI * 2 / 360);
    */
  }
  
  
  
 /*var matrix = shape.getScreenCTM();
  var trshape= shape.getAttribute('transform');  
  var shap=1;
  if (shape.tagName == 'path') { shap=2; 
        
        
        
  }
  */  
  //if (shape.getAttribute('transform') ) { shap=2; } 
  //var svgNamespace = 'http://www.w3.org/2000/svg';
  
   tracker = this.container.ownerDocument.createElement('v:group');
   tracker.id = 'tracker'; 
  //tracker.setAttribute('rotation',trshape);
  tracker.setAttribute('coordorigin','0, 0');
  //tracker.setAttribute('wrapcoords',true);
 
   
  tracker.setAttribute('coordsize',box.width+','+ box.height);
  tracker.style.position = 'absolute';   
  tracker.style.left = box.x ;
  tracker.style.top = box.y;
  tracker.style.width = box.width ;
  tracker.style.height = box.height ;
       
        
        
        
        
   
    
    
    
    ////////////////

 /*
       
       var trshape='translate (0,0) rotate(0) translate(0,0) '; 
       var trshape_split=trshape.split(') ');    
       
      // get_between (trshape, s1, s2) ;
     if(shape.getAttribute('transform')){ 
         var trshape=shape.getAttribute('transform') ;   
         //var spl=trshape.replace(', ',' ');  
         //var spl1=spl.replace(')',' ');    
         var trshape_split=trshape.split(') '); 
         

    }
  */
                                         
 var corners = [];
  var point = createPoint(box.x, box.y, box.width, box.height);
 //point = {x:box.x, y:box.y, width: box.width, height:box.height};
//point = createPoint(box.x, box.y, box.width, box.height);    
  //1
  corners.push( createPoint(box.x + box.width, box.y, box.width, box.height) );
  point.x = box.x + box.width;
  point.y = box.y;
  //2
  corners.push( createPoint(box.x + box.width, box.y + box.height, box.width, box.height) );
  point.x = box.x + box.width;
  point.y = box.y + box.height;
  //3
  //corners.push( point.matrixTransform(matrix) );
  corners.push( createPoint(box.x , box.y + box.height, box.width, box.height) );
  point.x = box.x;
  point.y = box.y + box.height;
  //4
  corners.push( createPoint(box.x + box.width, box.y, box.width, box.height) );   
  
  var max = createPoint(corners[0].x, corners[0].y);
  var min = createPoint(corners[0].x, corners[0].y);

  // identify the new corner coordinates of the
  // fully transformed bounding box
  
  for (var i = 1; i < corners.length; i++) {
    var x = corners[i].x;
    var y = corners[i].y;
    if (x < min.x) {
      min.x = x;
    }
    else if (x > max.x) {
      max.x = x;
    }
    if (y < min.y) {
      min.y = y;
    }
    else if (y > max.y) {
      max.y = y;
    }
  } 
      
      
 var border_square = this.container.ownerDocument.createElement('v:rect');
  
  border_square.style.position = 'relative';
  border_square.style.left = 0 - 10;
  border_square.style.top = 0 - 10;
  border_square.style.width = box.width + 20;
  border_square.style.height = box.height + 20;
  border_square.setAttribute('filled', 'false');
  border_square.setAttribute('stroked', 'true');
  border_square.setAttribute('strokecolor', 'blue');
  border_square.setAttribute('strokeweight', '1px');  
  
  
  var border_angle = this.container.ownerDocument.createElement('v:polyline');  
  border_angle.style.position = 'relative';
 
    //border_angle.setAttribute('from',(box.width+10) + 'px,' + (box.height/2) + 'px');
   //border_angle.setAttribute('to', (box.width+10+25) + 'px,' + (box.width+10) + 'px');
  border_angle.setAttribute('filled', 'false');
  border_angle.setAttribute('stroked', 'true');
  border_angle.setAttribute('strokecolor', 'blue');
  border_angle.setAttribute('strokeweight', '1px'); 
  border_angle.setAttribute("points", (box.width+10)+","+((box.height/2))+", "
                                      +(box.width+10+25)+","+((box.height/2)) );
                  
      
    /* var path01 = this.container.ownerDocument.createElement('v:path');  
     //path01.setAttribute("v", "m "+thispath+" c"+ thispath2+" e ");  
     path01.setAttribute("v", "m"+(min.x-10)+","+ (min.y-10)+" r"+(box.width+20)+","+(0)+" r"+(0)+","+(box.height+20)+" r"+(-box.width-20)+','+(0)+"x e m"+(box.x+box.width+10)+","+ (box.y+(box.height/2))+" r"+(25)+",0  e ");
     border.appendChild(path01)
    */ 
     //border.setAttribute('stroke-width', '1'); 
       
// createRect(min.x, min.y, max.x - min.x, max.y - min.y);
  
  
 /* tracker = this.container.ownerDocument.createElement('v:rect');
  tracker.id = 'tracker';
  tracker.style.position = 'absolute';
  tracker.style.left = box.x - 10;
  tracker.style.top = box.y - 10;
  tracker.style.width = box.width + 20;
  tracker.style.height = box.height + 20;
  tracker.setAttribute('filled', 'false');
  tracker.setAttribute('stroked', 'true');
  tracker.setAttribute('strokecolor', 'blue');
  tracker.setAttribute('strokeweight', '1px');
  this.container.appendChild(tracker);
 */
     var circle1 = this.container.ownerDocument.createElement('v:oval'); 
      circle1.style.position = 'relative'; 
        circle1.style.left = ( (box.width+40)-5);
    circle1.style.top = ( (box.height / 2) -5);
    circle1.style.width = (10);
    circle1.style.height = (10);
    circle1.setAttribute('filled', 'true');
   circle1.setAttribute('stroked', 'true'); 
   circle1.setAttribute('fillcolor', '#ffffff');
   circle1.setAttribute('strokecolor', 'green');
   circle1.setAttribute('strokeweight', '1px');

   
  var rect1 = this.container.ownerDocument.createElement('v:rect');
  rect1.style.position = 'relative';
  rect1.style.left =  - 10-5;
  rect1.style.top =  - 10-5;
  rect1.style.width = 10;
  rect1.style.height = 10;
  rect1.setAttribute('filled', 'true');
  rect1.setAttribute('stroked', 'true'); 
  rect1.setAttribute('fillcolor', '#ffffff');
  rect1.setAttribute('strokecolor', 'green');
  rect1.setAttribute('strokeweight', '1px');

    
  var rect2 = this.container.ownerDocument.createElement('v:rect');
  rect2.style.position = 'relative';
  rect2.style.left =   box.width +5;
  rect2.style.top = -10 -5;
  rect2.style.width = 10;
  rect2.style.height = 10;
  rect2.setAttribute('filled', 'true');
  rect2.setAttribute('stroked', 'true'); 
  rect2.setAttribute('fillcolor', '#ffffff');
  rect2.setAttribute('strokecolor', 'green');
  rect2.setAttribute('strokeweight', '1px');

                                                        
  var rect3 = this.container.ownerDocument.createElement('v:rect');
  rect3.style.position = 'relative';
  rect3.style.left =   box.width+5;
  rect3.style.top =  box.height+5;
  rect3.style.width = 10;
  rect3.style.height = 10;
  rect3.setAttribute('filled', 'true');
  rect3.setAttribute('stroked', 'true'); 
  rect3.setAttribute('fillcolor', '#ffffff');
  rect3.setAttribute('strokecolor', 'green');
  rect3.setAttribute('strokeweight', '1px');
   
  var rect4 = this.container.ownerDocument.createElement('v:rect');
  rect4.style.position = 'relative';
  rect4.style.left =  -10-5;
  rect4.style.top = box.height+5;
  rect4.style.width = 10;
  rect4.style.height = 10;
  rect4.setAttribute('filled', 'true');
  rect4.setAttribute('stroked', 'true'); 
  rect4.setAttribute('fillcolor', '#ffffff');
  rect4.setAttribute('strokecolor', 'green');
  rect4.setAttribute('strokeweight', '1px');
 
 
 
  var rectmid12 = this.container.ownerDocument.createElement('v:rect');
  rectmid12.style.position = 'relative';
  rectmid12.style.left = (box.width/2) -5;
  rectmid12.style.top =- 10-5;
  rectmid12.style.width = 10;
  rectmid12.style.height = 10;
  rectmid12.setAttribute('filled', 'true');
  rectmid12.setAttribute('stroked', 'true'); 
  rectmid12.setAttribute('fillcolor', '#ffffff');
  rectmid12.setAttribute('strokecolor', 'green');
  rectmid12.setAttribute('strokeweight', '1px');

 var rectmid23 = this.container.ownerDocument.createElement('v:rect');
  rectmid23.style.position = 'relative';
  rectmid23.style.left = box.width +5;
  rectmid23.style.top = (box.height/2)-5;
  rectmid23.style.width = 10;
  rectmid23.style.height = 10;
  rectmid23.setAttribute('filled', 'true');
  rectmid23.setAttribute('stroked', 'true'); 
  rectmid23.setAttribute('fillcolor', '#ffffff');
  rectmid23.setAttribute('strokecolor', 'green');
  rectmid23.setAttribute('strokeweight', '1px');

 var rectmid34 = this.container.ownerDocument.createElement('v:rect');
  rectmid34.style.position = 'relative';
  rectmid34.style.left = (box.width/2)-5;
  rectmid34.style.top = box.height+5;
  rectmid34.style.width = 10;
  rectmid34.style.height = 10;
  rectmid34.setAttribute('filled', 'true');
  rectmid34.setAttribute('stroked', 'true'); 
  rectmid34.setAttribute('fillcolor', '#ffffff');
  rectmid34.setAttribute('strokecolor', 'green');
  rectmid34.setAttribute('strokeweight', '1px');

 
 var rectmid41 = this.container.ownerDocument.createElement('v:rect');
  rectmid41.style.position = 'relative';
  rectmid41.style.left =  -10-5 ;
  rectmid41.style.top =(box.height/2)-5;
  rectmid41.style.width = 10;
  rectmid41.style.height = 10;
  rectmid41.setAttribute('filled', 'true');
  rectmid41.setAttribute('stroked', 'true'); 
  rectmid41.setAttribute('fillcolor', '#ffffff');
  rectmid41.setAttribute('strokecolor', 'green');
  rectmid41.setAttribute('strokeweight', '1px');
 
       
  

     var colorin="#ff0000";
      var colorout="#ffffff" 
      
        circle1.attachEvent("onmouseover", function(event) {circle1.style.cursor= 's-resize';  circle1.setAttribute('fillcolor', colorin ); typeTransform='Rotate'; scaleType='nw'; }, false);
     circle1.attachEvent("onmouseout", function(event) {circle1.style.cursor= 'default';  circle1.setAttribute('fillcolor', colorout ); typeTransform='Rotate'; }, false); //typeTransform='rotate'
 
      
     rect1.attachEvent("onmouseover", function(event) {rect1.style.cursor= 'nw-resize';  rect1.setAttribute('fillcolor', colorin ); typeTransform='Scale'; scaleType='nw';  }, false);
     rect1.attachEvent("onmouseout", function(event) {rect1.style.cursor= 'default';  rect1.setAttribute('fillcolor', colorout ); typeTransform='Scale';  }, false); //typeTransform='rotate'
    
     rect2.attachEvent("onmouseover", function(event) {rect2.style.cursor= 'ne-resize';  rect2.setAttribute('fillcolor', colorin ); typeTransform='Scale'; scaleType='ne';}, false);  
     rect2.attachEvent("onmouseout", function(event) {rect2.style.cursor= 'default';  rect2.setAttribute('fillcolor', colorout ); typeTransform='Scale'; }, false);
      
     rect3.attachEvent("onmouseover", function(event) {rect3.style.cursor= 'se-resize';  rect3.setAttribute('fillcolor', colorin ); typeTransform='Scale'; scaleType='se';}, false);  
     rect3.attachEvent("onmouseout", function(event) {rect3.style.cursor= 'default';  rect3.setAttribute('fillcolor', colorout ); typeTransform='Scale'; }, false);
     
     rect4.attachEvent("onmouseover", function(event) {rect4.style.cursor= 'sw-resize';  rect4.setAttribute('fillcolor', colorin ); typeTransform='Scale'; scaleType='sw';}, false);  
     rect4.attachEvent("onmouseout", function(event) {rect4.style.cursor= 'default';  rect4.setAttribute('fillcolor', colorout ); typeTransform='Scale'; }, false);
                                                    
     rectmid12.attachEvent("onmouseover", function(event) {rectmid12.style.cursor= 'n-resize';  rectmid12.setAttribute('fillcolor', colorin ); typeTransform='Scale'; scaleType='n';}, false);  
     rectmid12.attachEvent("onmouseout", function(event) {rectmid12.style.cursor= 'default';  rectmid12.setAttribute('fillcolor', colorout ); typeTransform=''; }, false); 

     rectmid23.attachEvent("onmouseover", function(event) {rectmid23.style.cursor= 'e-resize';  rectmid23.setAttribute('fillcolor', colorin ); typeTransform='Scale'; scaleType='e';}, false);  
     rectmid23.attachEvent("onmouseout", function(event) {rectmid23.style.cursor= 'default';  rectmid23.setAttribute('fillcolor', colorout ); typeTransform=''; }, false); 
     
     rectmid34.attachEvent("onmouseover", function(event) {rectmid34.style.cursor= 's-resize';  rectmid34.setAttribute('fillcolor', colorin ); typeTransform='Scale'; scaleType='s';}, false);  
     rectmid34.attachEvent("onmouseout", function(event) {rectmid34.style.cursor= 'default';  rectmid34.setAttribute('fillcolor', colorout ); typeTransform=''; }, false); 

     rectmid41.attachEvent("onmouseover", function(event) {rectmid41.style.cursor= 'w-resize';  rectmid41.setAttribute('fillcolor', colorin ); typeTransform='Scale'; scaleType='w'; }, false);  
     rectmid41.attachEvent("onmouseout", function(event) {rectmid41.style.cursor= 'default';  rectmid41.setAttribute('fillcolor', colorout ); typeTransform=''; }, false); 
   //tracker.setAttribute('transform',trshape); 

 
 
  tracker.appendChild(border_square); 
  tracker.appendChild(border_angle);  
   
  tracker.appendChild(circle1);  
  
  tracker.appendChild(rect1);    
  tracker.appendChild(rect2);   
  tracker.appendChild(rect3); 
  tracker.appendChild(rect4);    
  tracker.appendChild(rectmid12);  
  tracker.appendChild(rectmid23);
  tracker.appendChild(rectmid34);
  tracker.appendChild(rectmid41);  
  
  /*
   
  
 
  */


   this.container.appendChild(tracker);



}                                      










VMLRenderer.prototype.getMarkup = function() { 
       
  return this.container.innerHTML;
}



/////////////////////////////////



var rotatexxx=0; 
 
var scaleType=''; 
var xrot=0;
var yrot=0;  

var point = {x:0, y:0, width: 0, height:0};

function createPoint (x, y, width, height) {
    //var point = {x:34, y:22, width: 22, height:23};
    //point.x = x;
    //point.y = y;   
    point = {x:x, y:y, width: width, height:height};
    return point;
  }


/////////////////////////////////

VMLRenderer.prototype.restruct= function(shape)
{
};        



VMLRenderer.prototype.transform = function() {

};

VMLRenderer.prototype.scaleShape = function(shape, previus,toX, toY) {
// document.forms[0].code.value="escala";      

         //document.forms[0].code.value="escala"; 
          var box = this.bounds(shape);
	 var prevbox=this.bounds(previus);
	var centerx= box.x+(box.width/2);
	var centery= box.y+(box.height/2); 
	var coord=this.editor.inputxy;
	toX=parseFloat(coord[0]);
	toY=parseFloat(coord[1]); 
	var d2p_center=dist2p(centerx,centery,toX,toY);       

	var d2p=dist2p(box.x,box.y,toX,toY);

	var shareScale=box.width/d2p;

	var trans_ShareScale='';
	var tx, ty, tw, yh;

	if(scaleType.length==1){
		if(scaleType== 'w')
		 {
			trans_ShareScale=shareScale+",1";  
			tx=toX; 
			ty=prevbox.y; 
			var dist=prevbox.x-toX;
			var w=dist+prevbox.width;
			if(w<1){w=1;}
			tw=w;
			th=prevbox.height;
			//document.forms[0].code.value=box.x+' '+toX+' '+dist+''; 
		 }        
		if(scaleType== 'e')
		 {
		        trans_ShareScale=shareScale+",1"; 
			tx=prevbox.x; 
			ty=prevbox.y; 
			var dist=toX-(prevbox.x+prevbox.width); //dist2p(toX,b,c,d);
			var w=dist+prevbox.width;
			if(w<1){w=1;}
			tw=w;
			th=prevbox.height;
 
		 }        
		if(scaleType== 'n')
		 {
			trans_ShareScale="1,"+shareScale; 
			
			tx=prevbox.x; 
			ty=toY; 
			var dist=prevbox.y-toY;
			var h=dist+prevbox.height;
			if(h<1){h=1;}
			tw=prevbox.width;
			th=h;

		 }
                if( scaleType== 's')
                 {
                        trans_ShareScale="1,"+shareScale;  

			tx=prevbox.x; 
			ty=prevbox.y; 
			var dist=toY-(prevbox.y+prevbox.height); //dist2p(toX,b,c,d);
			var h=dist+prevbox.height;
			if(h<1){h=1;}
			tw=prevbox.width;
			th=h;

	         }
        }
	if(scaleType.length==2){
		if(scaleType== 'nw'){
			trans_ShareScale=shareScale+","+shareScale; 
          
      			//var angle_diagonal=getAngle(prevbox.width,prevbox.height);
      			  var angle_diagonal=ang2v(prevbox.x,prevbox.y,prevbox.x+prevbox.width,prevbox.y+prevbox.height)
            
                        var ax= prevbox.x;
                        var ay= prevbox.y;
                        var bx= prevbox.x+prevbox.width; 
                        var by= prevbox.y+prevbox.height; 
                        
                        var cx= toX;
                        var cy= toY;
                        var dx= toX+10*Math.cos(angle_diagonal+(Math.PI/2)); 
                        var dy= toY+10*Math.sin(angle_diagonal+(Math.PI/2)); 
                      var section_a=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy); 
                 //document.forms[0].code.value=angle_diagonal* 180 / Math.PI;       

                var tx= section_a[1];
                var ty= section_a[2];
                
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= 0;
                        var by= section_a[2] ; 
                        
                        var cx=prevbox.x+prevbox.width; 
                        var cy= prevbox.y;

                        var dx= prevbox.x+prevbox.width;  
                        var dy= 0;
                        
                      
                var section_b=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);

                var distx=dist2p(section_a[1],section_a[2],section_b[1],section_b[2]);         
                
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= section_a[1] 
                        var by= 0; 
                        
                        var cx= prevbox.x; 
                        var cy= prevbox.y+prevbox.height; 

                        var dx= 0; 
                        var dy= prevbox.y+prevbox.height;
                        
                      
                var section_c=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);

                var disty=dist2p(section_a[1],section_a[2],section_c[1],section_c[2]);         
                
                  
 

                    
                        if(distx<1){distx=1;}    
			
         		
			if(disty<1){disty=1;}
                        //document.forms[0].code.value=distx+' '+disty;
			tw=distx;
			th=disty;

			
		}                  
		
	//////////////////// SE
		
           if( scaleType== 'se'){
			trans_ShareScale=shareScale+","+shareScale;   
			
	          
      			//var angle_diagonal=getAngle(prevbox.width,prevbox.height);
       			var angle_diagonal=ang2v(prevbox.x,prevbox.y,prevbox.x+prevbox.width,prevbox.y+prevbox.height)
		
			
			
                        var ax= prevbox.x;
                        var ay= prevbox.y;
                        var bx= prevbox.x+prevbox.width; 
                        var by= prevbox.y+prevbox.height; 
                        
                        var cx= toX;
                        var cy= toY;   
                        var dx= toX+10*Math.cos(angle_diagonal+(Math.PI/2)); 
                        var dy= toY+10*Math.sin(angle_diagonal+(Math.PI/2)); 
      
                var section_a=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);   
                
                                         

                //////////
                var tx= prevbox.x;
                var ty= prevbox.y;
                
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= 0;
                        var by= section_a[2] ; 
                        
                        var cx=prevbox.x; 
                        var cy= prevbox.y;

                        var dx= prevbox.x;  
                        var dy= 0;
                        
                      
                var section_b=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
               
               /////////////////
               
               
                var distx=dist2p(section_a[1],section_a[2],section_b[1],section_b[2]);         

             
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= section_a[1] 
                        var by= 0; 
                        
                        var cx= prevbox.x; 
                        var cy= prevbox.y; 

                        var dx=0;
                        var dy= prevbox.y;
                        
                      
                var section_c=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
               
               ///////////////
               
                var disty=dist2p(section_a[1],section_a[2],section_c[1],section_c[2]);         
                
   
                    
                        if(distx<1){distx=1;}    
			
         		
			if(disty<1){disty=1;}
                        
			tw=distx;
			th=disty;

			
		}

		if(scaleType== 'ne'){  
		        
			trans_ShareScale=shareScale+","+shareScale;   
			
	                var angle_diagonal=ang2v(prevbox.x,prevbox.y+prevbox.height,prevbox.x+prevbox.width,prevbox.y)
      			//var angle_diagonal=getAngle(prevbox.width,prevbox.height);
 		
			
				
			
                        var ax= prevbox.x;
                        var ay= prevbox.y+prevbox.height;
                        var bx= prevbox.x+prevbox.width; 
                        var by= prevbox.y;
                       
                        var cx= toX;
                        var cy= toY;   
                        var dx= toX+10*Math.cos(angle_diagonal+(Math.PI/2)); 
                        var dy= toY+10*Math.sin(angle_diagonal+(Math.PI/2)); 


                      //document.forms[0].code.value=angle_diagonal;

      
                var section_a=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);   
                
                                         

                //////////
                var tx= prevbox.x;
                var ty= section_a[2];
                
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= 0;
                        var by= section_a[2] ; 
                        
                        var cx=prevbox.x; 
                        var cy= prevbox.y;

                        var dx= prevbox.x;  
                        var dy= 0;
                        
                      
                var section_b=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
               
               /////////////////
               
               
                var distx=dist2p(section_a[1],section_a[2],section_b[1],section_b[2]);         

             
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= section_a[1]; 
                        var by= 0; 
                        
                        var cx= prevbox.x; 
                        var cy= prevbox.y+prevbox.height; 

                        var dx=0;
                        var dy= prevbox.y+prevbox.height;
                        
                      
                var section_c=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
               
               ///////////////
               
                var disty=dist2p(section_a[1],section_a[2],section_c[1],section_c[2]);         
                

                    
                        if(distx<1){distx=1;}    
			
         		
			if(disty<1){disty=1;}
                        //document.forms[0].code.value=distx+' '+disty;
			tw=distx;
			th=disty;
			
			
			
			
			
		}
		if(scaleType== 'sw'){
			trans_ShareScale=shareScale+","+shareScale;  
			
			
				
			
	                var angle_diagonal=ang2v(prevbox.x,prevbox.y+prevbox.height,prevbox.x+prevbox.width,prevbox.y)
      			//var angle_diagonal=getAngle(prevbox.width,prevbox.height);
 		
			
				
			
                        var ax= prevbox.x;
                        var ay= prevbox.y+prevbox.height;
                        var bx= prevbox.x+prevbox.width; 
                        var by= prevbox.y;
                       
                        var cx= toX;
                        var cy= toY;   
                        var dx= toX+10*Math.cos(angle_diagonal+(Math.PI/2)); 
                        var dy= toY+10*Math.sin(angle_diagonal+(Math.PI/2)); 


                      //document.forms[0].code.value=angle_diagonal;

      
                var section_a=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);   
                

                //////////
                var tx= section_a[1];
                var ty= prevbox.y;
                
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= 0;
                        var by= section_a[2] ; 
                        
                        var cx=prevbox.x+prevbox.width; 
                        var cy= prevbox.y+prevbox.height;

                        var dx= prevbox.x+prevbox.width;  
                        var dy= 0;
                        
                      
                var section_b=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
                var distx=dist2p(section_a[1],section_a[2],section_b[1],section_b[2]);         

               /////////////////             
                        var ax= section_a[1];
                        var ay= section_a[2];
                        var bx= section_a[1];
                        var by= 0; 
                          
                        var cx= prevbox.x; 
                        var cy= prevbox.y; 

                        var dx=0;
                        var dy= prevbox.y;
                        
                      
                var section_c=ntrsccn2rb(ax,ay,bx,by,cx,cy,dx,dy);
                  var disty=dist2p(section_a[1],section_a[2],section_c[1],section_c[2]);         
              ///////////////
                
   
                    
                        if(distx<1){distx=1;}    
			
         		
			if(disty<1){disty=1;}
                        //document.forms[0].code.value=distx+' '+disty;
			tw=distx;
			th=disty;
			
		}

	}  



 if(shape.tagName == 'rect')
  { 
    //alert(data[0]); 
    
    
      shape.style.left = tx + 'px';
      shape.style.top = ty + 'px'; 
      shape.style.height = th + 'px';
      shape.style.width = tw + 'px';
    
  }
   else 
 if(shape.tagName == 'text')
  {
    /*
    shape.setAttribute('x',tx);
    shape.setAttribute('y',ty);   
    shape.setAttribute('width', tw);     
    shape.setAttribute('height', th); 
    
    //previus.setAttribute('transform', "scale("+trans_ShareScale+")");
     shape.setAttribute('x', tx + 'px');
    shape.setAttribute('y', ty + 'px');

    shape.setAttribute('textLength', parseInt(Math.round(tw)));    
    
     */
  } 
   else 
 if(shape.tagName == 'oval')
  {
    //shape.getAttribute('transform)
   
      shape.style.left = tx + 'px';
      shape.style.top = ty + 'px'; 
      shape.style.height = th + 'px';
      shape.style.width = tw + 'px';
 
        
  }
   else 
 if(shape.tagName == 'line')
  { 
       shape.setAttribute('to',tx + 'px,' + ty + 'px'); 
           shape.setAttribute('from', tw + 'px,' + th + 'px');
   
         
  }
   else
 if (shape.tagName == 'polyline') 
  {
   
  }
   else 
 if (shape.tagName == 'image') 
  {   
     
      shape.style.left = tx + 'px';
      shape.style.top = ty + 'px'; 
      shape.style.height = th + 'px';
      shape.style.width = tw + 'px';
      
  }
   else 
 if (shape.tagName == 'shape')
  {     

      shape.style.left = tx + 'px';
      shape.style.top = ty + 'px'; 
      shape.style.height = th + 'px';
      shape.style.width = tw + 'px';

       //document.forms[0].code.value='';
       //shape.setAttribute('transform', "scale("+trans_ShareScale+")");

  }  
   	                             

 
         
         
};  



VMLRenderer.prototype.rotateShape = function(shape, previus,toX, toY) {
 
 
 
         //document.forms[0].code.value=$('xyinput').innerHTML;  
    //document.getElementById('richdraw').style.cursor='e-resize';
         var box = this.bounds(shape);
	 var prevbox=this.bounds(previus);
	var centerx= box.x+(box.width/2);
	var centery= box.y+(box.height/2); 
	var coord=this.editor.inputxy;

       var actual_angle=ang2v(centerx,centery,coord[0], coord[1]);
       
       if(xrot<toX) { rotatexxx+=1;}else{rotatexxx-=1;}
       xrot=toX;
       yrot=toY;  
       
	var xtr=0;
        var ytr=0;
                
        //var box= shape.getBBox();  
        var tr1x=  box.x;  
         var tr1y=  box.y;

 
 
    toX+=xtr;
        toY+=xtr;

      //var trax=parseFloat(toX-box.x);   var tray= parseFloat(toY-box.y);      
      var trax=parseFloat(box.x/2);   var tray= parseFloat(box.y/2); 
       var angler=Math.atan2(toX,toY);
         var angle=angler*180/Math.PI;  
         // var T = shape.getCTM(); 
          //var rotini=T.a*(180 / Math.PI);
           //var angle=rotini*180/Math.PI;
          //var rot_angle=actual_angle*180/Math.PI;  
          //document.forms[0].code.value=centerx+' '+centery+' '+coord[0]+' '+coord[1]+'____ '+rot_angle+' '+actual_angle*180/Math.PI;
          
          
         // matrix( a, b, c, d, e, f )
         // a c e
         // b d f
         // 0 0 1
         //a scale factor of 2, a rotation of 30 deg and a translation of (500,50)
         //T     1.732   -1   500     1   1.732   50     0   0   1
         //T      1  ad-bc      d  -c -de+cf   -b  a  be-df    0   0   1
         
         //shape.setAttribute('transform', "translate("+(-xshe)+","+(-yshe)+")");
 
         // shape.setAttribute("transform", "  matrix( a, b, c, d, e, f )");
          // shape.setAttribute('transform', "translate("+(box.x+(box.width/2))+","+(box.y+(box.height/2))+")  rotate("+rotatexxx+") ");
           //shape.setAttribute('transform', "translate("+(box.x+(box.width/2))+","+(box.y+(box.height/2))+") rotate("+rotatexxx+") translate("+(-box.x-(box.width/2))+","+(-box.y-(box.height/2))+") ");
         //shape.setAttribute('transform', "rotate("+rotatexxx+","+(box.x+(box.width/2))+","+(box.y+(box.height/2))+")");
         //shape.setAttribute('transform', "rotate("+rotatexxx+","+(prevbox.x+(prevbox.width/2))+","+(prevbox.y+(prevbox.height/2))+")");
         //shape.setAttribute('rotation', rot_angle);
         shape.setAttribute('rotation', angle);
         //(prevbox.x+(prevbox.width/2))+","+(prevbox.y+(prevbox.height/2))+")");
                          
 
 
    }

//////////////////////////////
/*H  = 0;
W  = 0;
LX = new Array();
S  = new Array();
i  = 0;
b  = true;

function SVG2VML(i){
	l = L[i];
	if(l.indexOf(" d=")>0){
		p = l.indexOf("fill:")+6;
		C = l.substring(p,p+7);
		p = l.indexOf(" d=")+4;
		q = l.lastIndexOf("z")-1;
		l = l.substring(p,q);
		l = l.replace(/M/g,"m");
		l = l.replace(/c/g,"v");
		l = l.replace(/l/g,"r");
		S = l.split(" ");
		l="";
		for(var j in S){
			c = S[j];
			p = c.substring(0,1);
			d = p>"9"?p:"";
			n = Math.round(c.substring(d!="") * 100);
			l+= (d+n+" ");
		}
		LX[i] = l;
		code = '<v:shape coordsize="'+(W*100)+','+(H*100)+'" class=vml strokeweight="2" strokecolor="'+C+'" filled="false" fillcolor = "'+C+'"/>';
		VML.insertAdjacentHTML("beforeEnd",code);
	} else {
		L[i] = LX[i] = ""
		VML.insertAdjacentHTML("beforeEnd","<span></span>");
	}
}
*/
//http://msdn2.microsoft.com/en-us/library/bb263897(VS.85).aspx
//http://www.w3.org/TR/NOTE-VML
//http://trac.openlayers.org/changeset/5285
//http://vectorconverter.sourceforge.net/index.html
//http://www.dhteumeuleu.com/colorsyntax/viewJS.php?src=svg2vml1.html


VMLRenderer.prototype.getshapes = function(){
return this.container.childNodes;
}


 /*JS File: ../js/drawing/wrapper_core.js*/ 


 /**
 * @author antimatter15
 */

Ax.loadShapes = function(shapes, noattachlistener, instance){ //instance; probably need a better name for this. but its the richdraw/onlypaths/viewer/etc reference. 
    if (typeof shapes == "string") { //try un-scrabling this!
        shapes = Ext.util.JSON.decode(shapes);
    }else if(typeof shapes == "undefined"){
		return;
	}
	for (var i = 0; i < shapes.length; i++) {
		Ax.loadShape(shapes[i], noattachlistener, instance);
	}
}

Ax.loadShape = function(shape, noattachlistener, instance){
	  var newshape  = ((instance)?instance:Ax.canvas).renderer.create(shape.type, //Shape
	  (shape.fillColor)?shape.fillColor:("#"+Ax.Color.fill), 
	  (shape.lineColor)?shape.lineColor:("#"+Ax.Color.line), 
	  (shape.fillOpac)?shape.fillOpac:1,
	  (shape.lineOpac)?shape.lineOpac:1, 
	  (shape.lineWidth)?shape.lineWidth:Ax.Color.width, 
	  (shape.left)?shape.left:100,
	  (shape.top)?shape.top:100, 
	  (shape.width)?shape.width:100,
	  (shape.height)?shape.height:100,
	  (shape.text)?shape.text:'',
	  (shape.textSize)?shape.textSize:19,
	  (shape.textFamily)?shape.textFamily:'Arial',
	  (shape.href)?shape.href:'', 
	  (shape.points)?shape.points:'', 
	  (shape.transform)?shape.transform:'',
	  (shape.parent)?shape.parent:''); 
 
    newshape.id = (shape.id) ? shape.id : createUUID()
    
    if (!noattachlistener) {
        Ext.get(newshape).on("mousedown", Ax.canvas.onHit, Ax.canvas);
    }
}

Ax.dumpshape = function(shape){
    if (!shape.getAttribute("transform")) {
		try {
        	var box = shape.getBBox()
        	shape.setAttributeNS(null, 'transform', 'rotate(0, ' + (box.x + (box.width / 2)) + ', ' + (box.y + (box.height / 2)) + ')');
    	}catch(err){
			//ZOMG! WTF? LOL!
		}
	}
    return Ax.canvas.info(shape)
}

Ax.dumpshapes_core = function(){
    var rawshapes = Ax.canvas.getshapes()
    var newshapes = [];
    for (var i = 0; i < rawshapes.length; i++) {
        if (rawshapes[i].id != "tracker") {
            newshapes.push(Ax.dumpshape(rawshapes[i]));
        }
    }
	return newshapes
}

Ax.dumpshapes = function(format){
    if (format == "json") {
        return Ext.util.JSON.encode(Ax.dumpshapes_core())
    }
    else {
        return Ax.dumpshapes_core();
    }
}



 /*JS File: ../js/drawing/op_wrapper.js*/ 


 /**
* Heh. This file provides wrappers for OnlyPaths. really quite simple really
* donno if i'll even use this. it'll probably be filled with hacks and other crap
* and there'll be probably more globals declared here than anywhere else... combined
*/

Ax.canvasWidth=480;
Ax.canvasHeight=272; 

/*
There actually is a story behind me choosing 480x272...
i could explain this in a simple way, but i don't want to because it won't help me
get out of that dreaded lowest-documented 10% on ohloh. so simply, this project got
started in about early 2007. That was when I was part of a Sony Playstation Portable
user community. and 480x272 was the PSP's resolution... so why not? and anyway, now
i have an iphone (which is awesome btw) and I mgiht change the default size to that..
though there is one slight problem..... i have no frigging idea what that is. :(
*/

function $(e){//this is a little hack since OnlyPaths used to be based off of Richdraw
  //which used prototype, and now this ext port is still haunted by that non-namespaced
  //prototypednessity... well anywhoo, this dollar sign makes the application seem worth
  //more.... so what bad could that do?
  return document.getElementById(e);
}//pwahappydoo. who cares. i'm bored. crap. poo. wee. doo. poo. moo. woot

clockdata = function(){};

  
Ax.onlypaths = {
  version: "Symply Web 0.1.03 Modified"
}

var zoominit, centerZoomx, centerZoomy;
var selectmode=''; //I have a feeling these comments aren't helping anyone
var data_path_close = false;


Ax.canvasSize_core = function(){ //this function really does nothing.
	zoominit='0 0 '+Ax.canvasWidth+' '+Ax.canvasHeight; //some OnlyPaths stuffs
	centerZoomx=Math.round(Ax.canvasWidth/2); //some OnlyPaths stuffs
	centerZoomy=Math.round(Ax.canvasHeight/2); //some OnlyPaths stuffs
}

Ax.canvasSize_core(); //set the stuffs

Ax.canvasSize = function(){
	Ax.canvasSize_core(); //doo the important things
	

	//refresh the canvaseses
	try{
		Ax.selectFrame(1, Ax.tcurrent.layer)
		Ax.reloadCanvas_core();
	}catch(err){}
		
	try{
		Ax.init_preview()
	}catch(err){}

}


Ax.drawinit_core = function(){
  var renderer = null;
  if(Ext.isIE == true){
    renderer = new VMLRenderer();
  }else{
    renderer = new SVGRenderer();
  }
  Ax.canvas = new RichDrawEditor($("drawcanvas"), renderer);
  Ax.canvas.onInputXY = Ax.setDrawXY;
  Ax.canvas.actualStyle = function(){}; //this is a hack so it doesn't replace some stuff that i'm about to set now
  
  
  Ax.canvas.textMessaje = "Ajax Animator"
  Ax.canvas.textSize = 19;
  Ax.canvas.fontFamily = "Arial";
  Ax.canvas.imageHref = "http://osflash.org/_media/ajaxanimator.png?w=&h=&cache=cache"
  
  
  Ax.canvas.onselect  = Ax.loadcolors;
  Ext.get(Ax.canvas.container.parentNode).on("mouseup",function(){
    setTimeout(function(){Ax.autodiff();return true},10);
  })
  Ax.Color.update = Ax.updatecolors;
  Ax.updatecolors();
}

Ax.drawinit = function(){
  $("drawcanvas").innerHTML = "";
  $("drawcanvas").style.height = Ax.canvasHeight+"px";
  $("drawcanvas").style.width = Ax.canvasWidth+"px"

  if(Ext.isIE==true){ //yes. i know. browser sniffing is bad
    $("drawcanvas").style.position = "absolute";
    $("drawcanvas").style.left = "5%";
  }

  //Ax.msg("W00t!","you enabled the drawing component: OnlyPaths!!!! NOw you can start drawing and doing stuff that actually matters");

  Ax.drawinit_core()

  Ax.setTool('rect');
}

Ax.loadcolors = function(){
  Ax.setColors({
    lw: Ax.canvas.queryCommand('linewidth'),
    lc: Ax.canvas.queryCommand('linecolor').replace("#",""),
    fc: Ax.canvas.queryCommand('fillcolor').replace("#","")
  })
}

Ax.updatecolors = function(){
  Ax.canvas.editCommand('fillcolor', '#'+Ax.Color.fill);
  Ax.canvas.editCommand('linecolor', '#'+Ax.Color.line);
  Ax.canvas.editCommand('linewidth', Ax.Color.width.toString()+'px');   
  Ax.canvas.setGrid(Ax.Color.grid, Ax.Color.grid);
  Ax.autodiff();
}



Ax.reloadCanvas = function(){//now a very very robust function, should be able to recover from most errors, even most really random ones
  var init = (new Date()).getTime(),
  log = [],
  backup = [],
  mode = "select";
  try{
    mode = Ax.canvas.queryCommand("mode")
  }catch(err){log.push("FO1: "+err)}
  try{
  backup = Ax.dumpshapes()
  }catch(err){log.push("FO2: "+err);
  Ax.msg("Sorry","OnlyPaths has encountered a critical error. The canvas data may be unrecoverable.")}
  try{
  Ax.canvas.renderer.removeAll()
  }catch(err){log.push("FO3: "+err)}
  try{
  Ax.canvas.container.innerHTML = null
  }catch(err){log.push("FO4: "+err)}
  try{
  Ax.canvas = null
  }catch(err){log.push("FO5: "+err)}
  try{
  Ax.drawinit_core();
  }catch(err){log.push("FO6: "+err);console.log(err)}
  try{
  Ax.setTool(mode)
  }catch(err){log.push("FO7: "+err);Ax.msg("Sorry","Recovery might have failed. You may have to restart the application.")}
  try{
  Ax.loadShapes(backup)
  }catch(err){log.push("FO8: "+err);Ax.msg("Sorry","Recovery might have failed. You may have to restart the application.")}
  
  var time = (new Date()).getTime()-init

  if(log.length > 0){
    Ax.msg("Problems while restarting:", log.join("<br>"));
    Ax.msg("Attempt information","Canvas reinitialization time was "+time+"ms");
  }else{
    Ax.msg("Canvas Reloaded","This should have resolved most canvas-related issues. Canvas reinitialized in "+time+"ms");
  }
}


Ax.reloadCanvas_core = function(){
	//hey, I figure we need something faster and silenter than the debugging rekovry one
	//reKovery iK aweKome Kright? Kno, Kis is Knot a KDE ProKegt
	try{
		var backup = Ax.dumpshapes();
		Ax.canvas.renderer.removeAll(); //die
		Ax.canvas.container.innerHTML = null;//die
	 	Ax.canvas = null;//die again
		Ax.drawinit(); //here does the resizing
		Ax.loadShapes(backup);
	}catch(err){
		return false;
	}
	return true;
}

Ax.setTool = function(tool){
 
 
for(var tool_id in Ax.toolConfig){
Ax.viewport.findById("tool_"+tool_id).unselect()
}

//report usage statistics
/* take out that first "/" to disable
Ax.gs(({select:10,rect:11,roundrect:12,
ellipse:13,line:14,path:15,
controlpath:16,text:17,image:18,
shape:19,reset:20,"delete":21})[tool])
/**///*//for my text editor (notepad2, though i normally use notepad++ which doesn't face this issue)


if(tool == "controlpath"){
	Ax.msg("Warning","The Polygon tool is unstable and may cause issues and possibly may corrupt the entire animation.")
	selectmode = "controlpath"
}else if(tool == "path"){
	selectmode = "";
}



try {
	
	switch(tool){
		case "text":
		Ax.setPropertiesMode("Text",1)
		break;
		case "image":
		Ax.setPropertiesMode("Image",2)
		break;
		default:
		Ax.setPropertiesMode("Animation",0)
		break;
	}
	
	switch (tool) {
		case "delete":
			Ax.canvas.deleteSelection();
			(function(){
				Ax.viewport.findById("tool_" + tool).unselect();
				Ax.setTool("select")
			}).defer(200);
			break;
		case "reset":
			Ax.canvas.renderer.removeAll();
			
			(function(){
				Ax.viewport.findById("tool_" + tool).unselect();
				Ax.setTool("select")
			}).defer(200);
			break;
		case "shape":
			Ax.canvas.unselect();
			(function(){
				Ax.viewport.findById("tool_" + tool).unselect();
				Ax.setTool("select")
			}).defer(200);
			Ax.viewport.findById("library").expand();
			break;
		default:
			
			Ax.canvas.unselect();
			Ax.viewport.findById("tool_" + tool).select(true);
			Ax.canvas.editCommand('mode', tool);
			break;
	}
} 
catch (err) {
	Ax.toastMsg("Error","OnlyPaths, the drawing component of the Ajax Animator has crashed. To attempt to fix this, go to <b>Tools->Recovery->Reload Canvas</b>.")
}
  
  setTimeout(function(){Ax.autodiff();return true},10); //do some magickal saving.
}




 /*JS File: ../js/drawing/view_wrapper.js*/ 


 
/* some analogies for engresh!
 * 
 */
 //  wrapper : onlypaths :: view_wrapper : op_view

//so basically this is a set of wrapper stuff for op_view, or RichDrawViewer. Its a simplified version of onlypaths that has no dependencies
//for sole drawing of crap

//the indentation here is screwed cause im using a diffrent ide to make this.

/*
 okay, this file has prettymuch been diversified from a simple preview.js stuff
 to a flexible implementation that probably should work standalone.
 */
//a little hack to get IE to work
/*
 Meh. This one is from Mozilla, but its too big so i'm gonna steal from elsewhere
 if (!Array.prototype.indexOf){
 Array.prototype.indexOf = function(elt , from){
 var len = this.length;
 var from = Number(arguments[1]) || 0;
 from = (from < 0)
 ? Math.ceil(from)
 : Math.floor(from);
 if (from < 0) from += len;
 for (; from < len; from++) {
 if (from in this && this[from] === elt) return from;
 }
 return -1;
 };
 }
 */
//from http://snippets.dzone.com/posts/show/2437
//modified to work with my compilier
//*
if (![].indexOf) {
    Array.prototype.indexOf = function(v){
        for (var i = this.length; i-- && this[i] != v;) {
        }
        return i;
    }
}
//*/

Ax.framerate = 12;
//*


Ax.init_view = function(element, width, height){
    element.innerHTML = ""; //I wish I could make a witty comment here. Something like those guys at SMF
	//http://www.simplemachines.org/community/index.php?topic=243341.0
    element.style.overflow = "hidden";
    
	element.style.height = (height?height:272) + "px";
    element.style.width = (width?width:480) + "px";
	
	Ax.canvasSize_core();
	var zoomcache = zoominit;
	zoominit = '0 0 '+(width?width:480)+' '+(height?height:272);
	
    var output =  Ax.init_view_core(element); //stupid onlypaths hacks!
	zoominit = zoomcache;
	return output;
}

Ax.init_view_core = function(element){
    if (Ext.isIE == true) {
        var renderer = new VMLRenderer();
    }
    else {
        var renderer = new SVGRenderer();
    }
    return new RichDrawViewer(element, renderer);
}


Ax.viewer_load_frame = function(frame, layers, canvas, tweenfunc){
    canvas.renderer.removeAll(); //clear viewerstuff
    for (var layer in layers) {
        //alert([1, 2, 3, 4, 5].indexOf(2))
        if (layers[layer].keyframes.indexOf(frame) != -1) {
            Ax.loadShapes(layers[layer].src[frame], true, canvas);
        }
        else 
            if (Ax.largest_nonempty(frame, layer, layers) && Ax.smallest_nonempty(frame, layer, layers)) {
                Ax.loadShapes(((tweenfunc) ? tweenfunc : Ax.getSFTween)(frame, Ax.largest_nonempty(frame, layer, layers), Ax.smallest_nonempty(frame, layer, layers), layer, layers[layer].src), true, canvas);
            }
            else 
                if (Ax.largest_nonempty(frame, layer, layers)) {
                    //console.log("Blank Frame")
                    Ax.loadShapes(layers[layer].src[Ax.largest_nonempty(frame, layer, layers)], true, canvas);
                }
                else {
               	     //console.log("blank frame")
                }
    }
    if (frame >= Ax.count_frames(layers)) {
        return 0;
    }
    return frame
}



//*/



 /*JS File: ../js/ui/statusbar.js*/ 


 //if i ever look at this file again: http://extjs.com/deploy/dev/docs/?class=Ext.menu.Adapter


Ext.onReady(function(){

var xy = new Ext.Toolbar.TextItem('0, 0');

Ax.setDrawXY = function(x,y){
    //a little easter egg, sorta like that SMF one....
    //.... just.... this'll probably kill performance....
    //hmm... i wonder if x.toString()+y.toString() is faster than [x,y].join("")
    //lemme see......
    //if([x,y].join("") == "1337"){
    if(x.toString()+y.toString() == "1337"){
    //too bad you'll never be able to know if it's [1,337],[13,37], or [133,7]
    //ooh.... x.toString()+y.toString() is 3x faster taking roughly 3 seconds
    //to hapen one million times, versus [x,y].join("") taking 9 seconds
        Ext.fly(xy.getEl()).update("leet");
    }else{
        Ext.fly(xy.getEl()).update(x.toString()+", "+y.toString());
    }
}

var previewstatus = new Ext.Toolbar.TextItem('0');
Ax.setPreviewStatus = function(text){
	Ext.fly(previewstatus.getEl()).update(text);
}


Ax.CanvasStatusbar = ({
    defaultText: 'Ready',
    defaultIconCls: '',
    items: [
     xy,"-",
	{
		iconCls: "x-tbar-page-first",
		tooltip: "Go to first frame",
    handler: function(){Ax.controls.first()}
	},{
        iconCls: "x-tbar-page-prev",
		tooltip: "Go to previous frame",
    handler: function(){Ax.controls.previous()}
    },
	"-",
	"Frame <input type=\"text\" id=\"cbframe\" style=\"width: 30px\" value=\"0\"> of ?",
	"-",
	{
		iconCls: "x-tbar-page-next",
		tooltip: "Go to next frame",
    handler: function(){Ax.controls.next()}
	},{
		iconCls: "x-tbar-page-last",
		tooltip: "Go to last frame",
    handler: function(){Ax.controls.last()}
	},'-',{
	text: "More",
	menu: [{text : "Preview", handler: function(){Ax.controls.play()}}]
	}, " "]
})


Ax.PreviewStatusbar = ({
    defaultText: 'Ready',
    defaultIconCls: '',
    items: [{text: "Performance: ", tooltip: "The amount of time it takes to render a frame",
            handler: function(){
              Ext.MessageBox.alert("About Performance","Lower the better, It largely depends"+
                                   " on the framerate, speed on your computer, the number of t"+
                                   "imes the animation was played, browser and the number and "+
                                   "types of shapes.")
            }
            },
            previewstatus,
	'-',
{
		iconCls: "x-tbar-page-first",
		tooltip: "Go to first frame",
    handler: function(){Ax.controls.first()}
	},{
        iconCls: "x-tbar-page-prev",
		tooltip: "Go to previous frame",
    handler: function(){Ax.controls.previous()}
    },
	"-",
	"Frame <input type=\"text\" id=\"pbframe\" style=\"width: 30px\" value=\"0\"> of ?",
	"-",
	{
		iconCls: "x-tbar-page-next",
		tooltip: "Go to next frame",
    handler: function(){Ax.controls.next()}
	},{
		iconCls: "x-tbar-page-last",
		tooltip: "Go to last frame",
    handler: function(){Ax.controls.last()}
	},
	'-', {
	text: "More",
	menu: [{text : "Canvas", handler: function(){Ax.viewport.findById("maintabpanel").activate(0)}}]
	}," "]
})

})

//Simple Status Function

Ax.setStatus = function(status){
//if(!status.anim){status.anim=false}; //a little hack to stop those this.statusEl is undefined errors
//oh. crap. that doesn't work :(

Ax.viewport.findById("canvas").getBottomToolbar().setStatus(status)
Ax.viewport.findById("preview").getBottomToolbar().setStatus(status)
}
Ax.showBusy = function(){
Ax.viewport.findById("canvas").getBottomToolbar().showBusy()
Ax.viewport.findById("preview").getBottomToolbar().showBusy()
}




 /*JS File: ../js/ui/history.js*/ 


 /*
 Grid for History panel
 */
Ax.history_store = [{}];
Ax.history_cursor = 0;

Ax.history_add = function(summary){
    Ax.history_store.push(Ext.ux.clone(Ax.export_animation()));
    //console.log(Ax.canvas.getshapes())
    Ax.viewport.findById("history").getStore().add(new Ext.data.Record({
        id: Ax.history_store.length - 1,
        type: (summary) ? summary : "Edit" //I fear this is not cross-platform
    }))
    Ax.history_cursor = Ax.history_store.length - 1
    return Ax.history_store.length - 1
}

Ax.history_undo = function(){
    Ax.history_revert(Ax.history_cursor - 1);
}


Ax.history_redo = function(){
    Ax.history_revert(Ax.history_cursor + 1);
}


Ax.history_clear = function(){
    Ax.history_store = [{}];//blah!
    var history_items = Ax.viewport.findById("history").getStore().getRange(1);
    for (var i = 0; i < history_items.length; i++) {
        Ax.viewport.findById("history").getStore().remove(history_items[i])
    }
}

Ax.history_revert = function(revision){
    if (revision < Ax.history_store.length && revision > 0) { //check if valid
        //poop
        //console.log(revision);
        Ax.history_cursor = revision;
        Ax.import_animation(Ext.ux.clone(Ax.history_store[revision]))
    }
}

Ax.History = Ext.extend(Ext.grid.GridPanel, {
    initComponent: function(){
        Ext.apply(this, {
            id: "history",
            store: new Ext.data.SimpleStore({
                fields: [{
                    name: 'id',
                    type: 'float'
                }, {
                    name: 'type'
                }],
                data: [[0, "Nothing"]]
            }),
            sm: new Ext.grid.RowSelectionModel({
                singleSelect: true
            }),
            
            columns: [{
                id: 'id',
                header: "#",
                width: 20,
                sortable: true,
                dataIndex: 'id'
            }, {
                header: "Type",
                sortable: true,
                dataIndex: 'type'
            }],
            viewConfig: {
                forceFit: true,
                autoFill: true
            },
            border: false
        }); // eo apply
        this.on("rowclick", function(grid, rowindex, event){
            grid.getSelectionModel().clearSelections()
            if (rowindex == 0) {
                return Ax.msg("Are You Sure?", "If you really want to, the <b>File->New</b> button is there for you.")
            }
            Ax.history_revert(rowindex);
        })
        // call parent
        Ax.History.superclass.initComponent.apply(this, arguments);
    } // eo function initComponent
});

Ext.reg('history', Ax.History);



 /*JS File: ../js/ui/clipboard.js*/ 


 /*
 Grid for Clipboard panel
 */
Ax.clipboard_store = [[]];

Ax.clipboard_copy = function(){
    if (!Ax.canvas.selected) {
        return Ax.msg("Error", "Nothing's selected...")
    }
    Ax.clipboard_store.push(Ax.canvas.renderer.copy(Ax.canvas.selected));
    Ax.viewport.findById("clipboard").getStore().add(new Ext.data.Record({
        id: Ax.clipboard_store.length - 1,
        type: Ax.toolConfig[Ax.clipboard_store[Ax.clipboard_store.length - 1].nodeName][2] //I fear this is not cross-platform
    }))
    return Ax.clipboard_store.length - 1
}

Ax.clipboard_cut = function(){
    Ax.clipboard_copy();
    Ax.setTool("delete")
}

Ax.clipboard_clear = function(){
    Ax.clipboard_store = [[]];//blah!
    var clipboard_items = Ax.viewport.findById("clipboard").getStore().getRange(1);
    for (var i = 0; i < clipboard_items.length; i++) {
        Ax.viewport.findById("clipboard").getStore().remove(clipboard_items[i])
    }
}

Ax.clipboard_paste = function(index){
    if (!index) {
        index = Ax.clipboard_store.length - 1
    }
    Ext.get(Ax.canvas.renderer.paste(Ax.clipboard_store[index].cloneNode(true))).on("mousedown", Ax.canvas.onHit, Ax.canvas);
    Ax.autodiff();
}

Ax.Clipboard = Ext.extend(Ext.grid.GridPanel, {
    initComponent: function(){
        Ext.apply(this, {
            id: "clipboard",
            store: new Ext.data.SimpleStore({
                fields: [{
                    name: 'id',
                    type: 'float'
                }, {
                    name: 'type'
                }],
                data: [[0, "Nothing"]]
            }),
            sm: new Ext.grid.RowSelectionModel({
                singleSelect: true
            }),
            
            columns: [{
                id: 'id',
                header: "#",
                width: 20,
                sortable: true,
                dataIndex: 'id'
            }, {
                header: "Type",
                sortable: true,
                dataIndex: 'type'
            }],
            viewConfig: {
                forceFit: true,
                autoFill: true
            },
            border: false
        }); // eo apply
        this.on("rowclick", function(grid, rowindex, event){
			grid.getSelectionModel().clearSelections()
            if (rowindex == 0) {
                return Ax.msg("Meh.", "What? You expect something to happen?")
            }
            Ax.clipboard_paste(rowindex);
            
        })
        
        // call parent
        Ax.Clipboard.superclass.initComponent.apply(this, arguments);
    } // eo function initComponent
});

Ext.reg('clipboard', Ax.Clipboard);



 /*JS File: ../js/ui/library.js*/ 


 /*
 Tree View for Library
 */
Ax.Library = Ext.extend(Ext.tree.TreePanel, {
    initComponent: function(){
        Ext.apply(this, {
            xtype: "treepanel",
            useArrows: true,
            autoScroll: true,
            animate: true,
            enableDD: false,
            containerScroll: true,
            root: new Ext.tree.AsyncTreeNode({
                text: 'Shared',
                expanded: true,
                draggable: false,
                id: '.'
            }),
            loader: new Ext.tree.TreeLoader({
                dataUrl: (window.location.protocol=="file:")?null:Ax.files.library //so you can use it as a file:// in fx3
            }),
            dropConfig: {
                appendOnly: true
            },
            border: false
        
        });
		this.on("click", function(node){
                    if (node.childrenRendered == false) {
                        Ext.Ajax.request({
                            url: Ax.files.libraryitem + node.id,
                            success: function(e){
								Ax.loadShapes(e.responseText)
                            }
                        })
                    }
                })
			
        Ax.Library.superclass.initComponent.apply(this, arguments);

	}
    
});

Ext.reg("library", Ax.Library);

                
                



 /*JS File: ../js/ui/login.js*/ 


 Ax.LoginForm = Ext.extend(Ext.Panel,{
initComponent: function(){
Ext.apply(this,{
layout:"accordion",
layoutConfig:{
  activeOnTop:false,
  animate:true,
  autoWidth:true,
  collapseFirst:false,
  fill:true,
  hideCollapseTool:false,
  titleCollapse:true
},
border: false,
items:[{
    title:"Login",
    layout: "fit",
    iconCls: "tb_login",
    //autoHeight:true,
    border: false,
    items:[{
        xtype:"form",
        labelWidth:30,
        border:false,
        items:[{
            xtype:"textfield",
            fieldLabel:"User",
            name:"textvalue",
            width:90
          },{
            xtype:"textfield",
            fieldLabel:"Pass",
            name:"textvalue",
            width:90
          },{
            xtype:"button",
            text:"Login"
          }]
      }]
  },{
    title:"Register",
    //autoHeight:true,
    layout: "fit",
    iconCls: "tb_register",
    border: false,
    items:[{
        xtype:"form",
        labelWidth:30,
        border:false,
        items:[{
            xtype:"textfield",
            fieldLabel:"User",
            name:"textvalue",
            width:90
          },{
            xtype:"textfield",
            fieldLabel:"Pass",
            name:"textvalue",
            width:90
          },{
            xtype:"textfield",
            fieldLabel:"Pass",
            name:"textvalue",
            width:90
          },{
            xtype:"button",
            text:"Create Account"
          }]
      }]
  }]
})

Ax.LoginForm.superclass.initComponent.apply(this, arguments);
}
})
Ext.reg("loginform",Ax.LoginForm)


 /*JS File: ../js/ui/toolbar.js*/ 


 Ax.MainToolbar = [
  {text:"File", menu: [
  {text: "New", iconCls: "tb_new", handler: function(){Ax.new_animation()}},
  {text: "Open", iconCls: "tb_open", menu: [
    {text: "From Webserver", iconCls: "tb_server", disabled: true},
	{text: "From Computer", iconCls: "tb_comp", handler: function(){Ax.open.file()}},
    {text: "From Text", iconCls: "tb_text", handler: function(){Ax.open.text()}},
	{text: "From URL", iconCls: "tb_url", handler: function(){Ax.open.url()}}
	]},
	
  {text: "Save", iconCls: "tb_save",menu: [
    {text: "To Webserver", iconCls: "tb_server", disabled: true},
    {text: "To Computer", iconCls: "tb_comp", handler: function(){Ax.save.computer()}},
    {text: "To Text", iconCls: "tb_text", handler: function(){Ax.save.text()}}
  ]},
  "-",
  {text: "Publish", iconCls: "tb_publish", menu: [
  	{text: "Flash", iconCls: "tb_flash", handler: function(){Ax.ex.swf.save()}},
	{text: "Processing", iconCls: "tb_processing", handler: function(){Ax.ex.processing.save()}},
	{text: "Silverlight", iconCls: "tb_silverlight", handler: function(){Ax.ex.silverlight.save()}},
	{text: "JavaFX", iconCls: "tb_javafx", handler: function(){Ax.ex.javafx.save()}},
	{text: "Animated GIF", iconCls: "tb_image", handler: function(){Ax.ex.gif.save()}}
  ]},
  {text: "Offline", iconCls: "tb_offline", handler: function(){Ax.offline()}}
]},
{text:"Edit", menu: [
  {text: "Undo", iconCls: "tb_undo", handler: function(){Ax.history_undo()}},
  {text: "Redo", iconCls: "tb_redo", handler: function(){Ax.history_redo()}},
  "-", //seperator, i hope when i run this through a formatter the comments arent stripped.
  {text: "Cut", iconCls: "tb_cut", handler: function(){Ax.clipboard_cut()}}, //woah! look! the whole thing is progressively 2 characters more!
  {text: "Copy", iconCls: "tb_copy", handler: function(){Ax.clipboard_copy()}}, //that's freaking cool!
  {text: "Paste", iconCls: "tb_paste", handler: function(){Ax.clipboard_paste()}}, //awesomeness
  {text: "Delete", iconCls: "tb_delete", handler: function(){Ax.setTool("delete")}} //wootyness
  //i wonder what woudl be here? "explode"?
]},
{text:"View", menu: [
  //Add some check item stuff for visible panels

  {text: "Animation", iconCls: "tb_animation", handler: function(){Ax.controls.play()}},
  {text: "Information", iconCls: "tb_about", handler: function(){Ax.animationinfo()}},
  {text: "Theme", iconCls: "tb_theme", menu: new Ext.ux.ThemeMenu},
  "-",
  {text: "Timeline", xtype: "checkitem", checked: true, handler: function(item){Ax.timeline_setcollapse(item)}},
  {text: "Tools", xtype: "checkitem", checked: true, handler: function(item){Ax.tools_setcollapse(item)}},
  {text: "Misc", xtype: "checkitem", checked: true, handler: function(item){Ax.misc_setcollapse(item)}},
  {text: "Properties", xtype: "checkitem", checked: true, handler: function(item){Ax.properties_setcollapse(item)}}
]},
{text:"Tools", menu: [
  //{text: "Color Picker", iconCls: "tb_color"},
  {text: "Drawing", iconCls: "tb_tools", menu: [{text: "Select", iconCls: "tx_select", handler: function(){Ax.setTool("select")}},
                                                {text: "Rectangle", iconCls: "tx_rectangle", handler: function(){Ax.setTool("rect")}},
                                                {text: "Rounded Rectangle", iconCls: "tx_roundrect", handler: function(){Ax.setTool("roundrect")}},
                                                {text: "Ellipse/Circle", iconCls: "tx_circle", handler: function(){Ax.setTool("ellipse")}},
                                                {text: "Line", iconCls: "tx_line", handler: function(){Ax.setTool("line")}},
                                                {text: "Freeform Path", iconCls: "tx_path", handler: function(){Ax.setTool("path")}},
                                                {text: "Polygon", iconCls: "tx_polygon", handler: function(){Ax.setTool("polygon")}},
                                                {text: "Text", iconCls: "tx_text", handler: function(){Ax.setTool("text")}},
                                                {text: "Image", iconCls: "tx_image", handler: function(){Ax.setTool("image")}}]},
  {text: "Recovery", iconCls: "tb_shield", menu: [
                            {text: "Reload Canvas", iconCls: "tb_recover_canvas", handler: function(){Ax.reloadCanvas()}},
                            {text: "Reload Animation", iconCls: "tb_recover_animation", handler: function(){Ax.reload_animation()}},
                            {text: "Reload Application", iconCls: "tb_recover_application", handler: function(){window.location.reload(true)}}
  ]},
  {text: "Script Executor", iconCls: "tb_script", handler: function(){Ax.macroExec()}},
  {text: "Plugin Settings", iconCls: "tb_plugin_conf", handler: function(){Ax.plugins_unavailable()}}
]},
{text:"Timeline", menu: [
  {text: "New Layer",iconCls: "tb_newlayer", handler: function(){Ax.addLayer()}},
  {text: "Insert Frame", iconCls: "tb_insertframe", handler: function(){Ax.insertFrame()}},
  {text: "To Keyframe",iconCls: "tb_addkeyframe", handler: function(){Ax.toKeyframe()}},
  {text: "Clear Frame",iconCls: "tb_clearframe", handler: function(){Ax.setTool("reset")}},
  "-", //organized from stuff you might actually use, compared to stuff you have a slight change if any of using
  {text: "Reload Data", iconCls: "tb_reload", handler: function(){Ax.reloadTimeline()}},
  {text: "Purge Empty", iconCls: "tb_purge_empty", handler: function(){Ax.timelineCleanup()}}
]},
{text:"Animation", menu: [
  {text: "Canvas Mode", disabled: true}, //this needs serious work.
  {text: "Play", iconCls: "tb_play", handler: function(){Ax.controls.play()}},
  {text: "Pause", iconCls: "tb_pause", handler: function(){Ax.controls.pause()}},
  {text: "Next Frame", iconCls: "tb_nf", handler: function(){Ax.controls.next()}},
  {text: "Previous Frame", iconCls: "tb_pf", handler: function(){Ax.controls.previous()}},
  {text: "Last Frame", iconCls: "tb_last", handler: function(){Ax.controls.last()}},
  {text: "First Frame", iconCls: "tb_first", handler: function(){Ax.controls.first()}},
  "-", //not really related...
  {text: "Recalculate Tweens", iconCls: "tb_recalculate", handler: function(){}}
]},
{text:"Plugins", menu: [
  {text: "Add Plugins", iconCls: "tb_plugin_add", handler: function(){Ax.plugins_unavailable()}},
  "-", //split
  {text: "Explode",iconCls: "tb_plugin", handler: function(el){Ax.exec(el.initialConfig.text)}},
  {text: "Random Shape",iconCls: "tb_plugin", handler: function(el){Ax.exec(el.initialConfig.text)}}
]},
{text:"User", menu: [
  {text: "Login", iconCls: "tb_login", disabled: true},
  {text: "Logout", iconCls: "tb_logout", disabled: true},
  {text: "Profile", iconCls: "tb_profile", disabled: true},
  {text: "Browse Animations", iconCls: "tb_browse", handler: function(){Ax.showanimationbrowser()}}
]},
{text:"Help", menu: [
  {text: "About", iconCls: "tb_about", handler: function(){Ax.About()}},
  {text: "Key Shortcuts", iconCls: "tb_keyboard", handler: function(){Ax.keyGuide()}},
  {text: "Tip of the Day", iconCls: "tb_tip", handler: function(){Ax.showTips()}},
  {text: "Manual", iconCls: "tb_docs", handler: function(){Ax.loadManual()}},
  {text: "FAQ", iconCls: "tb_docs", handler: function(){Ax.loadFAQ()}},
  {text: "Bug Reports", iconCls: "tb_bug", handler: function(){Ax.BugReport()}},
  {text: "Comments", iconCls: "tb_comment", handler: function(){Ax.comment()}},
  {text: "Contribute", iconCls: "tb_donate", handler: function(){Ax.donate()}},
  {text: "Interactive Tutorials", iconCls: "tb_tutorial", menu: [
    {text: "Beginner's Tutorial", iconCls: "tb_info", handler: function(){Ax.tutorials_unavailable()}}
  ]}
  ]}
]


 /*JS File: ../js/ui/properties.js*/ 


 //Various forms defining properties
Ax.PropertiesPanel = Ext.extend(Ext.Panel, {
    initComponent: function(){
        Ext.apply(this, {
            border: false,
            id: "properties_form",
            layout: "card",
            activeItem: 0,
            items: [{////////////////////////////////////Animation//////////////////////////////////////
                layout: "column",
                defaults: {
                    width: 120
                },
                border: false,
                items: [{
                    layout: "form",
                    border: false,
                    items: [{
                        xtype: "numberfield",
                        fieldLabel: "Width",
                        name: "width",
						value: Ax.canvasWidth,
						listeners: {
							"change":function(field, value){
								if(value.length == 0){
									field.setValue(Ax.canvasWidth);
									value = field.getValue();
								}
								Ax.canvasWidth = value;
								Ax.canvasSize();
							}
						},
                        width: 60
                    }]
                }, {
                    layout: "form",
                    border: false,
                    items: [{
                        xtype: "numberfield",
                        fieldLabel: "Height",
                        name: "height",
						value: Ax.canvasHeight,
                        width: 60,
						listeners: {
							"change":function(field, value){
								if(value.length == 0){
									field.setValue(Ax.canvasHeight);
									value = field.getValue();
								}
								Ax.canvasHeight = value;
								Ax.canvasSize();
							}
						}
                    }]
                }, {
                    layout: "form",
                    border: false,
                    items: [{
                        xtype: "numberfield",
                        fieldLabel: "Framerate",
                        name: "framerate",
						value: Ax.framerate,
                        width: 60,
						listeners: {
							"change":function(field, value){
								if(value.length == 0){
									field.setValue(Ax.framerate);
									value = field.getValue();
								}
								Ax.framerate = value;
							
							}
						}
                    }]
                }]
            }, { ////////////////////////////////////////Textystuff////////////////////////////////////////////
                layout: "column",
                defaults: {
                    width: 120
                },
                border: false,
                items: [{
                    layout: "form",
                    border: false,
					width: 300,
                    items: [{
                        xtype: "textfield",
                        fieldLabel: "Text",
                        name: "text",
						value: "Ajax Animator",
                        width: 240,
						listeners: {
							"change":function(field, value){
								if(value.length == 0){
									field.setValue("Arr! You found an easter egg! (Tada!)")
									value = field.getValue();
								}
								Ax.canvas.textMessaje = value;
							}
						}
                    }]
                }, {
                    layout: "form",
                    border: false,
                    items: [{
                        xtype: "numberfield",
                        fieldLabel: "Font Size",
                        name: "fontsize",
						value: 19,
                        width: 60,
						listeners: {
							"change":function(field, value){
								if(value.length == 0){
									field.setValue(19);
									value = field.getValue();
								}
								Ax.canvas.textSize = value;
							
							}
						}
                    }]
                }]
            },{ ////////////////////////////////////////Imagoo////////////////////////////////////////////
                layout: "column",
                defaults: {
                    width: 120
                },
                border: false,
                items: [{
                    layout: "form",
                    border: false,
					width: 400,
                    items: [{
                        xtype: "textfield",
                        fieldLabel: "URL",
                        name: "url",
						value: "http://osflash.org/_media/ajaxanimator.png?w=&h=&cache=cache",
                        width: 340,
						listeners: {
							"change":function(field, value){
								if(value.length == 0){
									field.setValue(Ax.canvas.imageHref)
								}
								Ax.canvas.imageHref = value;
							}
						}
                    }]
                }]
            }]
        
        })
        Ax.PropertiesPanel.superclass.initComponent.apply(this, arguments);
    }
})

Ext.reg("properties", Ax.PropertiesPanel);

Ax.setPropertiesMode = function(mode,number){
    Ax.viewport.findById("properties").setTitle(Ax.viewport.findById("properties").title.split("-")[0] + "- " + mode);
	Ax.viewport.findById("properties_form").layout.setActiveItem(number)
}



 /*JS File: ../js/ui/panels/center.js*/ 


 Ax.LayoutCenterPanel = Ext.extend(Ext.Panel,{
initComponent: function(){
Ext.apply(this,{

    region:"center",
    //title:"Canvas",
    layout:"fit",
	//tbar: Ax.MainToolbar,
    border:false,
    items:[{
        xtype:"tabpanel",
		id: "maintabpanel",
        tabPosition:"bottom",
        border:false,
        activeTab:0,
        items:[{
            xtype:"panel",
			id: "canvas_tab",
            title:"Canvas",
			iconCls: "canvas_icon",
            layout:"fit",
			tabTip: "Draw and create your animations",
             border:false,
			listeners: {
				'activate' : function(){
					if(Ax.viewport && Ax.viewport.findById("toolbar")){
					Ax.viewport.findById("toolbar").getTopToolbar().items.item(5).menu.items.item(0).setText("Canvas Mode")
					}
					//Ax.gs(9)
				}
			},
			items: [{
			//region: "center",
			id: "canvas",
            xtype:"panel",
            title:"Canvas",
			bbar: new Ext.StatusBar(Ax.CanvasStatusbar),
			tools: [{id: "gear"},{id: "help", 
			qtip: "Select tools from the west panel and draw on the canvas with them."}],
			iconCls: "canvas_icon",			
            layout:"fit",
            
			tbar: [
     " Name: ",{xtype: "textfield",
       value: Ax.animation.name,
       listeners: {
        "change": function(field){Ax.setAnimationName(field.getValue())}
        }, width: 200}   ,{xtype: "tbfill"},{text:"Zoom"},
      {xtype: "slider", width: 120, maxValue: 300, value: 100, increment: 5,plugins: new Ext.ux.SliderTip({
      getText: function(slider){return String.format('Canvas Zoom: {0}%', slider.getValue())}
        })}],

			 html:"<div class=\"x-border-layout-ct canvas_container\">"+
       "<div id=\"drawcanvas\" class=\"canvas\">Loading...</div>"+
       "</div>",
			 border: true
			}]
          },{
            xtype:"panel",
            title:"Preview",
			id: "preview_tab",
			iconCls: "preview_icon",
			tabTip: "Preview and Export your animations",
			items: [{
			id: "preview",
            xtype:"panel",
            title:"Preview",
			tbar: [" Name: ",{xtype: "textfield",
       value: Ax.animation.name,
       listeners: {
        "change": function(field){Ax.setAnimationName(field.getValue())}
        }, width: 200},{xtype: "tbfill"},{text:"Zoom"},
      {xtype: "slider", width: 120, maxValue: 300, value: 100, increment: 5,plugins: new Ext.ux.SliderTip({
      getText: function(slider){return String.format('Canvas Zoom: {0}%', slider.getValue())}
        })}],
			bbar: new Ext.StatusBar(Ax.PreviewStatusbar),
			border: false,
			tools: [{id: "gear"},{id: "help",
			qtip: "Preview and Export your animations to Flash&reg; ... Hopefully"}],
			iconCls: "preview_icon",			
            layout:"fit",
						 html:"<div class=\"x-border-layout-ct canvas_container\">"+
       "<div class=\"canvas\" id=\"previewcanvas\">Loading...</div>"+
       "</div>"
			
			}],
			listeners: {
      'render' : function(){
        setTimeout(function(){
              Ax.setAnimationName(Ax.animation.name);
        },100);
        
      },
				'activate' : function(){
					//Ax.gs(7);
					Ax.viewport.findById("toolbar").getTopToolbar().items.item(5).menu.items.item(0).setText("Preview Mode")
					Ax.init_preview();
          clearTimeout(Ax.preview_timeout);
					Ax.preview_increment();
				},
				'deactivate' : function(){
					Ax.controls.pause()
				}
			},
            layout:"fit",
			border: true
          },{
		  iconCls: "animations_icon",
		  xtype: "animationbrowser", 
		  tabTip: "Share and View other user's animations",
		  listeners: {
				'activate' : function(){

					//Ax.gs(8)
				},
				'deactivate' : function(){
					Ax.player_pause()
				}
			}
		  }]
      }]
  })
   Ax.LayoutCenterPanel.superclass.initComponent.apply(this, arguments);
  }
  })
  
  Ext.reg("layoutcenter",Ax.LayoutCenterPanel)
  
  
  Ax.setAnimationName = function(name){
    if(!name || name.replace(/ /g,"") == ""){
      name = "Untitled Production"
    }
    Ax.animation.name = name;
    
    if(Ax.viewport.findById("canvas").getTopToolbar().items){
        Ax.viewport.findById("canvas" ).getTopToolbar().items.item(1).getEl().value = name}
    if(Ax.viewport.findById("preview").getTopToolbar().items){
        Ax.viewport.findById("preview").getTopToolbar().items.item(1).getEl().value = name}
  }


 /*JS File: ../js/ui/panels/east.js*/ 


 Ax.LayoutEastPanel = Ext.extend(Ext.Panel,{
initComponent: function(){
Ext.apply(this,{
    region:"east",
    title:"Misc",
    id: "misc",
	iconCls: "misc_panel_icon",
    split:true,
    collapsible:true,
    titleCollapse:true,
    width:130,
    layout:"fit",
    border:true,
    items:[{
        xtype:"tabpanel",
        activeTab:0,
        border:false,
        items:[{
            xtype:"panel",
            title:"Misc",
			iconCls: "misc_icon",
            layout:"fit",
            items:[{
				//id: "misc_accordian",
                layout:"accordion",
                autoScroll: true,
                layoutConfig:{
                  activeOnTop:false,
                  animate:true,
                  autoWidth:true,
                  collapseFirst:false,
                  fill:true,
                  hideCollapseTool:false,
                  titleCollapse:true
                },
                border:false,
                items:[{
                    title:"History",
                    autoHeight:true,
					xtype: "history",
					iconCls: "history_icon",
                    border:false,
					tools: [{id: "close", qtip: "Clear History", handler: function(){Ax.history_clear()}}]
                  },{
                    title:"Clipboard",
                    autoHeight:true,
					xtype: "clipboard",
					layout: "fit",
					iconCls: "clipboard_icon",
					tools: [{id: "close", qtip: "Clear Clipboard", handler: function(){Ax.clipboard_clear()}}],
                    border:false
                  },{
                    title:"Library",
					id: "library",
                    autoHeight:true,
					iconCls: "library_icon",
                    border:false,
                    items:[{xtype:"library"}]
                  },{
                    title:"Misc",
                    autoHeight:true,
					iconCls: "misc_icon",
                    html:"Unavailable",
                    border:false
                  }]
              }]
          },{
		  	disabled: true,
            xtype:"panel",
            title:"User",
			iconCls: "user_icon",
      layout: "fit",
            border:false,
            //html: "hi",
			items:[{xtype: "loginform"}]
			//items: {html:"Yo wazzup dawg"}
          
		  }]
      }]
  })
   this.initialConfig.collapsible = true; //bugfix from http://outroot.com/extjs/bug1/ 
   Ax.LayoutEastPanel.superclass.initComponent.apply(this, arguments);
  }
  })
  
  Ext.reg("layouteast",Ax.LayoutEastPanel)
  
  Ax.misc_setcollapse = function(item){
if(Ax.viewport.findById("misc").collapsed != item.checked){
Ax.viewport.findById("misc").toggleCollapse();
}
}


 /*JS File: ../js/ui/panels/west.js*/ 


 Ax.LayoutWestPanel = Ext.extend(Ext.Panel,{
initComponent: function(){
Ext.apply(this,{
    region:"west",
    title:"Tools",
    id: "tools",
    split:true,
    collapsible:true,
    titleCollapse:true,
    hideCollapseTool: true,
    //html: "<img src='../img/mockup/tools.png'>",
    width:50,
    border:true,
    items: [{xtype:"toolbox"},{xtype: "drawpanel"}]
  })
   this.initialConfig.collapsible = true; //bugfix from http://outroot.com/extjs/bug1/ 
   Ax.LayoutWestPanel.superclass.initComponent.apply(this, arguments);
  }
  })
  
  Ext.reg("layoutwest",Ax.LayoutWestPanel)

  
  Ax.tools_setcollapse = function(item){
if(Ax.viewport.findById("tools").collapsed != item.checked){
Ax.viewport.findById("tools").toggleCollapse();
}
}


 /*JS File: ../js/ui/panels/north.js*/ 


 Ax.LayoutNorthPanel = Ext.extend(Ext.Panel,{
initComponent: function(){

Ext.apply(this,{
    region:"north",
	layout: "fit",
    collapsible:true,
    collapseMode: "mini",
    split:true,
	border: false,
  id: "timeline",
    height:70,
//    border:true,
	items: {xtype: "timeline", border: false}
  })
  this.initialConfig.collapsible = true; //bugfix from http://outroot.com/extjs/bug1/ 

   Ax.LayoutNorthPanel.superclass.initComponent.apply(this, arguments);
  }
  })
  
  Ext.reg("layoutnorth",Ax.LayoutNorthPanel)


 /*JS File: ../js/ui/panels/south.js*/ 


 Ax.LayoutSouthPanel = Ext.extend(Ext.Panel,{
initComponent: function(){
Ext.apply(this,{
    region:"south",
    id: "properties",
	iconCls: "app_settings",
    title:"Properties - Animation",
    split:true,
    collapsible:true,
    titleCollapse:true,
    height:50,
	items: [{
	xtype: "form",
	labelWidth: 50,
	border: false,
	items: {xtype: "properties"}
	}]
  })
   this.initialConfig.collapsible = true; //bugfix from http://outroot.com/extjs/bug1/ 
   Ax.LayoutSouthPanel.superclass.initComponent.apply(this, arguments);
  }
  })
  
  Ext.reg("layoutsouth",Ax.LayoutSouthPanel)
  
  Ax.properties_setcollapse = function(item){
if(Ax.viewport.findById("properties").collapsed != item.checked){
Ax.viewport.findById("properties").toggleCollapse();
}
}


 /*JS File: ../js/ui/register.js*/ 


 Ax.RegistrationForm = Ext.extend(Ext.form.FormPanel, {
    initComponent: function(){
        Ext.apply(this, {
            xtype: "form",
            title: "Registration Form",
            border: false,
            items: [{
                xtype: "textfield",
                fieldLabel: "Username",
                name: "textvalue"
            }, {
                xtype: "textfield",
                fieldLabel: "Password",
                name: "textvalue",
                inputType: "password"
            }, {
                xtype: "textfield",
                fieldLabel: "Password",
                name: "textvalue",
                inputType: "password"
            }, {
                xtype: "button",
                text: "Register Account"
            }]
        })
        
        Ax.RegistrationForm.superclass.initComponent.apply(this, arguments);
    }
})
Ext.reg("registrationform", Ax.RegistrationForm)



 /*JS File: ../js/ui/main.js*/ 


 /*
 Main User Interface
 'Glues' all components together
 */
Ext.onReady(function(){

    Ax.viewport = new Ext.Viewport({
        layout: "border",
        border: false,
        window: {
            layout: "fit"//,
            //tbar: {xtype: "maintoolbar"}
        },
        
        
        items: [{
            region: "north",
            id: "toolbar",
            border: false,
            tbar: Ax.MainToolbar,
            height: 27
        }, {
            region: "center",
            layout: "border",
            border: false,
            items: [{
                xtype: "layoutcenter"
            }, {
                xtype: "layoutnorth"
            }, {
                xtype: "layoutsouth"
            }, {
                xtype: "layoutwest"
            }, {
                xtype: "layouteast"
            }] //end main app border layout items
        }]
    
        //}]  //end main toolbar border layout items
    } //end border layout
); //End Viewport
}); //End Ext.onReady



 /*JS File: ../js/animation/tween_core.js*/ 


 /**
 * @author antimatter15
 */

Ax.largest_nonempty = function(frame,layer,object){
  //searches for largest non-empty frame that is less than the frame
  var nonempty = [];
  object = (object)?object:Ax.layers;

  for(var i = 0; i < object[layer].keyframes.length; i++){
    if(parseInt(object[layer].keyframes[i]) < frame){
        nonempty.push(parseInt(object[layer].keyframes[i]))
    }
  }
  return nonempty.sort(function(a,b){return b - a})[0];//sort descending and pull the first result (largest)
}

Ax.smallest_nonempty = function(frame,layer,object){
  //i'm just gonna copy from largest_nonempty and be too lazy to change the comments
  //so... yeah.... crappy documentation...
    //searches for largest non-empty frame that is less than the frame
  var nonempty = [];
  object = (object)?object:Ax.layers;

  for(var i = 0; i < object[layer].keyframes.length; i++){
    if(parseInt(object[layer].keyframes[i]) > frame){
        nonempty.push(parseInt(object[layer].keyframes[i]))
    }
  }
  return nonempty.sort(function(a,b){return a - b})[0];//sort descending and pull the first result (largest)
}

Ax.count_frames = function(layers, startAt){
	startAt = (startAt)?startAt:0; //set starting point
	layers = (layers)?layers:Ax.layers; //set layers object
	
	for (var layer in layers) { //loop through layers
	    //calculate the biggest frame
		var layer_frames = layers[layer].keyframes.sort(function(a, b){
            return b - a; //sort the keyframe from largest to smallest and pull out the biggest number
        })[0]; //the largest
		
        if (layer_frames > startAt) { //if this is bigger than current value
            startAt = layer_frames; //set current value
        }//end if
	}//end loop
	return startAt; //return last known frame
}

/*Alternate Tweening Engine. Theoretically Vastly Superior*/
Ax.getSFTween_core = function(frame, frame1, frame2, layer, store, clonefunc){//get single frame tween
    var frame1_data = {}, //where all the organized data goes
 		frame2_data = {}, //read above
 		frames_comp = {}, //an array of stuffs 
 		tween_frame = {}, //the tweens stuffs
		tween_axout = [] //xkcd reference (woah, its lining up!)

	
	for(var i = 0; i < store[frame1].length; i++){ //loopy
		frame1_data[store[frame1][i].id] = store[frame1][i];
		frames_comp[store[frame1][i].id] = null
	}
	for(var i = 0; i < store[frame2].length; i++){
		frame2_data[store[frame2][i].id] = store[frame2][i];
		frames_comp[store[frame2][i].id] = null
	}
	
	tween_frame = Ext.ux.clone(frame2_data)
	
	for(var i in frames_comp){
		if (frame2_data[i] && frame1_data[i]) {
			for (var a in frame2_data[i]) {
				tween_frame[i][a] = Ax.tweenAttribute(a, frame1, frame2, frame1_data[i][a], frame2_data[i][a], frame)
			}
		}
		
	}
	
	for(var i in tween_frame){
		tween_axout.push(tween_frame[i])
	}

    
    return tween_axout;
}


Ax.tweenAttribute = function(name, frame1, frame2, value1, value2, index){
	if (value1 == value2){//if they are the same, why bother?
		return value1;
	}
    if (typeof value2 == "number") { //currently only numbers are tweenable
        return Math.round(Ax.tweenNumber(frame1, frame2, value1, value2, index) * 1000) / 1000; //round to 3 decimal places
    }
    if (name == "transform") {
        return Ax.tweenTransform(frame1, frame2, value1, value2, index); //round to 3 decimal places
    }
    if (name == "points") {
        return Ax.tweenPath(frame1, frame2, value1, value2, index);
    }
	if (value1.substr(0,1) == "#" && value2.substr(0,1) == "#"){ //color tweening
		return Ax.tweenHex(frame1, frame2, value1, value2, index);
	}
    /*
     Now:
     Width,Height, Line Width, x, y
     Future:
     DONE - rotation transform, find out the rotation value, run them through the magickal Ax.tweenNumber function
     DONE - color tween: split hex string into 3 segments, turn that into a number, run it throught he magical function and re-hexify
     
     DONE - Stuff that isn't possible through the current toolset, but should work automagically:
     DONE - opacity tweening (i think they're stored in numbers)
     Fun:
     I donno, maybe some text tweening (i dont have any idea how that'd work. maybe changing a character every frame or something.
     */
    return value2; //return the second if no tweening possible.
}


/*
 Woot!!!!!! I FIXED THE ALGORITHIM!!!!!! TWICE!!!!!
 changelog:
 frs0t ps0t:
 return (index/(frame2-frame1))*(value2-value1); //just hope this works!
 second edit:
 return value1+(index/(frame2-frame1))*(value2-value1); //just hope this works!
 third magical edit:
 return value1+((index-frame1)/(frame2-frame1))*(value2-value1); //just hope this works!
 
 */
Ax.tweenTransform = function(frame1, frame2, value1, value2, index){//same as tweenNumber
	value1 = Ax.parseTransform(value1); //parse stuff
    value2 = Ax.parseTransform(value2);
	
	var degree = Ax.tweenNumber(frame1,frame2, value1[0], value2[0],index),
		xcoord = Ax.tweenNumber(frame1,frame2, value1[1], value2[1],index),
		ycoord = Ax.tweenNumber(frame1,frame2, value1[2], value2[2],index)
    
	if(isNaN(degree) == true){
		degree = 0;
	}
	if(isNaN(xcoord) == true){
		xcoord = 0;
	}
	if(isNaN(ycoord) == true){
		ycoord = 0;
	}
	
	
	//console.log(value1,value2);
	
    return "rotate(" +[degree,xcoord,ycoord].join(", ") +")";
    //     return "rotate("+[Ax.tweenNumber(frame1,frame2,value1[0],value2[0],index),
    //                     value2[1],
    //                     value2[2]].join(", ")+")"
}

Ax.parseTransform = function(transform){
    if (!transform || typeof transform != "string") {
        //Ax.msg("Error","Something Strange Happened")
        return [0, 0, 0];
    }
    transform = transform.replace(")", "").replace("rotate(", "").split(",");
    return [Math.round(parseFloat(transform[0]) * 1000) / 1000, Math.round(parseFloat(transform[1]) * 1000) / 1000, Math.round(parseFloat(transform[2]) * 1000) / 1000]
}

Ax.tweenPath = function(frame1, frame2, value1, value2, index){
    value1 = Ax.parsePath(value1);
    value2 = Ax.parsePath(value2);
    for (var i = 0; i < value2.length; i++) {
        if (parseFloat(value2[i]).toString() == value2[i]) {
            value2[i] = Ax.tweenNumber(frame1, frame2, parseFloat(value1[i]), parseFloat(value2[i]), index);
        }
    }
    
    return value2.join(" ")
}

Ax.parsePath = function(points){
    points = points.replace(/,/g, " , "); //replace commas with space+comma+space
    points = points.replace(/L/g, " L "); //replace commas with space+comma+space
    points = points.replace(/M/g, " M "); //replace commas with space+comma+space
    points = points.replace(/  /g, " "); //replace double-spaces
    points = points.replace(/  /g, " "); //replace double-spaces
    return points.split(" ")
}

Ax.tweenHex = function(frame1, frame2, value1, value2, index){
	value1=Ax.hex2rgb(value1);
	value2=Ax.hex2rgb(value2);

	return "#"+[Ax.toHex(Ax.tweenNumber(frame1, frame2, parseInt(value1.R), parseInt(value2.R), index)),
		Ax.toHex(Ax.tweenNumber(frame1, frame2, parseInt(value1.G), parseInt(value2.G), index)),
		Ax.toHex(Ax.tweenNumber(frame1, frame2, parseInt(value1.B), parseInt(value2.B), index))].join("");
}

Ax.hex2rgb = function(hex){
	var match = hex.toLowerCase().match(/^#?([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})$/);
	if (match){
		return {R:parseInt(match[1], 16), G:parseInt(match[2], 16), B:parseInt(match[3], 16)};
	}else{
		return {R: 0, G: 0, B: 0};
	}
}

Ax.toHex = function(color){
	color=parseInt(Math.floor(color)).toString(16);
	return (color.length<2)?"0"+color:color;
}

Ax.tweenNumber = function(frame1, frame2, value1, value2, index){//frame1, frame2, first number, second number, index (from first)
    //no type checking yet, cause i dont feel like it
    return value1 + ((index - frame1) / (frame2 - frame1)) * (value2 - value1); //just hope this works!
    //blah!
}//he he!!!!!!!!!!!!!!!!!!!!!! mua ha ah ha ha



 /*JS File: ../js/animation/tween.js*/ 


 /*tweening functionality*/

Ax.tween = function(frame1,frame2,layer){//this function loops through frames inbetween and flags them as tweens
//unlike the prior versions that actually computed the frames here, everything is just flagged. So,  the speed differences are enourmous.
//sadly, those tweens have to be computed eventually, so it has to be calculated all when you are about to preview things. There used to be
//a cool little cache-script that would cache things and hopefully reduce the processing load when previewing, but that didn't work well
//as i was too  lazy to add one single likne to this function to make it automatically clear 
  //console.log(frame1,frame2,layer)
  if(frame1 && frame2){
    //*ZOMG! CONZONLE DAWT LOOG!!!*/console.log(frame1,frame2,layer);
    for(var i = frame1 + 1; i < frame2; i++){//loop through frames from frame1 to frame2
      Ax.toTween(i,layer);//huh? oh. tell the timelinezo
    }//end loop
  }//end if tingy
}//end functioney

Ax.getSFTween = function (frame, frame1, frame2, layer, store){//get single frame tween
  if(!frame){frame = Ax.tcurrent.frame}//pull defaults if none
  if(!layer){layer = Ax.tcurrent.layer}//same as above,but i'll repeat it so i get a higher comment-ratio: pull defaults if none
  if(!frame1){frame1 = Ax.largest_nonempty(frame,layer)};//pull the last keyframe if none
  if(!frame2){frame2 = Ax.smallest_nonempty(frame,layer)};//pull the next keyframe if none, which is essentially the same thing as the one before
  //but i feel like increasing my comment ratio (as in the if(!layer){... line) but i'm repeating it for a higher comment-code-ratio (as in that same line). 
  
  //console.log(frame, frame1,frame2,layer)
  //tween a single frame and get a single frame (framedump) in return
  store = (store)?store:Ax.canvas_storage[layer];
  
  
  if(!store[frame1]){
  	Ax.toastMsg("Error!","Ajax Animator's Tweening Engine has encountered a potentially critical error because store[frame1] is non-existant.")
  	store[frame1] = [];
  }
  if(!store[frame2]){
  	Ax.toastMsg("Error!","Ajax Animator's Tweening Engine has encountered a potentially critical error because store[frame2] is non-existant.")
  	store[frame2] = [];
  }
  
 /*some random benchmarking stuffs, evidently, the engines are roughly the same in speed
 var first = (new Date()).getTime();
  Ax.getSFTween_old_core(frame, frame1, frame2, layer, store);
  first = ((new Date()).getTime() - first)
  var second = (new Date()).getTime();
  Ax.getSFTween_core(frame, frame1, frame2, layer, store);
  second = ((new Date()).getTime() - second )
  
  console.log(first,second)
*/
  
  
  	return Ax.getSFTween_core(frame, frame1, frame2, layer, store);
  
}




 /*JS File: ../js/animation/controls.js*/ 


 Ax.controls = {
    play: function(){
        Ax.viewport.findById("maintabpanel").activate(1)
        Ax.preview_increment();
    },
    pause: function(){
        Ax.viewport.findById("maintabpanel").activate(1)
        clearTimeout(Ax.preview_timeout);
        clearTimeout(Ax.preview_timeout);
        clearTimeout(Ax.preview_timeout);
    },
    next: function(){
        switch (Ax.viewport.findById("maintabpanel").getActiveTab().getId()) {
            case "canvas_tab":
                Ax.selectFrame(Ax.tcurrent.frame + 1, Ax.tcurrent.layer)
                break;
            case "preview_tab":
                Ax.preview_frame++;
                break;
        }
    },
    previous: function(){
        switch (Ax.viewport.findById("maintabpanel").getActiveTab().getId()) {
            case "canvas_tab":
                Ax.selectFrame(Ax.tcurrent.frame - 1, Ax.tcurrent.layer)
                break;
            case "preview_tab":
                Ax.preview_frame--;
                break;
        }
    },
    last: function(){
        //Ax.msg("No worky", "this doesn't work yet.")
        switch (Ax.viewport.findById("maintabpanel").getActiveTab().getId()) {
            case "canvas_tab":
                Ax.selectFrame(Ax.count_frames(), Ax.tcurrent.layer);
                break;
            case "preview_tab":
                Ax.preview_frame = Ax.count_frames();
                break;
        }
	},
    first: function(){
        switch (Ax.viewport.findById("maintabpanel").getActiveTab().getId()) {
            case "canvas_tab":
                Ax.selectFrame(1, Ax.tcurrent.layer);
                break;
            case "preview_tab":
                Ax.preview_frame = 1;
                break;
        }
    }
}



 /*JS File: ../js/animation/frames.js*/ 


 
Ax.dumpframe = function(frame,layer){
  if(!frame){frame = Ax.tcurrent.frame}
  if(!layer){layer = Ax.tcurrent.layer}
  //console.log(frame,layer)
  //dumps current frame onto the frame_storage
  //oops. scratch that, it's now the *canvas*_storage (without asterekasdwz)
  if(!Ax.canvas_storage[layer]){
    Ax.canvas_storage[layer] = {};
  }
  //Ax.canvas.unselect();
  var shapedump =  Ax.dumpshapes();

  if(!Ax.isTween(frame,layer)){
    Ax.canvas_storage[layer][frame] = shapedump;
  }
  return shapedump;

}

Ax.loadframe = function(frame,layer){
  if(Ax.canvas_storage[layer][frame]){
    Ax.canvas.unselect();
    Ax.canvas.renderer.removeAll();
    Ax.loadShapes(Ax.canvas_storage[layer][frame])
    Ax.autodiff();
    return true;
  }else if(Ax.isTween(frame,layer)){
    Ax.canvas.unselect();//unselect
    Ax.canvas.renderer.removeAll();//remove all objects
    Ax.loadShapes(Ax.getSFTween(frame,Ax.largest_nonempty(frame,layer),Ax.smallest_nonempty(frame,layer),layer));//load tween
    return true;//finish
  }
  Ax.canvas.renderer.removeAll();//remove all objects
  Ax.loadShapes(Ax.canvas_storage[layer][Ax.largest_nonempty(frame,layer)]);//load last keyframe
  //note to self: rename function to make more sense.....
  Ax.canvas.unselect();
  //Ax.canvas.renderer.removeAll();
  return false;
}




 /*JS File: ../js/animation/diff.js*/ 


 //This is a file that is virtually the core of the tweening engine
//not really. it just detects what frames are keyframes. automatically.

Ax.diff_exclude = ["id"]

Ax.autodiff = function(){
    //save canvas state
    if (Ax.tcurrent.layer && Ax.tcurrent.frame) { //..only if the current frame *exists*
        //here is the magical code that does the history revision saving stuffs
        var createdump = false;
        if (Ax.canvas_storage[Ax.tcurrent.layer] &&
        Ax.canvas_storage[Ax.tcurrent.layer][Ax.tcurrent.frame] &&
        Ax.diff_core(Ax.dumpshapes(), Ax.canvas_storage[Ax.tcurrent.layer][Ax.tcurrent.frame]) != true) {
            createdump = true;
        }
        
        Ax.dumpframe(); //dump current canvas to current layer
        //check for diff
        
        if (Ax.isTween() == true && Ax.diff_core(Ax.dumpshapes(), Ax.getSFTween()) != true) {
            //Ax.msg("Sorry!","For some reason, this feature isn't working at all. So, no editing tweens yet. Pity.")
            //console.log("specialtotweenness")
            Ax.toKeyframe(Ax.tcurrent.frame, Ax.tcurrent.layer)
        }
        else 
            if (Ax.diff(Ax.largest_nonempty(Ax.tcurrent.frame, Ax.tcurrent.layer), Ax.tcurrent.frame, Ax.tcurrent.layer) != true &&
            Ax.layers[Ax.tcurrent.layer].tweens.indexOf(Ax.tcurrent.frame) == -1) {
                Ax.toKeyframe(Ax.tcurrent.frame, Ax.tcurrent.layer);
            }
            else 
                if (Ax.isKeyframe() == false) {
                    //Ax.toBlank_core(Ax.tcurrent.frame,Ax.tcurrent.layer)
                    delete Ax.canvas_storage[Ax.tcurrent.layer][Ax.tcurrent.frame];
                }
        
        //here actually stores the revisions stuffs
        if (createdump == true) {
            if (Ax.canvas && Ax.canvas.queryCommand("mode")) {
                Ax.history_add(Ax.toolConfig[Ax.canvas.queryCommand("mode")][2]);//needs work
            }
        }
    }
}

Ax.diff = function(frame1, frame2, layer){
    //takes two frame identifier numbers and a layer as arguments
    //returns true or false, true being identical, false being different
    return Ax.diff_core(Ax.canvas_storage[layer][frame1], Ax.canvas_storage[layer][frame2])
}



Ax.diff_core = function(shapedump1, shapedump2){
    //It takes two arguments, one with the shape dump of the first frame
    // ( you can find it in the canvas_storage object, or dump it fresh)
    //with the dumpshapes() function. The ShapeDump takes the from of a
    //array with json shape dumps inside.
    if ((!shapedump1 || !shapedump2) || (shapedump1.length != shapedump2.length)) {
        return false;
    }
    else {
        for (var i = 0; i < shapedump1.length; i++) {
            for (var x in shapedump2[i]) {
                //console.log(i,shapedump1[i].type,x,shapedump2[i][x],shapedump1[i][x])
                if (Ax.diff_attr(shapedump1[i][x], shapedump2[i][x], x) == false) {
                    return false;
                }
            }
        }
    }
    return true;
}

Ax.diff_list = function(shapedump1, shapedump2){
	var difflist = [];
    if ((!shapedump1 || !shapedump2) || (shapedump1.length != shapedump2.length)) {
        return false;
    }
    else {
        for (var i = 0; i < shapedump1.length; i++) {
            for (var x in shapedump2[i]) {
                if (Ax.diff_attr(shapedump1[i][x], shapedump2[i][x], x) == false) {
                    difflist.push([shapedump1[i], x])
                }
            }
        }
    }
    return difflist;
}


Ax.diff_attr = function(value1, value2, attrid){
    if (Ax.diff_exclude.indexOf(attrid) == -1) {
        if (typeof value2 == "number") {
            value2 = Math.round(value2 * 100) / 100
            value1 = Math.round(value1 * 100) / 100
        }
        if (attrid == "transform") {
            if (Math.round(Ax.parseTransform(value2)[0]) != Math.round(Ax.parseTransform(value1)[0])) {
                return false
            }
        }
        else {
            if (value2 != value1) {
                return false;//not same
            }
        }
    }
    return true;
}





 /*JS File: ../js/animation/animations.js*/ 


 //this file is soooooo fubared
//omg.....

Ax.AnimationBrowser = Ext.extend(Ext.Panel, {
    initComponent: function(){
        Ext.apply(this, {
            id: "Animations",
            xtype: "panel",
            title: "Animations",
            border: false,
            layout: "fit",
            items: {
                layout: "border",
                border: false,
                items: [{
                
                    //border: false,
                    region: "center",
                    
                    title: "Player",
                    id: "Player",
                    layout: "border",
                    items: [{
                        region: "north",
                        border: false,
                        tbar: [{
                            text: "By:&nbsp;Unavailable"
                        }, {
                            xtype: "tbfill"
                        }, "Unavailable"],
                        height: 27
                    }, {
                        region: "south",
                        border: false,
                        bbar: [{
                            text: "Play",
                            iconCls: "play_icon",
                            handler: function(){
                                Ax.player_play()
                            }
                        }, {
                            text: "Pause",
                            iconCls: "stop_icon",
                            handler: function(){
                                Ax.player_pause()
                            }
                        }, {
                            text: "Import to Editor",
                            iconCls: "import_icon",
                            handler: function(){
                                Ax.player_import()
                            }
                        }, {
                            xtype: "tbfill"
                        }, "?/? ?FPS"],
                        height: 27
                    }, {
                        region: "center",
                        border: false,
                        html: "<div class=\"x-border-layout-ct canvas_container\"><div id=\"playercanvas\" class=\"canvas\"></div></div>"
                    }],
                    autoScroll: true,
                    tools: [{
                        id: "gear"
                    }, {
                        id: "help",
                        qtip: "View and share animations with other users. Use the left panel to browse for animations," +
                        " and click them to view them. Feel free to press the \"import\" button and make improvements."
                    }],
                    iconCls: "player_icon"
                }, {
                    //border: false,
                    region: "west",
                    id: "treebrowse",
                    title: "Browse",
                    collapseFirst: false,
                    tools: [{
                        id: "plus",
                        qtip: "Expand All",
                        handler: function(){
                            Ax.viewport.findById("treebrowse").expandAll()
                        }
                    }, {
                        id: "minus",
                        qtip: "Collapse All",
                        handler: function(){
                            Ax.viewport.findById("treebrowse").collapseAll()
                        }
                    }],
                    iconCls: "browse_icon",
                    width: 200,
                    split: true,
                    collapsible: true,
                    layout: "fit",
                    titleCollapse: true,
                    
                    //items: [{
                    //border: false,
                    xtype: "treepanel",
                    useArrows: true,
                    autoScroll: true,
                    animate: true,
                    enableDD: false,
                    containerScroll: true,
                    bbar: [{
                        text: "Reload",
                        qtip: "Reload Tree Data",
                        iconCls: "reload_icon",
                        handler: function(){
                            Ax.viewport.findById("treebrowse").getLoader().load(Ax.viewport.findById("treebrowse").getRootNode())
                        }
                    }],
                    root: new Ext.tree.AsyncTreeNode({
                        text: 'Animations',
                        expanded: true,
                        draggable: false,
                        id: '.'
                    }),
                    loader: new Ext.tree.TreeLoader({
                        dataUrl: (window.location.protocol=="file:")?null:Ax.files.userlist
                    }),
                    listeners: {
                        "click": function(node){
                            if (node.childrenRendered == false) {
                                Ext.Ajax.request({
                                    url: Ax.files.animations + node.id,
                                    success: function(e){
                                        Ax.player_pause()
                                        Ax.init_player(e.responseText);
                                        Ax.player_play()
                                    }
                                })
                            }
                        }
                    }
                
                
                
                    //}]
                
                }]
            }
        })//end ext.apply
        Ax.AnimationBrowser.superclass.initComponent.apply(this, arguments);
    }
    
})

Ext.reg("animationbrowser", Ax.AnimationBrowser)

Ax.showanimationbrowser = function(){
    Ax.viewport.findById("maintabpanel").activate(2)
}



 /*JS File: ../js/animation/storage.js*/ 


 Ax.canvas_storage = {}; //Initial data.

Ax.getshapes = function(frame,layer){
	//a very high-level function ish
	if(!frame){frame = Ax.tcurrent.frame}
	if(!layer){layer = Ax.tcurrent.layer}
	
	if(!Ax.canvas_storage[layer]){
		//conzoledawtloog("Error: NO LAYER OBJECT", Ax.canvas_storage[layer], Ax.canvas_storage, layer)
		return [];
	}
	
	if(Ax.canvas_storage[layer][frame]){
		//conzoledawtloog("OUT: KEYFRAME")
		return (Ax.canvas_storage[layer][frame]);
	}else if(Ax.smallest_nonempty(frame, layer) && Ax.largest_nonempty(frame, layer)){
		//conzoledawtloog("OUT: TWEEN")
		return Ax.getSFTween(frame, Ax.largest_nonempty(frame, layer), Ax.smallest_nonempty(frame, layer), layer)
	}
	
	//conzoledawtloog("Error: BLANK FRMAE")
	return [];	
}



 /*JS File: ../js/animation/timeline.js*/ 


 Ax.Timeline = Ext.extend(Ext.Panel, {
    initComponent: function(){
        Ext.apply(this, {
            layout: "border",
            items: [{
                region: "center",
                autoScroll: true,
                border: false,
                html: "<div id='timeline_core' class='x-unselectable' style='height: 100%; width: 100%'>Loading Frames...</div>"
            }, {
                region: "west",
                width: 100,
                border: false,
                split: true,
                
                collapsible: true,
                collapseMode: "mini",
                autoScroll: true,
                layout: "fit",
                //html: "Layers"
                items: {
                    id: "layers",
                    xtype: "editorgrid",
                    border: false,
                    hideHeaders: true,
                    plugins: [new Ext.ux.grid.CellActions({
                        callbacks: {
                            "tb_delete": function(grid, record, action, value){
								if (Ax.tcurrent.layer == value) {
									return Ax.toastMsg("Error!","You can't delete the current selected layer!")
								}
                                Ext.MessageBox.confirm("Delete " + value + "?", "Are you sure you want to delete " + value + "?", function(result){
                                    if (result == "yes") {
                                        Ax.deleteLayer(value)
                                    }
                                })
                            }
                        }
                    })],
                    viewConfig: {
                        autoFill: true,
                        forceFit: true
                    },
                    listeners: {
                        "afteredit": function(object){
                            //console.log(object.originalValue,object.value)
                            Ax.renameLayer(object.originalValue, object.value)
                        }
                    },
                    sm: new Ext.grid.RowSelectionModel({
                        singleSelect: true
                    }),
                    
                    //clicksToEdit:1,
                    ds:/*BEGIN*/ new Ext.data.Store()/*END*/,
                    columns: [{
                        header: "Comment",
                        dataIndex: "comment",
                        editor: new Ext.form.TextField(),
                        cellActions: [{
                            iconCls: "tb_delete",
                            qtip: "Delete this layer."
                        }]
                    }]
                }
            }]
        })
        Ax.Timeline.superclass.initComponent.apply(this, arguments);
    }
})

Ext.reg("timeline", Ax.Timeline)


Ax.timeline_setcollapse = function(item){
if(Ax.viewport.findById("timeline").collapsed != item.checked){
Ax.viewport.findById("timeline").toggleCollapse();
}
}



 /*JS File: ../js/animation/timeline_core.js*/ 


 Ax.timeline = {el: null, mask: null};
Ax.layers = {}; //this stores all the data for layer stuff


Ax.tstat = { //statistics for the count of frames and layers (displayed in timeline, not animation)
  layers: 0, //layers
  frames: 0  //frames.
}

Ax.tcurrent = { //currently selected frame/layer
  layer: null, //btw layers are strings (their ID)
  frame: null //im trying to decide whether this shoudl be 0 or null
}

Ax.renameLayer = function(oldname,newname){ //pretty neat. eh?
  Ax.layers[newname]=Ax.layers[oldname]; //we didn't have cusom layer names in the old version
  delete Ax.layers[oldname]; //...just random numbers
  
  Ax.canvas_storage[newname] = Ax.canvas_storage[oldname]; //but this seems nicer
  delete Ax.canvas_storage[oldname]; //right?
  
  return Ax.layers; //ok.
}

Ax.deleteLayer = function(name){//Sorta works.... anyone wanna test?
  if(Ax.tcurrent.layer == name){
  	return Ax.toastMsg("Delete Error","You can not delect the current selected layer.")
  }

  Ext.get(Ax.layers[name].el).remove(); //remove the table element
  Ax.viewport.findById("layers").getStore().remove(Ax.layers[name].record);
  //remoe the stuff from the little editable grid witht he titles
   
  delete Ax.layers[name]; //delete the entry
  Ax.tstat.layers--; //we removed a frame...
  
}

Ax.addLayer = function(layername){
  layername = (layername)?layername:"Layer "+((Ax.tstat.layers+1).toString());

  var f_layer = document.createElement("tr"); 
  Ax.layers[layername] = {
    el:f_layer,
    keyframes: [1],
    tweens: [],
    record: new Ext.data.Record({comment:layername})
    }
  Ax.viewport.findById("layers").getStore().add(Ax.layers[layername].record)
  if(!Ax.canvas_storage[layername]){
    Ax.canvas_storage[layername] = {"1":[]};//create a canvas storage slot with first frame set to blank
  }
  
  //Ext.log(f_layer.innerHTML)
  //Ax.current.layer = layer
  Ax.tstat.layers++
  Ax.timeline.el.appendChild(f_layer)
  
  for(var frame = 0; frame < Ax.tstat.frames; frame++){
    Ax.addFrame_core(frame+1,layername)
  }


  //Ext.log(f_layer.innerHTML)
  return f_layer;
}

Ax.addFrame = function(){
  Ax.tstat.frames++
  for(var layer in Ax.layers){
    Ax.addFrame_core(Ax.tstat.frames,layer)
  }
}

Ax.addFrames = function(frames){ //mind the s, this just loops through whatever number and makes so many frames
  for(var i = 0; i < frames; i++){
    Ax.addFrame()
  }
}




Ax.addFrame_core = function(frame,layer){
  //console.log(layer)
  var frame_cell = document.createElement("td")
  //frame.style.bgColor = "#99BBE8";
  frame_cell.className = "frame"

  var frame_content = document.createElement("div")
  frame_content.className = "frame"
  frame_content.innerHTML =  frame //[1,2,5,10,42,420,316,4242,1337][Math.floor(Math.random()*9)];

  switch(frame_content.innerHTML.length){
    case 1:
      frame_content.style.marginTop = "1px";    
      frame_content.style.fontSize = "110%";
      //frame_content.style.marginTop = "-6px";
      //frame_content.style.fontSize = "140%";
    break;
    case 2:
      frame_content.style.marginBottom = "-2px";    
      frame_content.style.fontSize = "90%";
      break;
    case 3:
      frame_content.style.marginBottom = "-7px"
      frame_content.style.fontSize = "65%";
    break;
    case 4:
      frame_content.style.marginBottom = "-11px"
      frame_content.style.fontSize = "40%";
    break;
  }
  
  frame_cell.appendChild(frame_content)
  
  Ax.addFrameListeners(frame_cell,frame,layer)
  
  Ax.layers[layer].el.appendChild(frame_cell)
}
//#99BBE8



Ax.getFrame = function(frame,layer){
  if(frame > 0){
    return Ext.get(Ax.layers[layer].el.childNodes[frame-1]);
  }
}

Ax.selectFrame = function(frame,layer){
  if(frame < 1){return false;}; //OMG!! PONIES!
  
  if(Ext.get("cbframe")){
  	Ext.get("cbframe").dom.value = frame;
  }
  
  Ax.viewport.findById("layers").getSelectionModel().selectRecords([Ax.layers[layer].record], false)
  //select the layer
  
  Ax.autodiff(); //save current state, etc.
    
  //Set cursor
  Ax.tcurrent.frame = frame;
  Ax.tcurrent.layer = layer;
  //Change Styles
  Ax.selectFrame_core(frame,layer);
  //Add frames if necessary
  if(frame > Ax.tstat.frames - 30){
    Ax.addFrames(50 - (Ax.tstat.frames - frame))
  }

  //change the canvas to new one if possible
  Ax.loadframe(frame,layer)
  
}

Ax.selectFrame_core = function(frame,layer){
  Ax.timeline.mask.style.top = (Ax.getFrame(frame,layer).getY()-Ext.get(Ax.timeline.el).getY()).toString()+"px"
  Ax.timeline.mask.style.left = (Ax.getFrame(frame,layer).getX()-Ext.get(Ax.timeline.el).getX()).toString()+"px"
}

Ax.insertFrame = function(frame,layer){
  if(frame < 1){return false;}; //OMG!! PONIES!
  if(!frame){frame = Ax.tcurrent.frame}
  if(!layer){layer = Ax.tcurrent.layer}

  Ax.addFrame()
  
  for(var i = 0; i < Ax.layers[layer].keyframes.length; i++){
    if(Ax.layers[layer].keyframes[i] > frame){
      var keyframe_id = Ax.layers[layer].keyframes[i];
      Ax.layers[layer].keyframes[i] += 1;
      Ax.canvas_storage[layer][(keyframe_id+1).toString()] = Ax.canvas_storage[layer][keyframe_id.toString()]
      delete Ax.canvas_storage[layer][keyframe_id.toString()]
    }
  }
  for(var i = 0; i < Ax.layers[layer].tweens.length; i++){
    if(Ax.layers[layer].tweens[i] > frame){
      Ax.layers[layer].tweens[i]+=1
    }
  }
  for(var i = frame; i < Ax.tstat.frames; i++){
    Ax.renderFrame(i,layer)
  }
  
  if(Ax.isTween(frame,layer)){
    Ax.tween(Ax.largest_nonempty(frame,layer),Ax.smallest_nonempty(frame,layer),layer); //tween from previous keyframe to no
    if(frame == Ax.tcurrent.frame && layer == Ax.tcurrent.layer){
      Ax.loadframe(frame, layer)
    }
  }
  
}

Ax.renderFrame = function(frame,layer){
  switch(Ax.frameType(frame,layer)){
    case "keyframe":
      Ax.toKeyframe_core(frame,layer)
      break;
    case "tween":
      Ax.toTween_core(frame,layer)
      break;
    case "blank":
      Ax.toBlank_core(frame,layer)
      break;
  }
}

Ax.frameType = function(frame,layer){
  if(Ax.isKeyframe(frame,layer) == true){
    return "keyframe"
  }
  if(Ax.isTween(frame,layer) == true){
    return "tween"
  }
  return "blank"
}

Ax.toKeyframe = function(frame,layer){
  if(!frame){frame = Ax.tcurrent.frame}
  if(!layer){layer = Ax.tcurrent.layer}

  
  if(!Ax.isKeyframe(frame,layer)){
    Ax.layers[layer].keyframes.push(frame);
  }
  
  
  if(Ax.isTween(frame,layer)){//this never sees light, because the thing above keeps it from ever executing
    //but its still here as a useless brick in case pigs can fly (don't you love cliches?)
    Ax.layers[layer].tweens.splice(Ax.layers[layer].tweens.indexOf(frame),1)
    //Ax.tween(frame,Ax.smallest_nonempty(frame,layer),layer); //tween from now to next
  }else{
    Ax.tween(Ax.largest_nonempty(frame,layer),frame,layer); //tween from previous keyframe to now
  }
  
  
  return Ax.toKeyframe_core(frame,layer)
}

Ax.frameClass = function(frame,layer,frameclass){
  Ax.getFrame(frame,layer).dom.className = "frame "+frameclass;
}

Ax.isTween = function(frame,layer){
  if(!frame){frame = Ax.tcurrent.frame}
  if(!layer){layer = Ax.tcurrent.layer}
  return (Ax.layers[layer].tweens.indexOf(frame) != -1)
}

Ax.isKeyframe = function(frame,layer){
  if(!frame){frame = Ax.tcurrent.frame}
  if(!layer){layer = Ax.tcurrent.layer}
  return (Ax.layers[layer].keyframes.indexOf(frame)!= -1)
}

Ax.toKeyframe_core = function(frame,layer){
  Ax.frameClass(frame,layer,"keyframe");
}

//there is no non-core Ax.toTween as it is supposedly automatic
//scratch that.... idk
Ax.toTween_core = function(frame,layer){
  Ax.frameClass(frame,layer,"tween");
}

Ax.toTween = function(frame,layer){
  if(Ax.layers[layer].tweens.indexOf(frame) == -1){
    Ax.layers[layer].tweens.push(frame);
  }
  
  return Ax.toTween_core(frame,layer)
}

Ax.toBlank_core = function(frame,layer){
  Ax.frameClass(frame,layer)
}

Ax.addFrameListeners = function(frame_cell,frame,layer){
  //not very memory friendlyish. stuffs dont get removed when unneeded/unused.
  new Ext.ToolTip({
   target: frame_cell,
   trackMouse: true,
   shadow: false,
   width: 120,
   title: "Loading...",
   html: 'Loading...',
   rframe: frame,
   rlayer: layer,
   listeners: {
   	"show":function(tooltip){
		
		var dataformat = {
			"Shapes": Ax.getshapes(tooltip.rframe, tooltip.rlayer).length
		}, dataoutput = "";
		
		for(var label in dataformat){
			dataoutput += "<span style=\"float: left\">"+label+"</span><span style=\"float: right\">"+dataformat[label]+"</span><br>"
		}
		
		
		var preview_tip = document.createElement("div"); //im not good with Ext dom stuffs
		preview_tip.className = "preview_tip"
		Ext.get(preview_tip).setHeight(((tooltip.getBox().width - 12) * Ax.canvasHeight)/Ax.canvasWidth)
		Ext.get(preview_tip).setWidth(tooltip.getBox().width - 12)
		
		
		tooltip.setTitle('Frame '+tooltip.rframe.toString()+" "+tooltip.rlayer.toString())
		tooltip.body.update(dataoutput)
		
		if(Ext.isIE){
			preview_tip.innerHTML = "Preview Tips Not Available For Microsoft Internet Explorer"
		}
		
		tooltip.body.dom.appendChild(preview_tip)
		
		Ax.viewer_load_frame(tooltip.rframe, Ax.export_animation_core(), Ax.init_view_core(preview_tip))

		//console.log((tooltip.getBox().width * Ax.canvasHeight)/Ax.canvasWidth)
		
		//
	},
	"hide": function(tooltip){
		//make more memory friendlyish
		tooltip.body.dom.innerHTML = "";
	}
   }
  });

}


Ax.create_timeline_mask = function(){
  Ax.timeline.mask = document.createElement("div")
  Ax.timeline.mask.className = "fselect_mask"
  Ax.timeline.el.appendChild(Ax.timeline.mask)
  
   new Ext.ToolTip({
   target: Ax.timeline.mask,
   trackMouse: true,
   shadow: false,
   //width: 120,
   title: 'Loading...',
   html: "Loading...",
   listeners: {
   	"show": function(tooltip){
		tooltip.setTitle('Frame '+Ax.tcurrent.frame.toString()+" "+Ax.tcurrent.layer.toString())
		tooltip.body.update("Selected Frame")
		
	}
   }
   })
}


Ax.reloadTimeline = function(){
	for(var layer in Ax.layers){
		for(var frame = 1; frame < Ax.tstat.frames+1; frame++){
			Ax.renderFrame(frame, layer);
		}
	}
	Ax.msg("Timeline Reloaded","Timeline has been sucessfully rendered")
}

Ax.timelineCleanup = function(){
	Ax.msg("Timeline Cleanup","Timeline has been sucessfully cleaned up."); //meh. it did nothing
}

Ax.initTimeline = function(){
  Ax.layers = {};
  
  Ext.get("timeline_core").dom.innerHTML = ""
  var frameTable = document.createElement("table");
  frameTable.setAttribute("cellspacing","0")
  frameTable.setAttribute("cellpadding","0")
  frameTable.setAttribute("border","0")
  //frameTable.style.border = "1px solid gra"
  var frameTBody = document.createElement("tbody");
  frameTable.appendChild(frameTBody)
  Ext.get("timeline_core").dom.appendChild(frameTable)
  Ax.timeline.el = frameTBody;
  
  Ext.get("timeline_core").parent().on("selectstart",function(event){event.stopEvent();return false})
  Ext.get("timeline_core").parent().on("mousedown", function(event, target){
  	if(target.className == "frame"){
	for(var layer in Ax.layers){
      if(target.parentNode.parentNode == Ax.layers[layer].el){
        Ax.selectFrame(parseInt(target.innerHTML),layer)
        break;
      }
    }
	}
	if(event.button == 2){
		
	}
  //	console.log(event,target)
  })
  Ext.get("timeline_core").parent().on("contextmenu",function(event,target){
    //console.log(event,target)
    event.stopEvent();
//console.log(Ax.tcurrent)
    if(target.className == "fselect_mask" ||( target.innerHTML == Ax.tcurrent.frame.toString() )){
      new Ext.menu.Menu({
        items: [
        {text: "Add Layer", iconCls: "tb_newlayer", handler: function(){Ax.addLayer()}},
        {text: "To Keyframe", iconCls: "tb_addkeyframe", handler: function(){Ax.toKeyframe()}},
        {text: "Insert Frame", iconCls: "tb_insertframe", handler: function(){Ax.insertFrame()}}
        ]
      }).showAt(event.xy)
    }else{
      new Ext.menu.Menu({
        items: [
         {text: "Add Layer", iconCls: "tb_newlayer", handler: function(){Ax.addLayer()}}
        ]
      }).showAt(event.xy)
    }
  })
  
  Ax.create_timeline_mask();
}

/*
Ext.onReady(function(){
  Ax.initTimeline()
  Ax.addLayer()
  Ax.addFrames(150)
})
//*/ /**/ //END





 /*JS File: ../js/animation/preview.js*/ 


 
Ax.preview_increment = function(){
  var start = (new Date()).getTime();
  Ax.preview_frame = Ax.viewer_load_frame( //load the next frame
  ((Ax.preview_frame)?Ax.preview_frame:Ax.tcurrent.frame), //if no current frame, load from the current editor frame
  Ax.preview_markup, //the la magickal poop!
  Ax.preview //the canvas
  ) + 1;

  if(Ax.preview_frame % 4 == 0){
        Ext.get("pbframe").dom.value = Ax.preview_frame
    Ax.setPreviewStatus(Math.round((new Date()).getTime() - start))
  }

  Ax.preview_timeout = setTimeout(function(){Ax.preview_increment()}, 1000/Ax.framerate);
}

Ax.preview_msg = function(){
    Ax.msg("Preview","Preview is for viewing! Head over to the Canvas tab to edit.")
  }


Ax.init_preview = function(){
  Ax.autodiff(); //insures its the current data.
	
  $("previewcanvas").innerHTML = "";
  
  Ext.get("previewcanvas").un("mousedown",Ax.preview_msg);//bai bai lyst3n3rz
  
  Ax.preview = Ax.init_view($("previewcanvas"), Ax.canvasWidth, Ax.canvasHeight);
  
  Ext.get("previewcanvas").on("mousedown",Ax.preview_msg);
  
  Ax.preview_markup = Ax.export_animation_core();
  Ax.preview_frame = null;
}





 /*JS File: ../js/animation/player.js*/ 


 
Ax.player_increment = function(){
    var start = (new Date()).getTime();
    Ax.player_frame = Ax.viewer_load_frame( //load the next frame
	((Ax.player_frame) ? Ax.player_frame : 1), //if no current frame, load from the current editor frame
 	Ax.player_markup.layers, //the la magickal poop!
 	Ax.player //the canvas
	) +
    1;
    
    Ax.player_timeout = setTimeout(function(){
        Ax.player_increment()
    }, 1000 / ((Ax.player_markup.framerate) ? Ax.player_markup.framerate : 12));
}

Ax.player_play = function(){
    Ax.player_increment();
}
Ax.player_pause = function(){
    clearTimeout(Ax.player_timeout);
}

Ax.init_player = function(markup){
    if (Ext.isIE == true) { //yes. i know. browser sniffing is bad
        $("playercanvas").style.position = "absolute";
        $("playercanvas").style.left = "5%";
    }
    if (typeof markup == typeof "insanelygreat") {
        markup = Ext.util.JSON.decode(markup)
    }
    $("playercanvas").innerHTML = "";
    Ax.player = Ax.init_view($("playercanvas"), markup.width, markup.height);
    Ax.player_markup = markup;
    Ax.player_frame = null;
}

Ax.player_import = function(){
    Ax.viewport.findById("maintabpanel").activate(0)
    Ax.import_animation(Ax.player_markup);
}



 /*JS File: ../js/data/format.js*/ 


 /*The magickal ALEON (Animation Lightweight Ecmascript Object Notation Format)*/
//or maybe AXON woudl be better.
//you can call it Awesome Lightweight Extreme Online New-animation-format if you like
//or other countless bacronyms
//sorry for the ridiculous name

/*
ALEON/Axff/Xff


{
  frames: 0, //frame count (required)
  tcframe: 1, //current frame
  tclayer: "Layer 1", //current layer
  generator: { //Ax.v dump
    app: "Ajax Animator",
    release: 0.2,
    build: 232
  },
  creation: 1214687653614, //unix epoch of creation
  modified: 1214687673324, //last modified date
  contrib: [ //array of contributors
    "k7d13x32fc" //10 digit auto-generated id for session, or username
  ],
    
  layers: { //where all the data is stored
    "Layer 1": {
      keyframes: [1,5,10,15,20],
      //tweens: [2,3,4,6,7,8,9,11,12,13,14,16,17,18,19], //this one is optional and not included by default
      src: [ //standard OPF data
        {type: "rect", id: "somelongidstring", x: 31, y: 32, ...}
      ]
    }
  }
}
*/


//format information
Ax.format = {
  support: {//format support. minimum version, maximum version
    min: 1,
    max: 13
  },
  revision: 13 //the version the app exports
}


Ax.emptyAnimation = {
  layers: {
    "Layer 1": {
      keyframes: [1],
      src: {
        "1":[]
      }
    }
  }
}

Ax.new_animation = function(){
  Ax.import_animation(Ext.ux.clone(Ax.emptyAnimation))
  Ax.history_add("New Animation")
}

Ax.export_animation_core = function(input,format){
  var layers = {};
  for(var layer in Ax.layers){
    layers[layer] = {
      keyframes: Ax.layers[layer].keyframes,
      //tweens: Ax.layers[layer].tweens, //this is not necessary
      src: Ax.canvas_storage[layer]
    }
  }
  return layers;
}

Ax.export_animation = function(input, format){
  if(!input){
    input = {};
  }
  
  input.name = Ax.animation.name; //quite important to have this up here so you can easily identify the animation from a quick glance
	
  if(!input.creation){
    input.creation = (new Date()).getTime()
  }
  
  if(typeof input.contrib != typeof ['antimatter15','is','awesome']){
    input.contrib = []; //an array
  }
  if(input.contrib.indexOf((Ax.userid)?Ax.userid:"anonymous") == -1){
    input.contrib.push((Ax.userid)?Ax.userid:"anonymous"); //add user to list of contributors if not there already
  }
  
  input.modified = (new Date()).getTime();
  input.generator = Ax.v;
    
  input.revision = Ax.format.revision;
  
  input.tcframe = Ax.tcurrent.frame;
  input.tclayer = Ax.tcurrent.layer;
  
  input.layers = Ax.export_animation_core(); //the most important part: the data
  
  input.width = Ax.canvasWidth;
  input.height = Ax.canvasHeight;
  
  input.framerate = Ax.framerate;
  
  if(format == "json"){
    return Ext.util.JSON.encode(input);
  }else{
    return input;
  }
}

Ax.import_animation = function(markup){
  if(typeof markup == typeof "tehkooliest"){ //if its in json, then decode it first
    markup = Ext.util.JSON.decode(markup)
  }
  Ax.setAnimationName(markup.name)
  //set the name for the animation in that little box in the toolbar. overly hackish, I know. Seriously, acessing dom?
  Ax.animation.markup = markup;
  
  Ax.canvasWidth = markup.width?markup.width:480
  Ax.canvasHeight = markup.height?markup.height:272
  Ax.canvasSize_core();
  
  Ax.framerate = markup.framerate?markup.framerate:12;
  
  Ax.import_animation_core(markup.layers);
  Ax.selectFrame((markup.tcframe)?markup.tcframe:1,(markup.tclayer)?markup.tclayer:"Layer 1");
  
}

Ax.test_animation_markup = function(markup){
  if(typeof markup != typeof "actionwoot"){
    return false; //its not valid, only takes json formatted string
  }
  try{
    markup = Ext.util.JSON.decode(markup); //attempt to decode
  }catch(err){
    return false;
  }
  if(!markup){
    return false; //its not valid, it didn't get through
  }
  if(typeof markup != typeof ({woot: "ness"})){
    return false; //its not the right type
  }
  if(typeof markup.layers != typeof ({ello: "world"})){
    return false;
  }
  
  return markup;
}

Ax.import_animation_core = function(layers){
  Ax.reloadCanvas_core(); //try resolving some issues;
  
  Ax.viewport.findById("layers").getStore().removeAll(); //remove all entries from layers panel
  Ax.initTimeline(); //reset timeline
  Ax.canvas_storage = {}; //empty canvas storage
  Ax.canvas.unselect();//unselect the canvas, saves a nasty bug
  Ax.canvas.renderer.removeAll(); //clear canvas
  
  
  Ax.layers = {};//reset layers object
  //Ax.tstat = {layers: 0, frames: 0}
  Ax.tstat.layers = 0;

for(var firstlayer in layers){
  Ax.tcurrent.layer = firstlayer;
  Ax.tcurrent.frame = 1;
  Ax.loadShapes(layers[firstlayer].src[1]);
  break;
}  


for(var layer in layers){ //loop through layers
    Ax.addLayer(layer); //add layer
    Ax.layers[layer].keyframes = layers[layer].keyframes; //set keyframes
    Ax.canvas_storage[layer] = layers[layer].src; //load canvas src
    //Ax.loadframe(1, layer); //note: this is a hack!
    //console.log(layers[layer].src);
    for(var i = 0; i < layers[layer].keyframes.sort(function(a,b){return b-a})[0] + 1; i++){
      Ax.selectFrame(i + 1,layer); //render frame to timeline, (renderFrame may be better)
      	if(layers[layer].keyframes.indexOf(i+1) != -1){
		Ax.toKeyframe(i+1, layer)
	}
    }
  }

}

Ax.reload_animation = function(){
  try{
    Ax.import_animation(Ax.export_animation(Ax.animation.markup))
  }catch(err){
    return Ax.msg("Animation Recovery","Animation recovery has failed due to error: "+err)
  }
  Ax.msg("Animation Reloaded","The current animation was reloaded. This hopefully has resolved most issues related to the timeline and other components.")
}




 /*JS File: ../js/data/formatgui.js*/ 


 /*
 * all the remarkably interesting code that displays that box to show you the markup
 * that magical dialog that asks if it wants to steal all your private files on your drive
 * that cool box requesting to steal items on your clipboard
 * that field that attempts to steal your favorite sites
 * that stuff that goes on that tries to carpetbomb your desktop with random aliens :P
 * yep, all that magic takes place..... here.
 */
Ax.autoimport = function(markup){
    var jsonmarkup = Ax.test_animation_markup(markup);
    if (jsonmarkup != false) {
        if (jsonmarkup.revision) {
            if (Math.round(jsonmarkup.revision) > Ax.format.support.max) {
                Ax.msg("Warning! Proof of time travel", "It seems that the animation you are attempting to load was created with a future version of the ajax animator. It may contain data that can not be loaded properly in this version, or may load perfectly fine.")
            }
            if (Math.round(jsonmarkup.revision) < Ax.format.support.min) {
                Ax.msg("Warning!", "The animation you are attempting to load seems to be created by an older, unsupported version. It is more than likely some information here will not load properly.")
            }
        }
        Ax.import_animation(markup);
    }
    else {
        if (markup.indexOf(";;") != -1) {
            Ax.msg("Unable to load animation!", "The animation looks like data from the AXML format used by Ajax Animator 0.14.7 and below. It is not supported natively in this release due to the usage of a new format in 0.20+.")
        }
        else {
            Ax.msg("Unable to load animation!", "The animation could not be loaded because it is malformed. Check the data for corruption, or from an unsupported source.")
        }
    }
}


Ax.animationinfo = function(type){
    //graphically displays metadata in animation, also some statistics, etc.
    
    if (type == "core") {
        return "<b>" + Ax.animation.name + ":</b><br />Generator: " + (Ax.animation.markup.generator ? (Ax.animation.markup.generator.app+" build "+Ax.animation.markup.generator.build) : "Unknown") +
        "<br />Format Version: " +
		(Ax.animation.markup.revision ? Ax.animation.markup.revision : "Unknown") + 
		"<br />Creation Date: " +
        ((Ax.animation.markup.creation) ? Ax.animation.markup.creation : "Unknown") +
        "<br />Last Modified Date: " +
        ((Ax.animation.markup.modified) ? Ax.animation.markup.modified : "Unknown") +
        "<br />Contributors: " +
        ((Ax.animation.markup.contrib) ? Ax.animation.markup.contrib : ['Unknown']).join(",") +
        "<br />Size: " +
        Ax.export_animation(Ax.animation.markup, "json").length +
        "<br />Layers: " +
        Ax.tstat.layers +
        "<br />Frames: " +
        Ax.count_frames()
    }
    
    (new Ext.Window({
        title: "Animation Info - " + Ax.animation.name,
        iconCls: "tb_about",
        width: 300,
        height: 200,
		layout: "fit",
		items: {
			border: false,
 	        html: Ax.animationinfo("core")
		},
        buttons: [{
            text: "Update",
            iconCls: "reload_icon",
            handler: function(){
                this.ownerCt.items.first().body.update(Ax.animationinfo("core"));
				//this.ownerCt.layout.body.update(Ax.animationinfo("core"))
            }
        }, {
            text: "Close",
            iconCls: "close",
            handler: function(){
                this.ownerCt.close()
            }
        }]
    
    })).show(document.body)
}



 /*JS File: ../js/data/save.js*/ 


 /**
 * @author antimatter15
 * 
 * This is pretty cool rite?
 */
 
Ax.save = {
    text: function(){
        (new Ext.Window({
            title: "Save Animation As Text",
            iconCls: "tb_save",
            width: 300,
            height: 300,
            buttons: [{
                text: "Update",
                iconCls: "reload_icon",
                handler: function(){
                    this.ownerCt.findById("outtext").setValue(Ax.export_animation(Ax.animation.markup, "json"))
                }
            }, {
                text: "Close",
                iconCls: "close",
                handler: function(){
                    this.ownerCt.close()
                }
            }],
            layout: "border",
            items: [{
                region: "north",
                border: false,
                html: "You may copy the text below and save it somewhere to open later from the File->Open->From Text menu option."
            }, {
                region: "center",
                layout: "fit",
                border: false,
                items: {
                    id: "outtext",
                    xtype: "textarea",
                    style: "font-size: 9px",
                    value: Ax.export_animation(Ax.animation.markup, "json")
                }
            }]
        })).show(document.body)
    },
    computer: function(data, name, base64){
        Ext.Ajax.request({
            url: Ax.files.save_proxy,
            params: {
                action: "test"
            },
            success: function(e){
                //console.log(e)
                if (e.responseText = "working") {
                    Ax.save.comp_iframe(data, name, base64); //server connection works, try the iframe awesomeness
                }
                else {
                    Ax.save.comp_datauri(data); //apparently the server doesn't work
                }
            },
            failure: function(){
                Ax.save.comp_datauri(data); //the connection failed, so try the datauri method
            }
        })
        
    },
    comp_datauri: function(data, base64){
        window.location = "data:application/octetstream;base64," + base64?data:(Ext.ux.base64.encode((data)?data:Ax.export_animation(Ax.animation.markup, "json")));
    },
    comp_iframe: function(data, name, base64){
        Ax.msg("Saving...", "The request is being processed by the server and may take a long time depending on the size of the animation." +
        "<form id=\"save_form\" method=\"POST\" action=\"" +
        Ax.files.save_proxy +
        "\"><input type=\"hidden\" name=\"encoding\" value=\"" +
		((base64)?"base64":"raw")+
		"\"><input type=\"hidden\" name=\"name\" value=\"" +
        ((name)?name:Ax.animation.name) +
        "\" /><input type=\"hidden\" name=\"action\" value=\"work\" /></form>");
        var new_input = document.createElement("input")
        new_input.type = "hidden";
        new_input.name = "data";
        new_input.value = (data)?data:Ax.export_animation(Ax.animation.markup, "json");
        Ext.get("save_form").dom.appendChild(new_input); //waste of Ext, I know
        Ext.get("save_form").dom.submit();
    }
}


 /*JS File: ../js/data/open.js*/ 


 /**
 * @author antimatter15
 */

 
 Ax.open = {
    text: function(){
        (new Ext.Window({
            title: "Open Animation From Text",
            iconCls: "tb_open",
            width: 300,
            height: 300,
            buttons: [{
                text: "Load",
                iconCls: "load",
                handler: function(){
                    Ax.autoimport(this.ownerCt.findById("loadtext").getValue())
                }
            }, {
                text: "Close",
                iconCls: "close",
                handler: function(){
                    this.ownerCt.close()
                }
            }],
            layout: "border",
            items: [{
                region: "north",
                border: false,
                html: "Paste some data acquired from the save to text button here."
            }, {
                region: "center",
                layout: "fit",
                border: false,
                items: {
                    id: "loadtext",
                    xtype: "textarea",
                    style: "font-size: 9px"
                }
            }]
        })).show(document.body)
    },
    file: function(){
        (new Ext.Window({
            title: "Open Animation From Computer",
            iconCls: "tb_open",
            width: 400,
            height: 105,
            buttons: [{
                text: "Load",
                iconCls: "load",
                handler: function(){
                    //console.log(this.ownerCt.findById("loadform"))
                    this.ownerCt.findById("loadform").form.submit({
                        url: Ax.files.open_proxy,
                        success: function(form, action){
                            Ax.autoimport(Ext.util.JSON.encode(action.result.data))
                        },
                        failure: function(form, action){
                            Ax.toastMsg("Upload Failed", action.failureType + action.result.error +
                            " Animation could not be loaded. If trying again fails, try pasting the file's contents into the Open from Text dialog.")
                        }
                    })
                    Ext.Ajax.request({
                        url: Ax.files.open_proxy,
                        params: {
                            action: "test"
                        },
                        success: function(e){
                     
                            if (e.responseText != "working") {                   
                                Ax.toastMsg("Probable Failure", "Upload handling server appears not to be working")
                            }
                        },
                        failure: function(){
                            Ax.toastMsg("Probable Failure", "Upload handling server appears not to be working")
                        }
                    })
                                       
                }
            }, {
                text: "Close",
                iconCls: "close",
                handler: function(){
                    this.ownerCt.close()
                }
            }],
            border: false,
            items: [{
                layout: "fit",
                html: "Please locate the saved animation from your computer.",
                border: false
            }, {
                border: false,
                id: "loadform",
                xtype: "form",
                fileUpload: true,
                listeners: {
                    beforeaction: function(){
                        Ax.msg("Uploading Data", "The animation file is being uploaded to the server.")
                    }
                },
                items: [{
                    name: "file",
                    xtype: "field",
                    fieldLabel: "Animation File",
                    inputType: "file"
                },{
					name: "action",
					xtype: "hidden",
					value: "work"
				}]
            }]
        })).show(document.body)
    },
    url: function(){
        (new Ext.Window({
            title: "Open Animation From URL",
            iconCls: "tb_open",
            width: 350,
            height: 100,
            buttons: [{
                text: "Load",
                iconCls: "load",
                handler: function(){
					Ext.MessageBox.alert("Functionality Disabled","Loading an animation from an external server has been disabled for (pseudo) security purposes.")
                    //Ax.autoimport(this.ownerCt.findById("loadtext").getValue())
                }
            }, {
                text: "Close",
                iconCls: "close",
                handler: function(){
                    this.ownerCt.close()
                }
            }],
            //layout: "border",
            border: false,
            items: [{
                layout: "fit",
                html: "Place the location of the online resource to load from.",
                border: false
            }, {
                label: "URL",
                id: "loadurl",
                style: "width: 100%",
                xtype: "textfield"
            }]
        })).show(document.body)
    }
}



 /*JS File: ../js/data/export.js*/ 


 /**
 * @author antimatter15
 */



Ax.ex = {}; //short for Ax.export, but sadly aptana goes crazy when i do that, so why not?





 /*JS File: ../js/data/export/array.js*/ 


 /**
 * @author antimatter15
 * This is sorta critical part of the other formats.
 * It makes making other formats easier
 * Especially those incapable of porting the tweening engine to
 */
Ax.ex.array = function(format){ //returns an array of every single frame (single layered) tweened when necessary
    Ax.autodiff(); //read the comment in player.js
    var layers = Ax.export_animation_core(), output = [], frame = 1, total_frames = Ax.count_frames(layers);
    for (;; frame++) {
        output.push([]);
        for (var layer in layers) {
            if (layers[layer].keyframes.indexOf(frame) != -1) {
                output[frame - 1] = output[frame - 1].concat(layers[layer].src[frame])
            }
            else 
                if (Ax.largest_nonempty(frame, layer, layers) && Ax.smallest_nonempty(frame, layer, layers)) {
                    output[frame - 1] = output[frame - 1].concat(Ax.getSFTween(frame, Ax.largest_nonempty(frame, layer, layers), Ax.smallest_nonempty(frame, layer, layers), layer, layers[layer].src))
                }
                else 
                    if (Ax.largest_nonempty(frame, layer, layers)) {
						output[frame - 1] = output[frame - 1].concat(layers[layer].src[Ax.largest_nonempty(frame, layer, layers)])
                    }
                    else {
                    //console.log("blank frame")
                    }
            
            if (frame >= total_frames) {
                if (format == "json") {
                    return Ext.util.JSON.encode(output);
                }
                else {
                    return output;
                }
            }
        }
    }
    //is it possible that an infinite loop finishes?
}

Ax.ex.array.save = function(){
    Ax.msg("Notes on exporting to OnlyPaths JSON Frame List", "Export to OnlyPaths JSON Frame List does not contain layer or tween data.")
    Ax.save.computer(Ext.util.JSON.encode(Ax.ex.array()), Ax.animation.name + ".opf");
}



 /*JS File: ../js/data/export/flash.js*/ 


 /**
 * @author antimatter15
 *
 * Wow! Flash! isn't it all about this these days? Oh wait. wrong version
 * Who cares? Flash is everwhere. It may suck in some ways (cross-platformness)
 * but its better than the competition (*cough* silverlight *cough*)
 * 
 * This probably doesn't make much sense. I can't even make sense of this.
 * But IDK. this is just another comment on comments, which is now a commment on commments on comments
 * because meta-thinking is good, metacommenting should also be good.
 */
Ax.ex.swf = function(){ //normally this actually does something, but this is a rare occasion where nothign happens
    return false; //boo hoo
}

Ax.ex.swf.save = function(){ //savenessy
    Ax.msg("Notes on exporting to Flash", "Export to flash currently uses the limited freemovie library. Better flash export will be available later using another library such as Transform SWF. ");    
    Ax.ex.swf.check(); //start the magickal process
}


Ax.ex.swf.check = function(){
    Ext.Ajax.request({
        url: Ax.files.export_swf, //the magickal server
        params: {
            "action": "test" //I say magickal too much don't I?
        },
        success: function(e){ //when the magickalness happens
            if (e.responseText != "working") { //lets test if its working
                Ax.ex.swf.connect_fail(); //waaah! Its failing!
            } 
            else {
                //woot it passed preliminary tests!
                Ax.ex.swf.upload(); //awesome insane wootness!
            }
        },
        failure: function(){
            Ax.ex.swf.connect_fail(); //oh. sure. I don't believe you. If it fails then it fails? Nonsense
        }
        
    })
}

Ax.ex.swf.upload = function(){ //where the cool stuff happens
    Ext.Ajax.request({ //do Ajaxy stuffs
        url: Ax.files.export_swf, //uh, same file
        params: {
            "action": "work", //WORK!
            "animation": Ax.ex.array("json") //okay, so I did it, I made Ax.ex.array("json").
        },
        success: function(e){ //YESs!
            Ax.save.computer(e.responseText, Ax.animation.name + ".swf", true); //save to computer using magikalness
        },
        failure: function(){
            Ax.ex.swf.connect_fail(); //what? its not supposed to happen! I already did preliminary tests! or... did you cheat?
        }
    })
}

Ax.ex.swf.connect_fail = function(){
    Ax.toastMsg("Error!", "Connection to SWF (Flash) compilier failed!"); //YOU PHAIL!
}



 /*JS File: ../js/data/export/silverlight.js*/ 


 /**
 * @author antimatter15
 * 
 * I really don't care about silverlight, but its a nifty feature to brag about
 */




Ax.ex.silverlight = function(){
    var data = Ax.ex.array(), //the magic behind it all;
 setup = '<Canvas xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">\n', //my little header
	draw = ""
    for (var i = 0; i < data.length; i++) {
		content = [];
        for (var s = 0; s < data[i].length; s++) {            
            switch (data[i][s].type) {
                case "line":
                    content.push(Ax.ex.silverlight.line(data[i][s]))
                    break;
                case "rect":
                    content.push(Ax.ex.silverlight.rect(data[i][s]))
                    break;
				case "ellipse":
					content.push(Ax.ex.silverlight.ellipse(data[i][s]))
					break;
				case "path":
					content.push(Ax.ex.silverlight.path(data[i][s]))
					break;
				case "text":
					content.push(Ax.ex.silverlight.text(data[i][s]))
					break;
				case "image":
					content.push(Ax.ex.silverlight.image(data[i][s]))
					break;
            }
        }
		draw += content.join("\n")+"\n";
    }
    return setup + draw + "</Canvas>";
}

    
Ax.ex.silverlight.line = function(shape){
	return new Ext.XTemplate('<Line X1="{left}" Y1="{top}" Fill="{fillColor}" Stroke="{lineColor}" X2="{[values.left+values.width]}" Y2="{[values.top+values.height]}"  StrokeThickness="{lineWidth}" />').apply(shape)
}

Ax.ex.silverlight.rect = function(shape){
	return new Ext.XTemplate('<Rectangle Canvas.Left="{left}" Canvas.Top="{top}" Fill="{fillColor}" Stroke="{lineColor}" Width="{width}" Height="{height}" StrokeThickness="{lineWidth}"><Rectangle.RenderTransform><RotateTransform Angle="{[Ax.parseTransform(values.transform)[0]]}"/></Rectangle.RenderTransform></Rectangle>').apply(shape)
}

Ax.ex.silverlight.path = function(shape){
	return new Ext.XTemplate('<Path Data="{points}"  Fill="{fillColor}" Stroke="{lineColor}" StrokeThickness="{lineWidth}" />').apply(shape)
}

Ax.ex.silverlight.text = function(shape){
	return new Ext.XTemplate('<TextBlock FontSize="{textSize}" Fill="{fillColor}" Stroke="{lineColor}"  FontFamily="{textFamily}" Canvas.Left="{left}" Canvas.Top="{top}">{text}</TextBlock>').apply(shape)
}

Ax.ex.silverlight.image = function(shape){
	return new Ext.XTemplate('<Rectangle Canvas.Left="{left}" Canvas.Top="{top}" Width="{width}" Height="{height}"><Rectangle.Fill><ImageBrush ImageSource="{href}" /></Rectangle.Fill></Rectangle>').apply(shape)
}

Ax.ex.silverlight.ellipse = function(shape){
	return new Ext.XTemplate('<Ellipse Canvas.Left="{left}" Fill="{fillColor}" Stroke="{lineColor}" StrokeThickness="{lineWidth}" Canvas.Top="{top}" Width="{width}" Height="{height}" />').apply(shape)

}
Ax.ex.silverlight.save = function(){
	//return Ax.save.computer(Ax.ex.silverlight(),Ax.animation.name+".xaml")
	Ax.msg("Notes on exporting to Silverlight (XAML)","Export to Silverlight is not complete, animations will be condensed to a single canvas of overlapping shapes and some shape data may not be exported.");
	Ax.save.computer(Ax.ex.processing(),Ax.animation.name+".pde")
}



 /*JS File: ../js/data/export/javafx.js*/ 


 /**
 * El Wootyness!
 * Uh... Java
 * So?
 * Um
 * hai
 * I don't actually know java.
 * oh crap.
 * @author Kevin
 */


Ax.ex.javafx = function(){
	
}

Ax.ex.javafx.save = function(){

	Ext.MessageBox.alert("JavaFX Export Not Available","We have not finished implementing JavaFX export.")	
}




 /*JS File: ../js/data/export/processing.js*/ 


 /**
 * @author antimatter15
 * I'm only making this because this is a cool language
 * I wouldn't even know about Processing if not for John Resig's Processing.JS
 * so yeah, this is sorta intended to be played on processing.js
 */

Ax.ex.processing = function(){
    var data = Ax.ex.array(), //the magic behind it all;
 setup = ["//The compilier for this was quickly hacked together", //my little header
 "int frame = 0;\nint frame_total = "+data.length+";", //some variable declarations
 "void setup(){", //the function start
 "size(480, 272);", //set the size of the canvas
 "frameRate(12);", //set the framerate (fps)
 "smooth();",
 "}\n"].join("\n"), //end the function
    content = [], //the magical content
    draw = ["void draw(){", //declare function
	"if(frame != frame_total){", //if its not the last frmae
	"frame += 1;", //increment it
	"}else{", //but itf it is the last frame
	"frame = 1;", //reset
	"}", //end if
	 "background(#FFFFFF);", //reset the canvas
	 "switch(frame){\n"
	 ].join("\n")
	
    for (var i = 0; i < data.length; i++) {
		content = [];
        for (var s = 0; s < data[i].length; s++) {
            content.push(Ax.ex.processing.stroke(data[i][s]))
            content.push(Ax.ex.processing.strokewidth(data[i][s]))
            content.push(Ax.ex.processing.fill(data[i][s]))
            
            switch (data[i][s].type) {
                case "line":
                    content.push(Ax.ex.processing.line(data[i][s]))
                    break;
                case "rect":
                    content.push(Ax.ex.processing.rect(data[i][s]))
                    break;
				case "ellipse":
					content.push(Ax.ex.processing.ellipse(data[i][s]))
					break;
				case "text":
					content.push(Ax.ex.processing.text(data[i][s]));
					break;
            }
        }
		draw += "case "+(i+1)+":\n"+content.join("\n")+"\nbreak;\n";
    }
    return setup + draw+"}\n}";
}
Ax.ex.processing.stroke = function(shape){
    return "stroke(" + shape.lineColor + ");";
}

Ax.ex.processing.strokewidth = function(shape){
    return "strokeWeight(" + shape.lineWidth + ");";
}

Ax.ex.processing.fill = function(shape){
    return "fill(" + shape.fillColor + ");";
}

Ax.ex.processing.line = function(shape){
    return "line(" +[shape.left,shape.top,shape.left+shape.width,shape.top+shape.height].join(", ") + ");";
}
Ax.ex.processing.text = function(shape){
    return "text(" +['"'+shape.text+'"',shape.left,shape.top].join(", ") + ");";
}

Ax.ex.processing.rect = function(shape){
    return "rect(" +[shape.left,shape.top,shape.width,shape.height] .join(", ") + ");";
}

Ax.ex.processing.ellipse = function(shape){
    return "ellipse(" +[shape.left,shape.top,shape.width,shape.height] .join(", ") + ");";
}
Ax.ex.processing.save = function(){
	Ax.msg("Notes on exporting to Processing","Export to processing is not complete, data such as images, paths, polygons, and rotation will not be exported.");
	Ax.save.computer(Ax.ex.processing(),Ax.animation.name+".pde")
}



 /*JS File: ../js/data/export/gif.js*/ 


 /**
 * @author antimatter15
 *
 * Why not? Its good to bridge Vector and Raster tech.
 * 
 * GIF is awesome, APNG is better, but nothing supports it
 * so whatever. GIF is here to stay, and its partly to blame
 * on IE 6.0 which sucks at transparent PNGs. darn you MSFT!
 */
Ax.ex.gif = function(){
    return false;//it turns out that the SWF generator was a copy+paste of this one.
    //but i decided to comment that one and ..... abandon this one. :(
}

Ax.ex.gif.save = function(){
    Ax.msg("Notes on exporting to Animated GIF", "Export to Animated GIF is not complete, data such as images and rotation will not be exported.")
    Ax.ex.gif.check(); //start the process
}


Ax.ex.gif.check = function(){
    Ext.Ajax.request({
        url: Ax.files.export_gif,
        params: {
            "action": "test"
        },
        success: function(e){
            if (e.responseText != "working") {
                Ax.ex.gif.connect_fail()
            }
            else {
                //woot it passed preliminary tests!
                Ax.ex.gif.upload();
            }
        },
        failure: function(){
            Ax.ex.gif.connect_fail(); //you know what would be really hardcore? making a rant and posting it here.
            /*
             * The folllowing space is reserved for a random rant.
             */
        }
        
    })
}

Ax.ex.gif.upload = function(){
    Ext.Ajax.request({
        url: Ax.files.export_gif,
        params: {
            "action": "work",
            "animation": Ax.ex.array("json")
        },
        success: function(e){
            Ax.save.computer(e.responseText, Ax.animation.name + ".gif", true);
        },
        failure: function(){
            Ax.ex.gif.connect_fail()
        }
    })
}

Ax.ex.gif.connect_fail = function(){
    Ax.toastMsg("Error!", "Connection to GIF compilier failed!")
}




 /*JS File: ../js/misc/help/tips.js*/ 


 /*
 * those random helpful usage tips window(s) that pops up for no apparent reason. demonstrating common sense.
 * i donno, they're probably somewhat helpful. and guessing that nobody other than me really uses it as much
 * as me, or nobody really knows special tricks that I know..... whatever. anyway. this isn't really helpful
 * is it?
 *
 * I'll try to copy something *good* like krita or the gimp for the layout for this thing.
 * I'm debating whether I should make this appear when you start it. woudl that work?
 * I'm probably talking to my self right now. and hopefully nobody will read this. but you nver know.
 */
//.... yes i did..... i totally copied Kate :P

Ax.tips_array = [];

Ax.showTips = function(){
    if (!Ax.tipsWindow) {
        Ax.tipsWindow = new Ext.Window({
            title: "Tip of the Day - Ajax Animator",
            iconCls: "tb_tip",
            layout: "border",
            width: 300,
            height: 200,
			minimizable: true,
            items: [{
                region: "north",
                html: "<center><h1 class='tiptitle'>Did you know...?</h1></center><br>",
                border: false
            }, {
                region: "center",
                html: Ax.getTipData(),
                border: false
            }],
            buttons: [{
                text: "Previous",
                iconCls: "arrow_prev",
				handler: function(){
					Ax.tipIndex--;
					this.ownerCt.layout.center.panel.body.update(Ax.getTipData())
				}
            }, {
                text: "Next",
                iconCls: "arrow_next",
                handler: function(){
					Ax.tipIndex = (Ax.tipIndex+1) % Ax.tips_array.length
                    this.ownerCt.layout.center.panel.body.update(Ax.getTipData())
                }
            }, {
                text: "Close",
                iconCls: "close",
                handler: function(){
                    this.ownerCt.close()
                }
            }]
        })
    	Ax.tipsWindow.on("minimize", function(){
			Ax.tipsWindow.toggleCollapse();
		})
		Ax.tipsWindow.on("beforeclose", function(){
			Ax.tipsWindow.hide();
			return false;
		})
	}
    Ax.tipsWindow.show(/*document.body*/)
}


Ax.getTipData = function(){
    
    if (!Ax.tipIndex) {
	
	//var today = 
	
	Ax.tipIndex = Math.floor( //floor it
	((new Date()).getTime() //get today's date
	- 2*2*2*2*2*3*3*42227*100000//Yes, I have an iPhone
	)/( //divide it by
	1000*60*60*24//A Day
	) % Ax.tips_array.length); //and get the remainder
    }
    return "<center>" + Ax.tips_array[Ax.tipIndex] + "</center>";
}



 /*JS File: ../js/misc/help/about.js*/ 


 Ax.About = function(){
//Ax.gs(6);

var aboutWindow = new Ext.Window({
    closable: true,
	iconCls: "tb_about",
    width: 410,
    height: 300,
    minimizable: true,
	title: "About Ajax Animator",
    border: false,
    plain: true,
    layout: 'border',
    buttons: [{
        text: 'Close',
        iconCls: "close",
        handler: function(){
            aboutWindow.close();
        }
    }],
    items: [{
	region: "north",
	baseCls: "ajaxanimator_logo",
	height: 70
	},{
	xtype: "tabpanel",
    region: 'center',
    margins: '3 3 3 0', 
    activeTab: 0,
    defaults: {autoScroll:true},
 
    items:[{
        title: 'Version',
		html: "<b>Ajax Animator "+Ax.v.release+"</b>"+"<br />"+
    "App Name: "+Ax.v.app+"<br />"+
		"Release: "+Ax.v.release+"<br />"+
    "Stability: "+Ax.v.stability+"<br />"+
		"Build: "+Ax.v.build+"<br />"+
    "Format revision: "+Ax.format.revision+"<br />"+
    "Format Revision Support: "+Ax.format.support.min + " - "+Ax.format.support.max+"<br />"+
    "OnlyPaths Version: "+Ax.onlypaths.version+"<br />"+
		"Testing: "+Ax.v.dev+"<br />"+
		"Release Date: "+Date.parseDate(Math.round(Ax.v.date),"U")+" ("+Ax.v.date+")<br />"+
		""
    },{
        title: 'Credits',
        html: '<b>Developers</b><br />'+
		'Antimatter15<br />'+
		"<b>Documentation</b><br />"+
		"Antimatter15<br />"+
		"Bruce Wainer (Brwainer) - Manual<br />"+
		"RandomProductions - FAQ<br />"+		
		"<b>Libraries/Extensions</b><br />"+
		'<i>Note: This is not a fully comprehensive list of everything used</i><br />'+
		'Ext v2.1 (http://extjs.com)<br />'+
		'Ext 2.x themes by Galdaka, J.C., madrabaz, and elyxr<br />'+
		'Ext.ux.ToastWindow by efattal<br />'+
		'Ext.ux.Crypto by vtswingkid<br />'+
		'<b>Patches/Bugfixes</b><br />'+
		'http://extjs.com/forum/showthread.php?p=146135<br />'+
		'http://outroot.com/extjs/bug1/<br />'+ 
		'<b>Images/Icons</b><br />'+
		'Logo by Antimatter15<br />'+
		'Icons from silk by famfamfam<br />'+
		'Icons from richdraw by Mark Finkle<br />'+
		'Loading icon from ajaxload.info<br />'+
    '<b>OnlyPaths</b><br />'+
    'Icons from OnlyPaths by josep_ssv<br />'+
    'OnlyPaths by josep_ssv<br />'+
    'RichDraw by Mark Finkle<br />'+
    'Sylvester by James Coglan<br />'
    },{
	title: "Special Thanks",
	html: "<b>Organizations</b><br />"+
	"liveswifers.org for their supportive community, and helping this project get started<br />"+
	"110mb.com hosting, for their reliability, cost (none), and helpful community<br />"+
	"Google Code for svn and project hosting - and just being awesome<br />"+
	"Extjs.com forums for excellent support<br />"+
	"<b>People</b><br />"+
	"inportb from 110mb forums for commentary<br />"+
	"brwainer from liveswifers.org for initial documentation, ideas, and suggestions<br />"+
	"BenjaminJ from liveswifers.org for support and ideas<br />"+
	"Brent Clancy (brclancy111/liveswif-050) for base login system<br />"+
	"RandomProductions for suggestions, fonts, and ideas<br />"+
	"OutOfLine for nice comments and motivation<br />"+
	"shanep for creating a forum for the project on liveswifers forums<br />"+
	""
	},{
		title: 'License',
		//autoLoad: "gpl-3.0-standalone.html"
		html: "GPL v3 (http://www.gnu.org/licenses/gpl-3.0.txt) <br /><br />"+Ax.gpl+" <br /><br /><i>Please don't sue me</i>"
	}]
}]
});
 
aboutWindow.on('minimize', function(){
    aboutWindow.toggleCollapse();
});

aboutWindow.show();
}

Ax.gpl = 
"This program is free software: you can redistribute it and/or modify"+"<br />"+
"it under the terms of the GNU General Public License as published by"+"<br />"+
"the Free Software Foundation, either version 3 of the License, or"+"<br />"+
"(at your option) any later version."+"<br />"+
"<br /><br />"+
"This program is distributed in the hope that it will be useful,"+"<br />"+
"but WITHOUT ANY WARRANTY; without even the implied warranty of"+"<br />"+
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the"+"<br />"+
"GNU General Public License for more details."+"<br />"+
"<br /><br />"+
"You should have received a copy of the GNU General Public License"+"<br />"+
"along with this program.  If not, see http://www.gnu.org/licenses/.";




 /*JS File: ../js/misc/help/help.js*/ 


 Ax.keys = { //An object with the key arrays that will be generated and converted into something user-readable

  "F5": "Insert Frame",
  "F6": "To Keyframe",
  "F7": "Empty Frame",
  "Enter": "Preview/Play",
  "Page Up": "Go to Previous Frame",
  "Page Down": "Go to Next frame",
  "Delete":"Delete Selection",
  "Ctrl+C": "Copy",
  "Ctrl+X": "Cut",
  "Ctrl+V": "Paste",
  "Ctrl+Z": "Undo",
  "Ctrl+Shift+Z": "Redo"
}
//..... hey.... wait.... what? I can read this.... Does this mean I'm not human?

Ax.keyGuide = function(){ //magickallyawesome function
//Ax.gs(5); //report user statistics
var generatedguide = "";
for(var x in Ax.keys){ //generate the magical human-readable stuff
  generatedguide += "<b>"+x+"</b> "+Ax.keys[x]+"<br>";
}
//oh wait... is it not human readable already? am i not human?
Ext.MessageBox.alert("Keyboard Shortcuts",generatedguide)
}





 /*JS File: ../js/misc/help/docs.js*/ 


 /*
Documentation (FAQ, Manual, Etc.)
*/

Ax.loadTab = function(object){
Ax.viewport.findById("maintabpanel").add(object).show()
}

Ax.loadFAQ = function(){
Ax.loadTab({xtype: "faq"})
//Ax.gs(2);
}
Ax.loadManual = function(){
Ax.loadTab({xtype: "manual"})
//Ax.gs(3);
}


Ax.FAQ = Ext.extend(Ext.Panel,{
initComponent: function(){
Ext.apply(this,{
	title: "FAQ",

	closable: true,
	iconCls: "tb_docs",
	layout: "fit",
	border: false,
	items: {
	title: "FAQ",
	border: true,
		cls: "docs",
	iconCls: "tb_docs",
	bodyStyle: "overflow: auto;",
	autoLoad: {
		url: Ax.files.faq
	}
	}
	
  })
   Ax.FAQ.superclass.initComponent.apply(this, arguments);
  }
  })
  
Ext.reg("faq",Ax.FAQ)

Ax.Manual = Ext.extend(Ext.Panel,{
initComponent: function(){
Ext.apply(this,{
	title: "Manual",
	closable: true,
	iconCls: "tb_docs",
	layout: "fit",
	border: false,
	items: {
	title: "Manual",
	border: true,
	iconCls: "tb_docs",
	cls: "docs",
	autoLoad: {
		url: Ax.files.manual
	}
	}
	
  })

   Ax.Manual.superclass.initComponent.apply(this, arguments);
  }
  })
  
Ext.reg("manual",Ax.Manual)


 /*JS File: ../js/misc/help/bugs.js*/ 


 Ax.BugReport = function(){
	return Ax.msg("Not Available","This feature is not available");
	
//Ax.gs(4);
var ErrorWindow = new Ext.Window({
    closable: true,
    width: 410,
    height: 300,
    minimizable: true,
	  title: "Report Bug",
    border: false,
    plain: true,
    layout: 'border',
    buttons: [
	
	{
        text: 'Cancel',
        handler: function(){
            ErrorWindow.close();
        }
    },{
		text: 'Send (recomended)',
		handler: function(){
			Ax.msg("Sending Bug Report","We are sending your bug report... Or at least we'll make you think we are.");
			ErrorWindow.close();
		}
	}
	
	],
    items: [{
	split: true,
	height: 80,
	region: "north",
	html: "Hai"
	},{
	region: "center",
	html: "scarey"
}]
});
 
ErrorWindow.on('minimize', function(){
    ErrorWindow.toggleCollapse();
});

ErrorWindow.show();
}


//onerror = Ax.Error

Ax.comment = function(){
Ax.msg("Not Available","This feature is not available");
}

Ax.donate = function(){
Ext.MessageBox.alert("Helping the Ajax Animator","If you enjoy using the Ajax Animator and would like to help assist the project, please use the ad-supported version, report bugs, comment on desired features and spread the word.");
}



 /*JS File: ../js/misc/help/tutorials.js*/ 


 /**
 * @author Kevin
 */

Ax.tutorials_unavailable = function(){
	Ext.MessageBox.alert("Interactive Tutorials Unavaliable","Sorry, this feature is not finished yet.")
}



 /*JS File: ../js/misc/help/tipdata.js*/ 


 Ax.tips_array = [//do not mind this poopy!

"Double click on the bar between the canvas and the timeline to hide the timeline."
,
"If the canvas starts to act awkwardly or fails to work at all, head over to <b>Tools->Recovery->Reload Canvas</b> and Ajax Animator will automatically try to restart the component. Don't worry, it captures the state of your current canvas and restores, so no work will be lost."
,
"If you ever experience problems in random components, you can try reloading the animation. From the <b>Tools->Recovery</b> menu, press the <b>Reload Animation</b> button, and it'll try to rescue your project from the evils of buggy-land."
,
"In the animation browser, or inside preview, you can press <b>Play</b> multiple times for faster playback. Be sure to press <b>Pause/Stop</b> multiple times before going to another tab though!"
,
"To make the paths you draw look more fluid, set the <b>Snapping Grid</b> (in the toolbox) to <b>1px</b>. It also gives you greater percision in control over shapes, but makes it harder to create any two shapes that are exactly the same size."
,
"You can quickly convert a frame to a keyframe by right-clicking on it in the <b>timeline</b> and selecting <b>To Keyframe</b> from the context menu."
,
"The text based format used by ajax animator can almost be modified by hand. It is really not too complex."
,
"Publish (Export) to Processing, Silverlight and the Ajax Animator File Format can work offline."
,
"The application is keyboard enabled. You can use common keystroke combinations to do various actions. Go to <b>Help->Keyboard Shortcuts</b> for details"
,
"You can tween almost any attribute of any shape, from stroke thickness, location, size, color, and opacity."
,
"Click on the <b>Zoom</b> label on the canvas to reset the zoom to 100% (Default)"
,
"If you are working on a big animation project and it causes Ajax Animator to run slow, try splitting it up to smaller scenes."
,
"The informal grey boxes that appear occasionally can be removed simply by clicking on them."
] //dont min dis little insignifigant character


 /*JS File: ../js/misc/server.js*/ 


 /**
 * I sorta wish I knew scriptdoc...
 * but anywho, this (for now) checks wheter the server works
 * @author Kevin
 */

Ax.testserver = function(reset){
	if(reset){
		Ax.server_working = null;
	}
    if (!Ax.server_working) {
        Ext.Ajax.request({
            url: Ax.files.test+"?m=working",
			method: "get",
            success: function(e){
                if (e.responseText.indexOf("working") != -1) {
                    Ax.server_working = true;
                }
                else {
                    Ax.server_working = false;
                }
            },
            failure: function(){
                Ax.server_working = false;
            }
        })
    }
    return Ax.server_working;
}


 /*JS File: ../js/misc/prefs.js*/ 


 Ax.urlprefs = Ext.urlDecode(window.location.search.substr(1));


 /*JS File: ../js/misc/usage.js*/ 


 //Usage statistics of the applicaiton

/*
Ax.ustat = [];

Ax.gs = function(){
for(var i = 0; i < arguments.length; i++){
Ax.ustat.push(arguments[i])
}
}

//That's all folks!

//...okay... i lied, there's some more stat processing code...

Ax.ls = function(){
return Ax.ustat
}

*/



 /*JS File: ../js/misc/message.js*/ 


 /*awesome little grey boxes that fall from the sky... stolen from Ext docs */

Ax.createBox = function(t, s){
        return ['<div class="msg">',
                '<div class="x-box-tl"><div class="x-box-tr"><div class="x-box-tc"></div></div></div>',
                '<div class="x-box-ml"><div class="x-box-mr"><div class="x-box-mc"><h3>', t, '</h3>', s, '</div></div></div>',
                '<div class="x-box-bl"><div class="x-box-br"><div class="x-box-bc"></div></div></div>',
                '</div>'].join('');
}
   
Ax.msg = function(title, format){
    if(!Ax.msgCt){
        Ax.msgCt = Ext.DomHelper.insertFirst(document.body, {id:'msg-div'}, true);
    }
    Ax.msgCt.alignTo(document, 't-t');
    var s = String.format.apply(String, Array.prototype.slice.call(arguments, 1));
    var m = Ext.DomHelper.append(Ax.msgCt, {html:Ax.createBox(title, s)}, true);
	m.on("click",function(){
		Ext.get(m).remove();
		//console.log(arguments)
	})
    m.slideIn('t').pause(10).ghost("t", {remove:true});
}

Ax.toastMsg = function(title, content, icon){
      new Ext.ux.ToastWindow({
        title: title,
        html: content,
        iconCls: (icon)?icon:'error'
      }).show(document);  
}


 /*JS File: ../js/misc/misc.js*/ 


 /*
A whole lot of random scripts
*/

/*
Ax.len = function(obj){ //really useful...
	var length;
	for(var i in obj){
		length++;
	}
	return length;
}
*/

Ax.macroExec = function(){
  (new Ext.Window({
    title: "Execute Macros/Scripts",
    iconCls: "tb_script",
    width: 300,
    height: 300,
    buttons: [{text: "Execute" , iconCls: "execute",handler: function(){eval(this.ownerCt.findById("loadtext").getValue())}},
              {text: "Close", iconCls: "close", handler: function(){this.ownerCt.close()}}],
    layout: "border",
    items: [{
      region: "north",
      border: false,
      html: "Here, you can run scripts, hacks or any javascript code."
      },{
        region: "center",
        layout: "fit",
        border: false,
        items: {
          id: "loadtext",
          xtype: "textarea",
          style: "font-size: 9px"
        }
        }]
    })).show(document.body)
}

Ax.offline = function(){
	Ext.MessageBox.alert("Offline Functionality Not Availiable","Offline is not availiable but most of the application should operate fine while using your browser's offline feature (if available) if icons, CSS, and scripts are properly cached. While offline, some functionality that require a server will not work such as anything User/Login, browsing user animations, and publishing to Flash/GIF.")
}



 /*JS File: ../js/misc/api.js*/ 


 //creates an api for macros
/*
* concept:
* dumps all shapes on the current canvas
* loops through all shapes
* feeds into a certain function, returns processed data
*/



Ax.api = {
  loop: {
    "frame": function(macrofunc){
      var dump = Ax.dumpshapes();
      for(var i = 0; i < dump.length; i++){
        dump[i] = macrofunc(dump[i]);
      }
      Ax.canvas.renderer.removeAll();
      Ax.loadShapes(dump);
    },
    "number": function(number,macrofunc){
      for(var i = 0; i < number; i++){
        macrofunc(i)
      }
    }
  },
  transform: {
    "translate": function(shape, x, y){
      shape.top += y;
      shape.left += x;
      return shape;
    },
    "absolute": function(shape, x, y){
      shape.top = y;
      shape.left = x;
      return shape;
    }
  },
  create: {
    shape: function(src){
      Ax.loadShape(src);
    },
    rect: function(x, y, width, height){
      Ax.canvas.renderer.create("rect", Ax.Color.fill, Ax.Color.line, Ax.Color.lineWidth, x, y, width, height)
    }
  }
}

Ax.exec = function(name){
  if(typeof Ax.plugins[name] == "function"){
    Ax.plugins[name]();
    Ax.autodiff();
  }else{
    Ax.toastMsg("Error!","Plugin Not Found!")
  }
}



 /*JS File: ../js/misc/plugins.js*/ 


 /*
* sample macros
* using the macro api
*/

Ax.plugins = {}

Ax.plugins["Wave"] = function(mx,my){
  Ax.api.loop.frame(function(shape){
    return Ax.api.transform.translate(shape,0,mx*Math.sin(shape.left/shape.width*my))
  })
}

Ax.plugins["Brick Wall"] = function(sx, sy, height, width, brickheight, brickwidth){
  for(var x = 0; x < width; x++){
    for(var y = 0; y < height; y++){
      Ax.api.create.shape({
        type: "rect",
        top: sy+(y*brickheight),
        left: sx+(x*brickwidth),
        width: brickwidth,
        height: brickheight
        });
    }
  }
}



Ax.plugins["Explode"] = function(){
  Ax.api.loop.frame(function(shape){
    return Ax.api.transform.absolute(shape, Math.round(Math.random()*(Ax.canvasHeight-shape.height)), Math.round(Math.random()*(Ax.canvasWidth-shape.width)));  
  })
}

Ax.plugins["Random Shape"] = function(){
  Ax.api.create.shape({
    type: "rect",
    top: Math.random()*Ax.canvasHeight,
    left: Math.random()*Ax.canvasWidth,
    width: Math.random()*Ax.canvasHeight,
    height: Math.random()*Ax.canvasHeight,
	fillColor: "#"+Ax.toHex(Math.random()*255)+Ax.toHex(Math.random()*255)+Ax.toHex(Math.random()*255),
	lineColor: "#"+Ax.toHex(Math.random()*255)+Ax.toHex(Math.random()*255)+Ax.toHex(Math.random()*255),
	lineWidth: Math.random() * 20
  });
}

Ax.plugins_unavailable = function(){
	Ax.msg("Not Available","This feature is not available.")
}




 /*JS File: ../js/misc/keyboard.js*/ 


 Ext.onReady(function(){
  Ax.keymap = new Ext.KeyMap(document, [
    {
      key: 117, //F6
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.toKeyframe()}
    },
    {
      key: 116, //F5
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.insertFrame()}
    },
    {
      key: 118, //F7
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.toBlank()}
    },
    {
      key: 13, //Enter
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.controls.play()}
    },
    {
      key: 33, //Page Up
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.controls.previous()}
    },
    {
      key: 46, //Delete
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.setTool("delete")}
    },
    {
      key: 34, //Page Down
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.controls.next()}
    },
    {
      key: "c", //Ctrl+C
      ctrl: true,
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.clipboard_copy()}
    },
    {
      key: "x", //Ctrl+X
      ctrl: true,
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.clipboard_cut()}
    },
    {
      key: "v", //Ctrl+V
      ctrl: true,
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.clipboard_paste()}
    },
    {
      key: "z", //Ctrl+Z
      ctrl: true,
      shift: false,
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};if(event.shiftKey==false){Ax.history_undo()}}
    },
    {
      key: "z", //Ctrl+Shift+Z 
      ctrl: true,
      shift: true,
      fn: function(code, event){if(!Ax.verify_keydown(code, event)){return};Ax.history_redo()}
    }
  ])
  })


Ax.verify_keydown = function(code, event){ //koolio! this is sssooooooo much better than that old one! actually, come to think of it.. now it's sorta complex...

  if([116, 117, 118].indexOf(code) != -1){//if its one of the "banned" keycodes, such as F5 (reloads page), ALWAYS stop it's default behavior
    event.stopEvent();//stop default behavior
  }
  
  var selectedText;  //stolen and modified from quirksmode
  if (window.getSelection) {
    selectedText = window.getSelection().toString();
  }else if (document.selection) { //I3 suxx0rz
    selectedText = document.selection.createRange();
  }
  if(selectedText.length > 1){return} //don't continue if there's anything in the selection
  
  if(['input','textarea'].indexOf(event.getTarget().tagName.toLowerCase()) == -1){ //ignore everything if it's a text element
      event.stopEvent();//yep..
      return true; //oooo
  }
  return;
  //console.log(event);
}


 /*JS File: ../js/misc/end.js*/ 


 Ext.onReady(function(){
    setTimeout(function(){
        Ext.get('loading').remove();
        Ext.get('loading-mask').fadeOut({
            remove: true
        });
        
        setTimeout(function(){
            Ax.initTimeline()
            Ax.addLayer()
            Ax.addFrames(99)
            if (Ax.urlprefs.draw != "false") {
                //Ax.preinit();
                Ax.drawinit();
            }
            //Main Timeline initialization stuff, create, add alyer, add frames, select first one..
            
            Ax.selectFrame(1, "Layer 1")
            //new Ext.ux.ToastWindow({delay: 1000});
			
            setTimeout(function(){
            
                //Ax.showTips();
                if (!window.developer) {
					if (Ax.v.dev) {
						//Ax.gs(1);
						
						new Ext.ux.ToastWindow({
							title: 'Testing Release',
							
							html: 'You are running an unstable testing release. ' +
							'It is not intended for normal use. Please report bugs and post ' +
							'comments about this release (build ' +
							Ax.v.build +
							') frequently. Happy Testing!'
						}).show(document);
					}
					else {
						new Ext.ux.ToastWindow({
							title: 'Beta Release',
							delay: 10000,
							html: "There's a reason it's beta, there may be <i>a lot</i> of bugs, some more annoying than others. "+
							"So please report bugs, post comments, and be a nice person."
						}).show(document);
					}
					
					if (Ext.isIE) {//you know I miss the days of saying "Error: YOUR BROWSER SUCKS!"
						Ext.MessageBox.alert("Notes on Microsoft Internet Explorer", "Currently, support for Microsoft Internet Explorer (6/7/8) are only experimental. Some features do not work properly such as animation and playback of some specific animations. The issues are being fixed, but in the mean time, you may try out another browser such as <a href='http://getfirefox.com'>Firefox</a>, <a href='http://opera.com'>Opera</a>, or <a href='http://apple.com/safari'>Safari</a>.")
					}
					else {
						Ax.showTips();
					}
				}
                
            }, 100)
            /*
            setTimeout(function(){
               // Ax.testserver();
                //really, this does nothing, so it shouldn't be used.
            }, 500)
			*/
        }, 150);
        
        
        
    }, 250);
})
