//  Copyright (2010-2013) Cédric Coussinet (cedric.coussinet@nomoseed.net)
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published
//  by the Free Software Foundation, version 2 of the License.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program. If not, see <http://www.gnu.org/licenses/>

var PI2 = 2 * Math.PI;

var rToD = 180 / Math.PI;
	
var dToR = 1 / rToD;
	
var atan2 = function (y,x)
{
	var r = Math.atan2(y,x);
	if (r<0)
		return -r;
	else
		return PI2 - r;
}

var nomoClickDelay = 500;  // doubleclick
var nomoEventSearch = null;
var nomoEventSelect = null;
var nomoEventChange = null;
var nomoEventOpen = null;

var nomoWorkspaces = new Array();

function nomoNsResolver(prefix) {
  var ns = {
    "project" : "http://www.nomoseed.org/project",
	"model" : "http://www.nomoseed.org/model",
	"svg" : "http://www.w3.org/2000/svg",
	"xlink" : "http://www.w3.org/1999/xlink",
  };
  return ns[prefix] || null;
}

var xhttp = new XMLHttpRequest();
function loadXML(dname){
	xhttp.open("GET",dname,false);
	xhttp.send("");
	return xhttp.responseXML;
}

function nomoInitializeEditor (){
	CodeMirror.xmlHints['<program><'] = [
          'header xmlns="http://www.nomoseed.org/project">\n<author/>\n<copyright>\n<mention xml:lang=""></mention>\n</copyright>\n<license name="">\n<mention xml:lang=""></mention>\n</license>\n<datetime></datetime>\n<version></version>\n<annotation>\n<documentation xml:lang=""></documentation>\n</annotation>\n</header>',
          'body>\n\n</body>',
		  'subprograms xmlns:xi="http://www.w3.org/2001/XInclude">\n\n</subprograms>',
		  'sdk>\n\n</sdk>'
	];
	CodeMirror.xmlHints['<program><sdk><'] = [
          'formalism xsi:type="" xmlns="http://www.nomoseed.org/sdk" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\n\n</formalism>',
          'color model="" category="" type="" saturation="" hue="" xmlns="http://www.nomoseed.org/sdk"/>',
          'macro active="true" name="" scheme="" xsi:type="" xmlns="http://www.nomoseed.org/sdk" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\n\n</macro>'
	];
	CodeMirror.xmlHints['<program><subprograms><'] = [
          'new instance="">\n<xi:include href=""/>\n</new>',
          'inherite instance="">\n<xi:include href=""/>\n</inherite>'
	];
	CodeMirror.xmlHints['<program><body><'] = [
          'models xmlns:xi="http://www.w3.org/2001/XInclude">\n\n</models>',
          'scheme>\n\n</scheme>'
	];
	CodeMirror.xmlHints['<program><body><models><'] = [
		'new instance="">\n<xi:include href=""/>\n</new>',
		'inherite instance="">\n<xi:include href=""/>\n</inherite>',
		'import instance="" subprogram="">\n<xi:include href=""/>\n</import>',
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<program><body><scheme><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><'] = [
          'rule name="">\n\n</rule>',
          'scheme name="">\n\n</scheme>'
	];
	CodeMirror.xmlHints['<program><models><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><annotation><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><annotation><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><rule><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><rule><annotation><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><rule><annotation><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><rule><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><rule><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><rule><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><rule><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><rule><conclusion><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><rule><conclusion><annotation><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><rule><conclusion><annotation><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><rule><conclusion><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><rule><conclusion><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><rule><conclusion><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><rule><conclusion><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><rule><premise><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><rule><premise><annotation><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><rule><premise><annotation><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><rule><premise><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><rule><premise><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><rule><premise><annotation><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><rule><premise><annotation><'] = 
	CodeMirror.xmlHints['<model><base><<annotation><'] = 
	CodeMirror.xmlHints['<model><definition><<annotation><'] = [
          '<documentation xml:lang=""></documentation>'
	];
	CodeMirror.xmlHints['<program><body><scheme><rule '] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><rule '] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><rule '] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><rule '] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><rule '] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><rule '] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><rule '] = [
          'relevance=""',
          'fitting_nbr=""'
	];
	CodeMirror.xmlHints['<program><body><scheme><rule><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><rule><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><rule><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><rule><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><rule><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><rule><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><rule><'] =
	CodeMirror.xmlHints['<program><body><scheme><template><rule><'] = [
          'conclusion model="" category="" type="">\n\n</conclusion>',
          'premise model="" category="" type="">\n\n</premise>',
          'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<program><body><scheme><rule><premise '] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><rule><premise '] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><rule><premise '] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><rule><premise '] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><rule><premise '] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><rule><premise '] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><rule><premise '] = [
          'inhibitor="true"'
	];
	CodeMirror.xmlHints['<program><body><scheme><rule><premise><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><rule><premise><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><rule><premise><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><rule><premise><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><rule><premise><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><rule><premise><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><rule><premise><'] = [
          'information value="" tolerance=""/>',
          'credibility value="" tolerance=""/>',
          'timespan value="" tolerance=""/>',
          'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<program><body><scheme><rule><conclusion><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><rule><conclusion><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><rule><conclusion><'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><rule><conclusion><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><rule><conclusion><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><rule><conclusion><'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><rule><conclusion><'] = [
        'information value=""/>',
        'output value=""/>',
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<program><body><scheme><rule><conclusion><information'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><rule><conclusion><information'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><rule><conclusion><information'] =
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><rule><conclusion><information'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><rule><conclusion><information'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><rule><conclusion><information'] = 
	CodeMirror.xmlHints['<program><body><scheme><scheme><scheme><scheme><scheme><scheme><scheme><rule><conclusion><information'] = 
	CodeMirror.xmlHints['<program><body><scheme><template><rule><conclusion><information'] = [
          'delay=""'
	];
	CodeMirror.xmlHints['<model><'] = [
          'header xmlns="http://www.nomoseed.org/project">\n<author/>\n<copyright>\n<mention xml:lang=""></mention>\n</copyright>\n<license name="">\n<mention xml:lang=""></mention>\n</license>\n<datetime></datetime>\n<version></version>\n<annotation>\n<documentation xml:lang=""></documentation>\n</annotation>\n</header>',
          'base xmlns:xi="http://www.w3.org/2001/XInclude">\n<xi:include href=""/>\n</base>',
          'definition>\n\n</definition>',
		  'sdk>\n\n</sdk>'
	];
	CodeMirror.xmlHints['<model><sdk><'] = [
          'color category="" type="" saturation="" hue="" xmlns="http://www.nomoseed.org/sdk"/>'
	];
	CodeMirror.xmlHints['<model><base><'] = [
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<model><definition><'] = [
		'perceptive_structure name="">\n<items>\n\n</items>\n<components>\n<component name=""/>\n</components>\n</perceptive_structure>',
		'command_type name="">\n<items>\n\n</items>\n<components>\n<component name=""/>\n</components>\n</command_type>',
		'conception_type name="">\n<items>\n\n</items>\n</conception_type>',
		'predictive_structure name="">\n<items>\n\n</items>\n</predictive_structure>',
		'reward_type name="">\n<items>\n\n</items>\n</reward_type>',
		'landmark_type name="">\n<items>\n\n</items>\n</landmark_type>',
		'plant_structure others_register="">\n\n</plant_structure>',
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<model><definition><perceptive_structure><'] = [
		'rewarded_by name=""/>',
		'predicted_by name=""/>',
		'command_type>\n<items>\n\n</items></command_type>',
		'conception_type name="">\n<items>\n\n</items></conception_type>',
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<model><definition><conception_type><'] = [
		'rewarded_by name=""/>',
		'predicted_by name=""/>',
		'conception_type name="">\n<items>\n\n</items></conception_type>',
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<model><definition><perceptive_structure><command_type><'] =
	CodeMirror.xmlHints['<model><definition><command_type><'] =
	CodeMirror.xmlHints['<model><definition><landmark_type><'] =
	CodeMirror.xmlHints['<model><definition><predictive_structure><'] =[
		'rewarded_by name=""/>',
		'conception_type name="">\n<items>\n\n</items></conception_type>',
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<model><definition><reward_type><'] = [
		'conception_type name="">\n<items>\n\n</items></conception_type>',
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<model><definition><perceptive_structure><conception_type><'] = 
	CodeMirror.xmlHints['<model><definition><predictive_structure><conception_type><'] = 
	CodeMirror.xmlHints['<model><definition><command_type><conception_type><'] = 
	CodeMirror.xmlHints['<model><definition><reward_type><conception_type><'] = 
	CodeMirror.xmlHints['<model><definition><landmark_type><conception_type><'] =
	CodeMirror.xmlHints['<model><definition><conception_type><conception_type><'] = [
		'rewarded_by name=""/>',
		'predicted_by name=""/>',
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	];
	CodeMirror.xmlHints['<model><definition><command_type><components><'] = 
	CodeMirror.xmlHints['<model><definition><perceptive_structure><components><'] = [
		'component name/>',
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	]
	CodeMirror.xmlHints['<model><definition><perceptive_structure><items><'] = 
	CodeMirror.xmlHints['<model><definition><predictive_structure><items><'] = 
	CodeMirror.xmlHints['<model><definition><command_type><items><'] = 
	CodeMirror.xmlHints['<model><definition><reward_type><items><'] = 
	CodeMirror.xmlHints['<model><definition><landmark_type><items><'] =
	CodeMirror.xmlHints['<model><definition><conception_type><items><'] =
	CodeMirror.xmlHints['<model><definition><perceptive_structure><conception_type><items><'] = 
	CodeMirror.xmlHints['<model><definition><predictive_structure><conception_type><items><'] = 
	CodeMirror.xmlHints['<model><definition><command_type><conception_type><items><'] = 
	CodeMirror.xmlHints['<model><definition><reward_type><conception_type><items><'] = 
	CodeMirror.xmlHints['<model><definition><landmark_type><conception_type><items><'] =
	CodeMirror.xmlHints['<model><definition><conception_type><conception_type><items><'] = [
		'item name=""/>',
        'annotation xmlns="http://www.nomoseed.org/project">\n<documentation xml:lang="">\n\n</documentation>\n</annotation>'
	]
	CodeMirror.xmlHints['<model><base><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><perceptive_structure><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><conception_type><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><perceptive_structure><command_type><annotation><'] =
	CodeMirror.xmlHints['<model><definition><command_type><annotation><'] =
	CodeMirror.xmlHints['<model><definition><landmark_type><annotation><'] =
	CodeMirror.xmlHints['<model><definition><predictive_structure><annotation><'] =
	CodeMirror.xmlHints['<model><definition><reward_type><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><perceptive_structure><conception_type><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><predictive_structure><conception_type><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><command_type><conception_type><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><reward_type><conception_type><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><landmark_type><conception_type><annotation><'] =
	CodeMirror.xmlHints['<model><definition><conception_type><conception_type><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><command_type><components><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><perceptive_structure><components><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><perceptive_structure><items><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><predictive_structure><items><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><command_type><items><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><reward_type><items><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><landmark_type><items><annotation><'] =
	CodeMirror.xmlHints['<model><definition><conception_type><items><annotation><'] =
	CodeMirror.xmlHints['<model><definition><perceptive_structure><conception_type><items><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><predictive_structure><conception_type><items><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><command_type><conception_type><items><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><reward_type><conception_type><items><annotation><'] = 
	CodeMirror.xmlHints['<model><definition><landmark_type><conception_type><items><annotation><'] =
	CodeMirror.xmlHints['<model><definition><conception_type><conception_type><items><annotation><'] = [
          '<documentation xml:lang=""></documentation>'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><'] = [
          'input',
		  'other'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><input><'] =
	CodeMirror.xmlHints['<model><definition><plant_structure><other><'] = [
          'operator_type',
		  'scope_type'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><input><operator_type><'] = [
          'item name="" information_tolerance="" />'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><input><scope_type><'] = [
          'item name="">\n<target category="input" model="" type="" />\n</item>'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><other><operator_type><'] = [
          'item name="">\n</item>'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><other><operator_type><item><'] = [
          'conclusion relevance="" fitting_nbr=""></conclusion>',
          'premise >\n<information tolerance="" />\n<credibility tolerance="" />\n<timespan tolerance="" />\n</premise>'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><input><operator_type><'] = [
          'item name="">\n<premise>\n<informations tolerance="" />\n</premise>\n</item>'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><other><operator_type><item><premise><'] = [
          'target category="input" model="" type="" />',
		  'information tolerance="" />',
		  'credibility tolerance="" />',
		  'timespan tolerance="" />'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><other><operator_type><item><conclusion><'] = [
          'target category="input" model="" type="" />',
          'delay value="" />',
          'information value="" />'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><other><operator_type><item><premise><information'] = [
          'value=""',
		  'tolerance=""'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><other><operator_type><item><premise><credibility'] = [
          'value=""',
		  'tolerance=""'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><other><operator_type><item><premise><conclusion'] = [
          'value=""',
		  'tolerance=""'
	];
	CodeMirror.xmlHints['<model><definition><plant_structure><other><scope_type><'] = [
          'item name="" target_category="" target_model="" target_type="" />'
	];
	nomoNavigation.initialize();
	window.onresize();
}

function nomoOpenWorkspace(number, projectType){
	if (number == nomoWorkspaces.length){
		nomoWorkspaces.push(new Workspace());
	}
	else
		nomoWorkspaces[number] = new Workspace();
	nomoWorkspace = nomoWorkspaces[number];
	nomoWorkspace.type = projectType;
	nomoNavigation.update();
}

var Workspace = function(){
	var editor;
	var hlLine;
	var codespace;
	var splitter;
	var validationspace;
	var isCaseSensitive = true;
	var cursor;
	var resultLink;
	var caseSensitive;
	var searchTools;
	var findString;
  	var replaceString;
	var text;
	var undo;
  	var redo;
  	var color;
  	var link_;
	this.type = "";
	var changeMinor;
	
	this.isInitialized = false;
	
	this.initialize = function(){
			$("#workspace .undo").bind("click", this.undo);
			$("#workspace .redo").bind("click", this.redo);
			$("#workspace .indent").bind("click", this.indent);
			$("#workspace .search").bind("keydown", this.changeSearch);
			$("#workspace .search").bind("click", this.changeSearch);
			$("#workspace .search_tools").get(0).style.visibility = "hidden";
			$("#workspace .case_sensitive").bind("click", this.checkCase);
			$("#workspace .next").bind("click", this.next);
			$("#workspace .previous").bind("click", this.previous);
			$("#workspace .replace").bind("click", this.replace);
			$("#workspace .replace_all").bind("click", this.replaceAll);
			$("#workspace .link").bind("click", this.link);
			$("#workspace .color").bind("click", this.color);
			$("#workspace .splitter").bind("mousedown", this.startSplitter);
			$("#workspace .text").bind("mousemove", this.moveSplitter);
			$("#workspace .text").bind("mouseup", this.upSplitter);
			codespace = $("#workspace .codespace").get(0);
			validationspace = $("#workspace .validationspace").get(0);
			caseSensitive = $("#workspace .case_sensitive").get(0);
			searchTools = $("#workspace .search_tools").get(0);
			findString = $("#workspace .search").get(0);
			replaceString = $("#workspace .word").get(0);
			text = $("#workspace .text").get(0);
			undo = $("#workspace .undo").get(0);
			redo = $("#workspace .redo").get(0);
			color = $("#workspace .color").get(0);
			link_ = $("#workspace .link").get(0);
			var foldFunc_html = CodeMirror.newFoldGutterFunction(CodeMirror.tagRangeFinder,"...");
			editor = CodeMirror.fromTextArea($("#workspace .code").get(0), {
				mode: "xml",
				autoCloseTags: true,
				gutters: ["CodeMirror-linenumbers", "CodeMirror-gutterfoldmarker"],
				lineNumbers: true,
				lineWrapping: true,
				extraKeys: {
					"' '": function(cm) { CodeMirror.xmlHint(cm, ' '); },
					"'<'": function(cm) { CodeMirror.xmlHint(cm, '<'); },
					"Ctrl-Space": function(cm) { CodeMirror.xmlHint(cm, ''); }
				}
			});
			editor.on("cursorActivity", function() {
				var cur = editor.getLineHandle(editor.getCursor().line);
				if (cur != hlLine) {
					editor.removeLineClass(hlLine, "background", "activeline");
					hlLine = editor.addLineClass(cur, "background", "activeline");
				}
				editor.matchHighlight("CodeMirror-matchhighlight");
			});
			editor.on("gutterClick", foldFunc_html);
			this.indent();
			editor.clearHistory();
			editor.on("change", this.change);
			hlLine = editor.addLineClass(0, "background", "activeline");
			var result = editor.getSearchCursor(new RegExp("<([^> ]+:)?header", "i"), 0, false );
			if (result.findNext())
				foldFunc_html(editor, result.from().line);
			validationspace.innerHTML = '<p>' + nomoSDK.parse (editor.getValue(), true).slice(1) + '</p>';
			$("#workspace .visualisationspace").get(0).style.height = $("#workspace .visualisationspace").get(0).offsetHeight + "px";
			this.isInitialized = true;
			if (this.type == "e" || this.type == "b")
				$("#workspace .link").get(0).style.display = "none";
			else
				$("#workspace .link").get(0).style.display = "";
			
			if (this.type == "u"){
				$("#workspace .interface select").get(0).style.width = $("#workspace .interface select").get(0).offsetWidth + 10 + "px";
				$("#workspace .interface").get(0).style.display = "";
				$("#workspace .interface").get(0).style.visibility = "visible ";
				}
			else
				$("#workspace .interface").get(0).style.display = "none";
			if (this.type == "m" || this.type == "p"){
				if (!nomoSDK.updateCSS())
					color.style.display = "none";
				else
					color.style.display = "";
			}
			else
				color.style.display = "none";
			$("#workspace").get(0).onpaste = this.onPaste;
			this.valid("");
			setTimeout("nomoWorkspace.addBind($('#tree'))",0);
		    editor.setSize(codespace.offsetWidth-2, codespace.offsetHeight-1);
			codespace.style.height = "90%";
			validationspace.style.height = "10%";
	}
	
	this.onPaste = function (e){
		if(e.target.tagName == "INPUT")
			e.target.value = e.clipboardData.getData("text/plain");
		else if(e.target.tagName == "TEXTAREA"){
			editor.replaceSelection("");
			editor.replaceRange(e.clipboardData.getData("text/plain"),editor.getCursor());
		}
	}
	this.addBind = function(navigator){
		navigator.bind("select_node.jstree", function (event, data) {
			if($("#tree").jstree("get_selected").length == 1){
				if (nomoEventSelect != null){
					nomoEventSelect = clearTimeout( nomoEventSelect );
				}
				nomoEventSelect = setTimeout("nomoWorkspace.select('"+data.rslt.obj.attr("id")+"');", nomoClickDelay);
			}
			else if (data.rslt.obj.attr("id").indexOf('-')!=-1 || $("#tree").jstree("get_selected")[$("#tree").jstree("get_selected").length-1].getAttribute("id").indexOf('-')!=-1 ){
				$("#tree").jstree("deselect_all");
				$("#tree").jstree("select_node", data.rslt.obj);
			}
		})
		.bind("move_node.jstree", function (event, data) {
			nomoWorkspace.moveNode(data.rslt.o.attr("id"), data.rslt.r.attr("id"), data.rslt.p);
		});
	}
	
	this.undo = function(){
		editor.undo();
		if (editor.historySize()['undo'] > 0) {
		  undo.style.opacity = "0.8";
		} else {
		  undo.style.opacity = "0.4";
		}
		if (editor.historySize()['redo'] > 0) {
			redo.style.opacity = "0.8";
		} else {
			redo.style.opacity = "0.4";
		}
	}
	
	this.redo = function(){
		editor.redo();
		if (editor.historySize()['redo'] > 0) {
			redo.style.opacity = "0.8";
		} else {
			redo.style.opacity = "0.4";
		}
		if (editor.historySize()['undo'] > 0) {
		  undo.style.opacity = "0.8";
		} else {
		  undo.style.opacity = "0.4";
		}
	}
	
	this.indent = function() {
		var lineCount = editor.lineCount();
		for(var line = 0; line < lineCount; line++)
			editor.indentLine(line);
	}
  
  this.checkCase = function() {
	isCaseSensitive = !isCaseSensitive;
	if (isCaseSensitive)
		caseSensitive.setAttribute("class", "case_sensitive ui sensitive");
	else
		caseSensitive.setAttribute("class", "case_sensitive ui unsensitive");
	setTimeout("nomoWorkspace.search();", 0);
  }
  
  	this.changeSearch = function() {
		if (nomoEventSearch != null) {
			clearTimeout( nomoEventSearch );
			nomoEventSearch = null;
		}
		nomoEventSearch = setTimeout("nomoWorkspace.search();", nomoClickDelay);
	}
  
  this.search = function() {
		var target = $("#workspace .search").get(0).value;
		if (target == null || target == '') {
			editor.setCursor(editor.getCursor());
			searchTools.style.visibility = "hidden";
			return false;
		}
		target = new RegExp(target, !isCaseSensitive ? "i" : "");

		cursor = editor.getSearchCursor(target, 0, !isCaseSensitive );
		if (cursor.findNext()){
			editor.setCursor(cursor.from());
			editor.setSelection(cursor.from(),cursor.to());
			if (cursor.findNext()){
				searchTools.style.visibility = "visible";
				cursor.findPrevious();
			}
			else
				searchTools.style.visibility = "hidden";
		}
		else{
			editor.setCursor(editor.getCursor());
			searchTools.style.visibility = "hidden";
		}
   }
   
    this.replace = function() {
		isRegex = true;
		var regFindString = isRegex ? new RegExp(findString.value, !isCaseSensitive ? "i" : "") : "";
		if (cursor){
			editor.replaceRange(isRegex ? cursor.pos.match[0].replace(regFindString, replaceString.value) : replaceString.value, cursor.from(), cursor.to());
			if (cursor.findNext()){
				editor.setCursor(cursor.from());
				editor.setSelection(cursor.from(),cursor.to());
				editor.focus();
			}
			else
				searchTools.style.visibility = "hidden";
		}
    }
  
    this.replaceAll = function() {
		isRegex = true;
		var regFindString = isRegex ? new RegExp(findString.value, !isCaseSensitive ? "i" : "") : "";
		cursor = editor.getSearchCursor(isRegex ? regFindString : findString.value, 0, !isCaseSensitive);
		while (cursor.findNext())
			editor.replaceRange(isRegex ? cursor.pos.match[0].replace(regFindString, replaceString.value) : replaceString.value, cursor.from(), cursor.to());
		searchTools.style.visibility = "hidden";
  }
  
  	this.next = function(){
		if (cursor.findNext()){
			editor.setCursor(cursor.from());
			editor.setSelection(cursor.from(),cursor.to());
			editor.focus();
		}
	}
	
	this.previous = function(){
		if (cursor.findPrevious()){
			editor.setCursor(cursor.from());
			editor.setSelection(cursor.from(),cursor.to());
			editor.focus();
		}
	}

	this.resize = function() {
		editor.setSize(codespace.offsetWidth-2, codespace.offsetHeight-1);
	}

	this.change = function(cm, changeObj) {
		if(nomoEventSelect == null) {
			if (nomoEventChange != null) {
				clearTimeout( nomoEventChange );
				nomoEventChange = null;
			}
			nomoEventChange = setTimeout("nomoWorkspace.valid('"+changeObj.text+"');", nomoClickDelay);
		}
	}
	 
	this.valid = function(newText){
		var his = editor.historySize();
		if (his['undo'] > 0) {
			undo.style.opacity = "0.8";
		} else {
			undo.style.opacity = "0.4";
		}
		if (his['redo'] > 0) {
			redo.style.opacity = "0.8";
		} else {
			redo.style.opacity = "0.4";
		}
		var xml = editor.getValue();
		if (xml == "" || xml == "\n"){
			editor.setValue(nomoSDK.getDefaultProject());
			var h = editor.getHistory();
			if (editor.getLine(0)[1]=='?')
				editor.removeLine(0);
			nomoWorkspace.indent();
			editor.setHistory(h);
		}
		else{
			var result = nomoSDK.parse (xml, his['undo'] == 0);
			if (result.charAt(0) == "*"){
				nomoSDK.update (xml);
				if (this.type == "m" || this.type == "p"){
					if (!nomoSDK.updateCSS())
						color.style.display = "none";
					else
						color.style.display = "";
				}
				setTimeout("nomoWorkspace.addBind($('#tree'))",0);
				link_.style.visibility='visible';
				result = result.slice(1);
			}
			else
				link_.style.visibility='hidden';
			if (!resultLink)
				validationspace.innerHTML = '<p>' + result + '</p>';
			else{
				validationspace.innerHTML = '<p>' + resultLink + '</p>';
				resultLink = "";
			}
		}
	}

	this.startSplitter = function (e){
		splitter = {yo: e.clientY, wh: text.offsetHeight, ch: codespace.offsetHeight, vh: validationspace.offsetHeight, dy: 0};
		nomoWorkspace.refresh();
	}

	
	this.moveSplitter = function(e){
		if (splitter){
			splitter.dy = e.clientY - splitter.yo;
			codespace.style.height = 100*(splitter.ch + splitter.dy)/splitter.wh + "%";
			$("#workspace .CodeMirror").height(codespace.offsetHeight-2);
			validationspace.style.height = 100*(splitter.vh - splitter.dy)/splitter.wh + "%";
		}
	}

	this.upSplitter = function(e){
		splitter = null;
		nomoWorkspace.refresh();
	}
	
	this.refresh = function(){
		nomoWorkspace.resize();
		editor.refresh();
		if(splitter)
			setTimeout("nomoWorkspace.refresh()",100);
	}
	
	this.select = function(id) {
		var i = id.split('-')[0].slice(1);
		if (nomoSDK.getCurrentWorkspace() != i){
			nomoWorkspace.changeWorkspace(id);
		}
		else if(!colorWidget.isActive()){
			nomoWorkspace.findSelection(id);
			nomoEventSelect = null;
		}
	}
	
	this.reload = function(id) {
		editor.focus();
		nomoWorkspace.resize();
		nomoWorkspace.findSelection(id);
		nomoEventSelect = null;
	}
	
	this.changeWorkspace = function(id) {
		var i = id.split('-')[0].slice(1);
		if(colorWidget.isActive())
			colorWidget.close();
		document.getElementById("workspace").setAttribute("id", "w" + nomoSDK.getCurrentWorkspace());
		nomoSDK.setCurrentWorkspace (i);
		document.getElementById("w"+i).setAttribute("id", "workspace");
		editor.refresh();
		editor.getTextArea().blur();
		setTimeout("nomoWorkspace = nomoWorkspaces["+i+"];nomoWorkspace.reload('" + id + "');", 100);
	}
	
	this.findSelection = function(id) {
		var target = id.split('-');
		var reg = id.split('-');
		editor.setCursor({line:editor.lineCount()-1,ch:0});
		if (target.length == 1){
			var first = {line:0,ch:0};
			editor.setCursor(first);
			editor.setSelection(first,first);
			editor.focus();
		}
		else {
			if (target[1] == "formalism")
				reg = new RegExp("<([^> ]+:)?"+target[2], "i");
			else if (target[1] == "plant_structure")
				reg = new RegExp("<([^> ]+:)?"+target[1], "i");
			else if (target[1] == "input" || target[1] == "other"){
				if (target[2] == "scope")
					reg = new RegExp("<([^> ]+:)?"+target[1], "i");
				else
					reg = new RegExp("<([^> ]+:)?"+target[1], "i");
				}
			else if (target[1] == "base")
				reg = new RegExp("<([^> ]+:)?"+target[1], "i");
			else if (target[1] == "new" || target[1] == "inherite" || target[1] == "import")
				reg = new RegExp("<([^> ]+:)?"+target[1]+"[^>]*instance=\""+target[2]+"\"", "i");
			else if (target[1] == "include")
				reg = new RegExp("<([^> ]+:)?include[^>]*"+target[2]+"\"", "i");
			else
				reg = new RegExp("<([^> ]+:)?"+target[1]+"[^>]*name=\""+target[2]+"\"", "i");
			var result = editor.getSearchCursor(reg, 0, false );
			if (result.findNext()){
				if (editor.getCursor().line != result.from().line){
					editor.setCursor(result.from());
					editor.setSelection(result.from(),result.to());
					editor.focus();
				}
			}
			else if (target[1] == "command_type"){
				reg = new RegExp("<([^> ]+:)?perceptive_structure[^>]*name=\""+target[2]+"\"", "i");
				result = editor.getSearchCursor(reg, 0, false );
				reg = new RegExp("<([^> ]+:)?command_type", "i");
				result.findNext();
				result = editor.getSearchCursor(reg,result.from(),false);
				if (result.findNext())
					if (editor.getCursor().line != result.from().line){
						editor.setCursor(result.from());
						editor.setSelection(result.from(),result.to());
						editor.focus();
					}
			}
		}
	}
	
	this.moveNode = function(mov, ref, order) {
		mov = mov.split('-');
		var movExp = new RegExp("<([^> ]+:)?"+mov[1]+"[^>]*name=\""+mov[2]+"\"", "i");
		mov = editor.getSearchCursor(movExp, 0, false );
		mov.findNext();
		mov = CodeMirror.tagRangeFinder(editor, {line: mov.from().line, ch: 0});
		var movText = editor.getRange({line:mov.from.line,ch:0}, {line:mov.to.line+1,ch:0});
		editor.replaceRange("",{line:mov.from.line,ch:0}, {line:mov.to.line+1,ch:0})
		ref = ref.split('-');
		var refExp = new RegExp("<([^> ]+:)?"+ref[1]+"[^>]*name=\""+ref[2]+"\"", "i");
		ref = editor.getSearchCursor(refExp, 0, false );
		ref.findNext();
		if (order=='before'){
			editor.replaceRange(movText,{line:ref.from().line,ch:0}, {line:ref.from().line,ch:0});
		}
		else if (order=='first')
			editor.replaceRange(movText,{line:ref.from().line+1,ch:0}, {line:ref.from().line+1,ch:0});
			
		else{
			ref = CodeMirror.tagRangeFinder(editor, {line: ref.from().line, ch: 0});
			editor.replaceRange(movText,{line:ref.to.line+1,ch:0}, {line:ref.to.line+1,ch:0});
		}
	}

	this.isSaved = function(newDatetime, oldDatetime) {
		if (oldDatetime != ''){
			var reg = new RegExp(oldDatetime, "i");
			cursor = editor.getSearchCursor(oldDatetime, 0, true);
			cursor.findNext();
			var h = editor.getHistory();
			editor.off("change", this.change);
			editor.replaceRange(newDatetime, cursor.from(), cursor.to());
			editor.on("change", this.change);
			editor.setHistory(h);
		}
	}

	this.link = function() {
		link_.removeEventListener('click',this.link, true);
		if (nomoWorkspace.type == 'u'){
		    var select = $("#workspace .interface select").get(0);
			var item = select.options[select.selectedIndex].value.split('_');
			if (item[0] != "none")
				nomoSDK.setInterface(item[0],item[1]);
		}
		var test = editor.getTextArea().value;
		resultLink = nomoSDK.link();
		if (resultLink.charAt(0) == "*")
			resultLink = resultLink.slice(1);
		if (nomoWorkspace.type == 'p'){
			editor.off("change", nomoWorkspace.change);
			var top = editor.getScrollInfo().top;
			var cursor = editor.getCursor();
			if (test != editor.getTextArea().value)
				editor.setValue(editor.getTextArea().value);
			if (editor.getLine(0)[1]=='?')
				editor.removeLine(0);
			nomoWorkspace.indent();
			editor.clearHistory();
			editor.setCursor(cursor);
			editor.scrollTo(0,top);
			editor.on("change", nomoWorkspace.change);
			nomoWorkspace.valid();
		}
		else{
			validationspace.innerHTML = '<p>' + resultLink + '</p>';
			resultLink = "";
		}
		link_.addEventListener('click',this.link, true);
	}
	
	this.updateColor = function() {
		var top = editor.getScrollInfo().top;
		var cursor = editor.getCursor();
		nomoSDK.updateText();
		editor.setValue(editor.getTextArea().value);
		var h = editor.getHistory();
		if (editor.getLine(0)[1]=='?'){
			editor.removeLine(0);
		}
		nomoWorkspace.indent();
		editor.setHistory(h);
		editor.setCursor(cursor);
		editor.scrollTo(0,top);
	}
	
	this.color = function() {
		colorWidget.show();
	}

};

var colorWidget = new (function(){

	var svg;
	var x0, y0;
	var ratio;
	var dx, dy;
	var target;
	var minX, maxX, minY, maxY;
	var maxSaturation = 570 / 2;
	var minSaturation = 570 / 8;
	var SaturationRatioHSL = 100 / maxSaturation;
	var saturationRatioXY = 5.7 / 2;
	var svgRatio;
	var styleSheet = document.styleSheets[0];
	var isActive_ = false;
	
	this.isActive = function() {return isActive_;}
	
	this.show = function() {
		document.getElementById("workspace").style.display="none";
		document.getElementById("wheel").style.display="block";
		svg = document.getElementById("wheel").getElementsByTagName("svg")[0];
		svg.style.height = document.getElementById("wheel").offsetHeight - 24+"px";
		isActive_ = true;
		for (j=0; j<styleSheet.cssRules.length; j++)
			if (styleSheet.cssRules[j].selectorText.indexOf("#"+ nomoWorkspace.type + nomoSDK.getCurrentWorkspace()) != -1) {
				var rgb = styleSheet.cssRules[j].style.backgroundColor.split('(')[1].split(')')[0].split(',');
				colorWidget.add(styleSheet.cssRules[j].selectorText.replace(' a > ins',''), nomoSDK.toHSL(rgb[0],rgb[1],rgb[2]));
			}
		window.addEventListener("resize", colorWidget.resize, false);
	}

	this.update = function() {
		for (j=0; j<styleSheet.cssRules.length; j++)
			if (styleSheet.cssRules[j].selectorText.indexOf("#" + nomoWorkspace.type + nomoSDK.getCurrentWorkspace()) != -1) {
				var rgb = styleSheet.cssRules[j].style.backgroundColor.split('(')[1].split(')')[0].split(',');
				colorWidget.add(styleSheet.cssRules[j].selectorText.replace(' a > ins',''), nomoSDK.toHSL(rgb[0],rgb[1],rgb[2]));
			}
	}
	
	this.close = function() {
		nomoWorkspace.updateColor();
		document.getElementById("wheel").style.display="none";
		var g = document.getElementById("viewColor");
		g.parentNode.replaceChild(g.cloneNode(false),g);
		document.getElementById("workspace").style.display="";
		window.removeEventListener("resize", colorWidget.resize, false);
		isActive_  = false;
		$("#tree").jstree("deselect_all");
		nomoWorkspace.resize();
	}

	this.add = function (name, color) {
		var hsl = color.split(',');
		var hue = Number(hsl[0]);
		var saturation = Number(hsl[1]);
		var point = toXY(hue, saturation);
		var g = document.createElementNS(nomoNsResolver("svg"), "g");
		document.getElementById("viewColor").appendChild(g);
		g.setAttribute("id", name);
		var use = document.createElementNS(nomoNsResolver("svg"), "use");
		g.appendChild(use);
		use.setAttribute("class", "trace");
		use.setAttributeNS(nomoNsResolver("xlink"), "href", "#target");
		use.setAttribute("x", point.x);
		use.setAttribute("y", point.y);
		var line = document.createElementNS(nomoNsResolver("svg"), "line");
		g.appendChild(line);
		line.setAttribute("x1", point.x + 8 * point.cos);
		line.setAttribute("y1", point.y - 8 * point.sin);
		var text = document.createElementNS(nomoNsResolver("svg"), "text");
		g.appendChild(text);
		setTextClass(text, hue * dToR);
		text.appendChild(document.createTextNode(name.split(' ')[1].slice(3).replace("t_",'').replace(".i_",'|').replace(".m_",'|').replace(".c_",'|')));
		text.setAttribute("x", (point.x + 170 * point.cos));
		text.setAttribute("y",(point.y - 170 * point.sin));
		var circle = document.createElementNS(nomoNsResolver("svg"), "circle");
		g.appendChild(circle);
		circle.setAttribute("r", 20);
		circle.setAttribute("fill-opacity", 1);
		circle.setAttribute("cx", point.x);
		circle.setAttribute("cy", point.y);
		var rect = document.createElementNS(nomoNsResolver("svg"), "rect");
		g.appendChild(rect);
		rect.setAttribute("rx", 10 );
		rect.setAttribute("ry", 10);
		var box = text.getBBox();
		var height = box.height + 10;
		var width =  box.width + 10;
		var x = box.x - 5;
		var y = box.y - 5;
		rect.setAttribute("height", height);
		rect.setAttribute("width", width);
		rect.setAttribute("x", x );
		rect.setAttribute("y", y);	
		setLineX2Y2(line, x, y, width, height, hue * dToR);
		rect.onmousedown = colorWidget.mouseDownText;
		circle.onmousedown = colorWidget.mouseDownColor;
	}

	this.resize = function() {
		svg.style.height = document.getElementById("wheel").offsetHeight - 24+"px";
	}

	this.remove = function(id) {
		var child = svg.getElementById(id);
		var parent = child.parentNode;
		parent.removeChild(child);
	}

	this.mouseDownText = function(evt) {
		if (evt.button == 0) {
			mouseInit(evt.clientX, evt.clientY);
			minX = - svgRatio * svg.offsetWidth / 2;
			maxX = svgRatio * svg.offsetWidth / 2;
			minY = - svgRatio * svg.offsetHeight / 2;
			maxY = svgRatio * svg.offsetHeight / 2;
			var parent = evt.target.parentNode;
			var text = parent.getElementsByTagName("text")[0];
			var use = parent.getElementsByTagName("use")[0];
			target = {
				rect: {
						node: evt.target
						},
				text: {
						node: text,
						x: Number(text.getAttribute("x")),
						y: Number(text.getAttribute("y"))
						},
				line: {
						node: parent.getElementsByTagName("line")[0]
						},
				use: {
					node: use,
					x: Number(use.getAttribute("x")),
					y: Number(use.getAttribute("y"))
					}
			};
			window.addEventListener("mousemove", colorWidget.mouseMoveText, false);
			window.addEventListener("mouseup", colorWidget.mouseUpText, false);
			window.addEventListener("blur", colorWidget.mouseUpText, false);
			evt.stopPropagation();
		}
	}

	this.mouseMoveText = function(evt) {
		var tx = target.text.x + (evt.clientX - x0) * svgRatio;
		var ty = target.text.y + (evt.clientY - y0) * svgRatio;
		if (tx > minX &&  tx < maxX && ty  > minY && ty  < maxY) {
			var r = atan2( ty -target.use.y, tx - target.use.x);
			setTextClass(target.text.node, r);
			target.text.node.setAttribute("x", tx);
			target.text.node.setAttribute("y", ty);
			target.line.node.setAttribute("x1", target.use.x + 8 * Math.cos(r));
			target.line.node.setAttribute("y1", target.use.y - 8 * Math.sin(r));
			var box = target.text.node.getBBox();
			var height = box.height + 10;
			var width =  box.width + 10;
			var x = box.x - 5;
			var y = box.y - 5;
			target.rect.node.setAttribute("x", x);
			target.rect.node.setAttribute("y", y);
			setLineX2Y2(target.line.node, x, y, width, height, r);
		}
	}

	this.mouseUpText = function(evt) {
		if (evt.button == 0) {
			window.removeEventListener("mousemove", colorWidget.mouseMoveText, false);
			window.removeEventListener("mouseup", colorWidget.mouseUpText, false);
			window.removeEventListener("blur", colorWidget.mouseUpText, false);
			target=null;
		}
	}

	this.mouseDownColor = function(evt) {
		if (evt.button == 0) {
			mouseInit(evt.clientX, evt.clientY);
			var parent = evt.target.parentNode;
			var circle = parent.getElementsByTagName("circle")[0];
			var line = parent.getElementsByTagName("line")[0];
			var css;
			var cssRule = parent.id +' a > ins';
			for (i=0; i<document.styleSheets[0].cssRules.length; i++)
					if (document.styleSheets[0].cssRules[i].selectorText == cssRule) {
						css = document.styleSheets[0].cssRules[i];
						break;
					}
			target = {
				css: css,
				line: {
						node: line,
						x2: Number(line.getAttribute("x2")),
						y2: Number(line.getAttribute("y2"))
						},
				circle: {
					node : circle,
					x: Number(circle.getAttribute("cx")),
					y: Number(circle.getAttribute("cy"))
					},
				use: {
					node : parent.getElementsByTagName("use")[0]
					}
			};
			nomoSDK.activeColor(parent.id);
			window.addEventListener("mousemove", colorWidget.mouseMoveColor, false);
			window.addEventListener("blur", colorWidget.mouseUpColor, false);
			window.addEventListener("mouseup", colorWidget.mouseUpColor, false);
			evt.stopPropagation();
		}
	}
	
	this.mouseMoveColor = function(evt) {
		var cx = target.circle.x + (evt.clientX - x0) * svgRatio;
		var cy = target.circle.y + (evt.clientY - y0) * svgRatio;
		var colorHSL = toHSL(cx, cy);
		if (colorHSL) {
			var r = atan2(target.line.y2 - cy, target.line.x2 - cx);
			target.circle.node.setAttribute("cx", cx);
			target.circle.node.setAttribute("cy", cy);
			target.use.node.setAttribute("x", cx);
			target.use.node.setAttribute("y", cy);
			target.line.node.setAttribute("x1", cx + 8 * Math.cos(r));
			target.line.node.setAttribute("y1", cy - 8 * Math.sin(r));
			target.css.style.backgroundColor = 'hsl('+colorHSL.h + ', ' + colorHSL.s + '%, '+ colorHSL.l + '%)';
			nomoSDK.setColor(colorHSL.h,colorHSL.s);
		}
	}
		
	this.mouseUpColor = function(evt) {
		if (evt.button == 0) {
			window.removeEventListener("mousemove", colorWidget.mouseMoveColor, false);
			window.removeEventListener("blur", colorWidget.mouseUpColor, false);
			window.removeEventListener("mouseup", colorWidget.mouseUpColor, false);
			target=null;
		}
	}
	
	var mouseInit = function(clientX, clientY) {
		x0 = clientX;
		y0 = clientY;
		if (svg.offsetWidth < svg.offsetHeight)
			svgRatio = 1000 / svg.offsetWidth;
		else
			svgRatio = 1000 / svg.offsetHeight;
	}
	
	var setTextClass = function(text, angle) {
		if (angle < 1.22 || angle > 5.06)
			text.setAttribute("class", "right");
		else if (angle > 1.91 && angle < 4.36)
			text.setAttribute("class", "left");
		else
			text.setAttribute("class", "center");
	};
	
	var setLineX2Y2 = function(line, x, y, width, height, angle) {
		if (angle < 1.22 || angle > 5.06) {
			line.setAttribute("x2", x);
			line.setAttribute("y2", y  + height / 2);
		}
		else if (angle > 1.91 && angle < 4.36) {
			line.setAttribute("x2", x + width);
			line.setAttribute("y2", y + height / 2);
		}
		else if (angle > 1.22 && angle < 1.91) {
			line.setAttribute("x2", x + width / 2);
			line.setAttribute("y2", y + height);
		}
		else {
			line.setAttribute("x2", x + width / 2);
			line.setAttribute("y2", y);
		}
	};
	
	var toXY = function (hue,saturation) {
		var r =  hue * dToR;
		var x= saturation * saturationRatioXY * Math.cos(r);
		var y= -saturation * saturationRatioXY * Math.sin(r);
		return {x:x, y:y, cos:Math.cos(r), sin:Math.sin(r)};
	};

	var toHSL = function (x, y) {
		var n = Math.sqrt((x * x) + (y * y));
		if ( n > (minSaturation) && n < maxSaturation) {
			var r = atan2(y,x);
			var d = Math.floor(r * rToD);
			return {h:d, s:Math.floor(n * SaturationRatioHSL), l:50};
		}
		return false;
	};
	
});

nomoUpdateCSS = function(css){
	var rules = css.split('|');
	var name = rules.pop();
	var present = false;
	var styleSheet = document.styleSheets[0];
	var index;
	for (i=0; i<rules.length/2; i++){
		index = 0
		for (j=0; j<styleSheet.cssRules.length; j++)
			if (styleSheet.cssRules[j].selectorText == "#"+name +" li."+rules[i*2]+" a > ins") {
				index = j;
				styleSheet.removeRule(j);
				break;
			}
		styleSheet.addRule("#"+name +" li."+rules[i*2]+" a > ins","background-color:" + rules[i*2 + 1], index);
	}
}

window.onresize = function (){
	document.body.style.height = (window.innerHeight-40) +'px';
	var visualisationspaces = $(".visualisationspace");
	var visualisationspace = $("#workspace .visualisationspace");
	for (i=0; i< visualisationspaces.length; i++){
		visualisationspaces[i].style.height = visualisationspace.get(0).offsetHeight + "px";
		nomoWorkspaces[i].resize();
	}
}

nomoClose = function(){
	if (colorWidget.isActive())
		colorWidget.close();
	else {
		var i = nomoSDK.getCurrentWorkspace();
		var msg = nomoSDK.isModified (i);
		if (msg != "")
			if (confirm (msg)) {
			    msg = nomoSDK.save(i);
				if (msg != ""){
					alert(msg);
					return;
					}
			}
		var node = document.getElementById('workspace');
		node.parentNode.removeChild(node);
		node = document.getElementById(nomoWorkspace.type + i);
		node.parentNode.removeChild(node);
		if (i == nomoWorkspaces.length - 1)
			nomoWorkspaces.pop();
		else
			nomoWorkspace[i] = "";
		i = nomoSDK.closeWorkspace();
		if (i != -1) {
			var next = document.getElementById('w'+i);
			next.setAttribute('id','workspace');
			nomoWorkspace = nomoWorkspaces[i];
			$("#tree").jstree("select_node", document.getElementById(nomoWorkspace.type + i));
		}
		else
			nomoWorkspace="";
	}
};

nomoOpen = function(href){
	if (href){
		if (nomoEventSelect != null){
			nomoEventSelect = clearTimeout( nomoEventSelect );
		}
		var result = nomoSDK.openWorkspace(href, event.target.parentElement.getAttribute("id").split('-')[0].slice(1));
		if(result[0] == '*'){
			if(colorWidget.isActive())
				colorWidget.close();
			$("#tree").jstree("deselect_all");
			$("#tree").jstree("select_node", document.getElementById(result.slice(1)));
		}
		else if(result)
			alert(result);
	}
};

nomoGetSelected = function(){
	var result = new Array;
	for (i=0;i<$("#tree").jstree("get_selected").length;i++)
		result.push($("#tree").jstree("get_selected")[i].getAttribute("id").slice(1));
	return result.join("-");
};

window.onmousedown = function(e){if(e.button==2)e.preventDefault();};

window.onload = nomoInitializeEditor;
