/*
 * request a resizePanels call.
 *
 * Send this through eventScheduler to avoid multiple calls (IE generates lots of resize events... we dont need to resize the panels each 0.001s ...
 *
 * */
function request_resizePanels(type){
	if(type=='fast') {
		eventScheduler.schedule('resizePanels',function(){resizePanels();},0.1);
	}
	else eventScheduler.schedule('resizePanels',function(){resizePanels();},0.5);
}


/* called on pageLoad & resize, to resize the containing panels */
function resizePanels(){
	var sizesh=new Array();
	var sizesw=new Array();
	var windowSize=getWindowSize();
	var h=Number(0);

	sizesh['engine_header']=$('pageContent').getTop();
	sizesh['engine_mainMenu']=0;
	sizesh['engine_statusBar']=0;
	sizesh['engine_subMenu']=0;
	sizesh['compensated_offsets']=0;
	sizesh['window']=Number(windowSize[1]);

	sizesw['panel_1']=Number($('panel_1').getWidth());
	sizesw['panel_3']=Number($('panel_3').getWidth());
	sizesw['window']=Number(windowSize[0]);

	sizesw['compensated_offsets']=Number(23);

	if($('attributes_mainContainer_td').visible())
		sizesw['compensated_offsets']=Number(40); //now theese i have no ideea why are here:) but the browser nees them to proprely resize stuff
	try{
		 window.document.body.scroll = 'no'; //IE
		 document.body.scroll='no'; //IE
		 document.body.style.overflow='hidden'; //MOZ
	}catch(err){}

	h=sizesh['window']-	(
						  sizesh['engine_header']
						+ sizesh['engine_mainMenu']
						+ sizesh['engine_statusBar']
						+ sizesh['engine_mainMenu']
						+ sizesh['engine_subMenu']
						+ sizesh['compensated_offsets']
						);


	sizesw['panel_1']=($('tabs_mainContainer_td').minimized?16:230);
	sizesw['panel_3']=($('attributes_mainContainer_td').minimized?0:350);

	w=sizesw['window']-	(
						  sizesw['panel_1']
						+ sizesw['panel_3']
						+ sizesw['compensated_offsets']
						);

	h=parseInt(Math.max(h,0));
	$('panel_1').style.height=h+'px';
	$('pageContainer').style.height=h+'px';
	$('pageContainer').style.width=w+'px';
	$('panel_3').style.height=h+'px';

	$('attributesContainer').style.height=(parseInt(h)-51)+'px';

	$('tabs_mainContainer').style.height=(parseInt(h)-16)+'px';

	$('pageLoadStatus').style.paddingTop=parseInt(8+Number(h)/2)+'px';
	$('pageLoadStatus').style.width=w+'px';

	$('tab_variables_container').setStyle({height:(parseInt(h)-16)+'px'});
	$('containerObjects_list').setStyle({height:(parseInt(h)-16-142)+'px'});

	updatePageStatus({text:"Resized",status:'idle'});
}

/*
 * get the window size...
 * */
function getWindowSize() {
	var viewportSize = document.viewport.getDimensions();
	return [viewportSize.width, viewportSize.height];
}


/*
 * toggle the ruler visibility for this page.
 * */
function toggleRuler(inputValue){
	var show=true;

	if(Object.isUndefined(inputValue))
		show=!getRuler();
	else
		show=inputValue;

	if(show){
		updatePageStatus({text:"Enable ruler",status:'idle'});
		var pages=grid._heap['pages'];
		if(pages<1)pages=1;
		$('preDocumentContainer1').addClassName('pageContainer_ruler1');
		$('preDocumentContainer1').style.backgroundImage='url("makeRuler.php?dir=X&w='+mm2px(Controls.getGlobal('page.width'))+'&h='+mm2px(Controls.getGlobal('page.height')*pages)+'&rnd='+Math.random()+'")';

		$('preDocumentContainer2').addClassName('pageContainer_ruler2');
		$('preDocumentContainer2').style.backgroundImage='url("makeRuler.php?dir=Y&w='+mm2px(Controls.getGlobal('page.width'))+'&h='+mm2px(Controls.getGlobal('page.height')*pages)+'&rnd='+Math.random()+'")';
	}else{
		updatePageStatus({text:"Disable ruler",status:'idle'});
		$('preDocumentContainer1').removeClassName('pageContainer_ruler1');
		$('preDocumentContainer1').style.backgroundImage='';

		$('preDocumentContainer2').removeClassName('pageContainer_ruler2');
		$('preDocumentContainer2').style.backgroundImage='';
	}

	$('page_ruler_').checked=(show?true:false);
	return show;
}

/*
 * Returns the state of the ruer(visible/invisible) as bool
 * */
function getRuler(){
	return $F('page_ruler_')!=null;
}

/*
 * function to modify the panel sizes according to special rules
 *
 * Workaropund for browser bugs, where the panels will not get resized even if the have no content...
 * */
function _toggleObjects(show){
	if(show && $('tabs_mainContainer_td').minimized){
		$('tabs_mainContainer_td').show();
		$('tabs_mainContainer_td').setStyle({'width':'200px'});
		$('tabs_mainContainer_td').minimized=false;
	}else if(!$('tabs_mainContainer_td').minimized){
		$('tabs_mainContainer_td').hide();
		$('tabs_mainContainer_td').setStyle({'width':'0px'});
		$('tabs_mainContainer_td').minimized=true;
	}
}

/*
 * function to modify the panel sizes according to special rules
 *
 * Workaropund for browser bugs, where the panels will not get resized even if the have no content...
 * */
function _toggleAttributes(show){
	if(show && $('attributes_mainContainer_td').minimized){
		$('attributes_mainContainer_td').show();
		$('attributes_mainContainer_td').setStyle({'width':'200px'});
		$('attributes_mainContainer_td').minimized=false;
	}else if(!$('attributes_mainContainer_td').minimized){
		$('attributes_mainContainer_td').hide();
		$('attributes_mainContainer_td').setStyle({'width':'0px'});
		$('attributes_mainContainer_td').minimized=true;
	}
}

/*
 * function to modify the panel sizes according to special rules
 *
 * Workaropund for browser bugs, where the panels will not get resized even if the have no content...
 * */
function hideObjects(){
	_toggleObjects(true);

	request_resizePanels('fast');
}

/*
 * function to modify the panel sizes according to special rules
 *
 * Workaropund for browser bugs, where the panels will not get resized even if the have no content...
 * */
function showObjects(){
	_toggleObjects(false);

	request_resizePanels('fast');
}

/*
 * function to modify the panel sizes according to special rules
 *
 * Workaropund for browser bugs, where the panels will not get resized even if the have no content...
 * */
function hidePanels(lastTab){
	_toggleObjects(true);
	_toggleAttributes(true);

	request_resizePanels('fast');
}

/*
 * function to modify the panel sizes according to special rules
 *
 * Workaropund for browser bugs, where the panels will not get resized even if the have no content...
 * */
function showPanels(lastTab){
	_toggleObjects(false);
	_toggleAttributes(false);

	request_resizePanels('fast');
}


// changes the zoom level, and updates the drawing board.
function updateZoomLevel(level){
	// updates the zoom level.
	/*
	 * - fire scheduled events for all elements
	 * - Make a temporary save into session
	 * - Make a request to change the internal zoom to the scripts side
	 * - Redraw grid & ruler if necessasry
	 * - Make a request to reload the saved session data.
	 *
	 * */

	grid.unfocus();

	$('pageLoadStatus').update("");

	eventScheduler.cancel('updatePageStatus');
	markBusyPage(0.5);

	updatePageStatus({text:"Zoom:Fire all events",status:'warning'});

	for(var i=0;i<Controls.controlList.length;i++){
		if(Controls.controlList[i] && !Object.isFunction(Controls.controlList[i])){
			var control=Controls.controlList[i];
			control.eventScheduler.fireAll();
		}
	}

	updatePageStatus({text:"Zoom:Save document data",status:'warning'});

	toggleRepeatableZones(0);

	var url="AJAXRequest.php?action=sessionSave";

	Controls.setGlobal('rulerIsVisible',false);
	if(getRuler())
		Controls.setGlobal('rulerIsVisible',true);

	if(Controls.getGlobal('rulerIsVisible'))
		toggleRuler();

	new Ajax.Request(url, {
		method: 'post',
		parameters:$('mainForm').serialize(true),
		onSuccess: function(transport) {
			// remove existing elements
			for(var i=0;i<Controls.controlList.length;i++){
				if(Controls.controlList[i] && !Object.isFunction(Controls.controlList[i])){
					Controls.remove(Controls.controlList[i]);
				}
			}

			updatePageStatus({text:"Zoom:Change zoom level",status:'warning'});
			Controls.setGlobal('zoom',level);
			var url="AJAXRequest.php?action=zoom&value="+level;
			new Ajax.Request(url, {asynchronous:false});

			updatePageStatus({text:"Zoom:Reload zoomed document",status:'warning'});
			var url="AJAXRequest.php?action=sessionLoad";
			new Ajax.Request(url, {
				method: 'get',
				onSuccess: function(transport) {
					var w=mm2px(Controls.getGlobal('page.width'));
					var h=mm2px(Controls.getGlobal('page.height'));
					var margins=Controls.getGlobal('page.margins');

					w=Math.max(0,Number(w));
					h=Math.max(0,Number(h));

					grid.onPageChanged({width:w,height:h});

					// resize document container
					$('preDocumentContainer1').setStyle({'width':(w+26)+'px', 'height':h+'px'});
					$('preDocumentContainer2').setStyle({'width':w+'px', 'height':h+'px'});
					$('documentContainer').setStyle({'width':w+'px', 'height':h+'px'});

					// insert elements into container
					String(transport.responseText).evalScripts();

					updatePageStatus({text:"Zoom:Restore grid & ruler",status:'warning'});

					if(Controls.getGlobal('rulerIsVisible'))
						eventScheduler.schedule('toggleRuler',toggleRuler,0.5);

					eventScheduler.schedule('updateGlobalGrid',function(params){
																			updatePageStatus({text:"Zoom:done",status:'ok'});
																			eventScheduler.schedule('updatePageStatus',function(){updatePageStatus();markBusyPage(0);},1.5);
																			}.bind(false,{width:w,height:h}),0.5);
					}
				});

			}
		}
	);
}

/*
 * Updates the page type to the new page settings
 * */
function updatePageType(inputType,realCall){
	var pageType=new Array();
	var Wmm,Hmm,type;

	if(inputType)
		inputType=String(inputType);
	else{
		inputType=$F('page_type_');
	}

	pageType=String(inputType).split('|');
	type=pageType[0];

	if(type=='custom'){
		Wmm=$F('page_Wmm_');
		Hmm=$F('page_Hmm_');
	}else{
		Wmm=pageType[1];
		Hmm=pageType[2];
	}

	markBusyPage(0.5);

	if(realCall==null && type=='custom'){
		eventScheduler.schedule('updatePageType',updatePageType.bind(this,inputType,true),1.5);
		return false;
	}


	if(Wmm!=0 && Hmm!=0){
		$('page_Wmm_').value=Wmm;
		$('page_Hmm_').value=Hmm;
	}

	var margins={};

	margins.top=Number($F('page_margins_top_'));
	margins.bottom=Number($F('page_margins_bottom_'));
	margins.left=Number($F('page_margins_left_'));
	margins.right=Number($F('page_margins_right_'));

	Wmm=Math.max(0,Number(Wmm)-(margins.left+margins.right));
	Hmm=Math.max(0,Number(Hmm)-(margins.top+margins.bottom));

	if(type=='custom'){
		// if we selected a "custom" page type, then enable the user to manually edit the page dimensions.
		$('page_Wmm_').writeAttribute('readonly',false);
		$('page_Hmm_').writeAttribute('readonly',false);

		$('page_Wmm_').removeClassName('disabled');
		$('page_Hmm_').removeClassName('disabled');
	}else{
		$('page_Wmm_').writeAttribute('readonly',true);
		$('page_Hmm_').writeAttribute('readonly',true);

		$('page_Wmm_').addClassName('disabled');
		$('page_Hmm_').addClassName('disabled');
	}


	if($F('repeatable_edit_')){
		toggleRepeatableZones(1);
		return;
	}

	var wh=updateRawPageDimensions(Wmm,Hmm,margins);

	updatePageStatus({text:"Changed page type",status:'idle'});

	eventScheduler.schedule('toggleRuler',function(params){if(Controls.getGlobal('rulerIsVisible'))toggleRuler(true);grid.onPageChanged({width:params.width,height:params.height});markBusyPage(0);}.bind(true,{width:wh.w,height:wh.h}),1.0);

	eventScheduler.schedule('forcePageIdle',function(params){grid.onPageChanged({width:params.width,height:params.height});markBusyPage(0,true);}.bind(true,{width:wh.w,height:wh.h}),2.5);
}

/*
 * Called from updatePageType() to modify the current page dimensions
 * */
function updateRawPageDimensions(Wmm,Hmm,margins){
	if(margins==null){
		margins={};
		margins.top=Number($F('page_margins_top_'));
		margins.bottom=Number($F('page_margins_bottom_'));
		margins.left=Number($F('page_margins_left_'));
		margins.right=Number($F('page_margins_right_'));
	}

	Controls.setGlobal('page.margins',margins);
	Controls.setGlobal('page.width',Wmm);
	Controls.setGlobal('page.height',Hmm);

	var w,h;
	w=Number(mm2px(Wmm));
	h=Number(mm2px(Hmm));
	$('documentContainer').setStyle({width:w+'px',height:h+'px'});

	grid._heap['pageW']=w;
	grid._heap['pageH']=h;

	var cw=w;
	var ch=h;
	$('preDocumentContainer1').setStyle({width:(cw+26)+'px',height:ch+'px'});
	$('preDocumentContainer2').setStyle({width:cw+'px',height:ch+'px'});

	Controls.setGlobal('rulerIsVisible',false);
	if(getRuler())
		Controls.setGlobal('rulerIsVisible',true);

	return {'w':w, 'h':h};
}

/**
 * Opens tge preview window.
 *
 * steps:
 * 	- create a temporary save of the document structure
 * 	- open up the popup, which should either display the previewed document, or force the download..
 */
function previewPage(){
	updatePageStatus({text:"saving preview data",status:'warning'});

	for(var i=0;i<Controls.controlList.length;i++){
		if(Controls.controlList[i] && !Object.isFunction(Controls.controlList[i])){
			var control=Controls.controlList[i];
			control.eventScheduler.fireAll();
		}
	}

	Controls.setGlobal('status','1/4 Save document data');
	grid.unfocus();

	var url="AJAXRequest.php?action=sessionSave&preGenerateOutput=1";

	new Ajax.Request(url, {
			method: 'post',
			parameters:$('mainForm').serialize(true),
			onSuccess: function(transport) {
				if(transport.responseText=='ok'){
					updatePageStatus({text:"opening preview window",status:'ok'});
					var previewType=$F('preview_type_');
					var previewAction=$F('preview_action_');

					window.open(
						"AJAXRequest.php?action=previewTemplate&previewType="+previewType+"&previewAction="+previewAction,
						"PDF_preview",
						"width=800, height=600, resizable=yes,scrollbars=yes");
					updatePageStatus({text:"idle",status:'idle'});
				}else{
					updatePageStatus({text:"cannot preview",status:'error'});
				}
			}
		});
	return true;
}

/*
 * periodically called function to save the document data to a temporary location.
 *
 * expanding this function could lead to the develop of "undo" operations?
 * */
function autoSaveDocument(realCall){
	if(realCall && Controls.isIdle() && Controls.getGlobal('pageChanged')){
		var serializedForm=$('mainForm').serialize(false);
		var serializedSize=Number(String(serializedForm).length/1024).round(1);

		updatePageStatus({text:"autosaving document data ("+serializedSize+"Kb)",status:'warning'});

		var url="AJAXRequest.php?action=autoSave"+'&rnd=' + Math.random();

		new Ajax.Request(url, {
			method: 'post',
			parameters:$('mainForm').serialize(true),
			onSuccess: function(transport) {
				if(transport.responseText=='ok'){
					updatePageStatus({text:"saved document data",status:'ok'});
				}else{
					updatePageStatus({text:"cannot save document data",status:'error'});
				}

				eventScheduler.schedule('autoSaveDocument',autoSaveDocument.bind(true,true),60);

				Controls.setGlobal('pageChanged',1);
			}
		});
	}else{
		eventScheduler.schedule('autoSaveDocument',autoSaveDocument.bind(true,true),30);
	}
}

/*
 * do a quick-background-save of the document
 * */
function fastSaveDocument(documentID,realCall,calls){
	if(!documentID){
		updatePageStatus({text:"invalid document data(documentID)",status:'error'});
		return false;
	}

	if(Controls.getGlobal('focus')){
		var control=Controls.getGlobal('focus');
		control.clearFocus();

		realCall=false;
	}

	if(realCall && Controls.isIdle()){

		for(var i=0;i<Controls.controlList.length;i++){
			if(Controls.controlList[i] && !Object.isFunction(Controls.controlList[i])){
				var control=Controls.controlList[i];
				control.eventScheduler.fireAll();
			}
		}

		var serializedForm=$('mainForm').serialize(false);
		var serializedSize=Number(String(serializedForm).length/1024).round(1);

		updatePageStatus({text:"saving document data ("+serializedSize+"Kb)",status:'warning'});

		var url="AJAXRequest.php?action=fastSave"+'&id='+documentID+'&rnd=' + Math.random();

		new Ajax.Request(url, {
			method: 'post',
			parameters:$('mainForm').serialize(true),
			onSuccess: function(transport) {
				if(transport.responseText=='ok'){
					updatePageStatus({text:"saved document data",status:'ok'});
					Controls.setGlobal('pageChanged',false);
					$('button_fastSaveDocument').setStyle({'fontWeight':'normal'});
				}else{

					if(transport.status!=200){
						updatePageStatus({text:"Cannot save document data. Please check the server connection.",status:'error',global:true,onlyGlobal:true});
					}else{
						updatePageStatus({text:"Cannot save document data. Server did not confirm save. Message: "+transport.responseText,status:'error',global:true,onlyGlobal:true});
					}

					updatePageStatus({text:"cannot save document data",status:'error',global:false});
				}
			},
			onFailure: function(transport){
				updatePageStatus({text:"Cannot save document data. Server dit not respond as expected",status:'error',global:true,onlyGlobal:true});
				updatePageStatus({text:"cannot save document data",status:'error',global:false});

				Controls.setGlobal('pageChanged',true);
				$('button_fastSaveDocument').setStyle({'fontWeight':'bold'});
			}
		});
	}else{

		grid.unfocus();

		calls=parseInt(calls);
		if(isNaN(calls))calls=1;

		if(calls>8)calls=8;

		var text='waiting document';
		text=text + String('.').times(calls);
		updatePageStatus({'text':text,status:'idle'});
		eventScheduler.schedule('fastSaveDocument',fastSaveDocument.bind(true,documentID,true,calls+1),1);
	}
}

/*
 * make a quick rtun-through the variable list, and search for matches.
 * */
function quickFilterVariables(text,input,realCall){
	if(!realCall){ //delay the event
		eventScheduler.schedule('quickFilterVariables',quickFilterVariables.bind(true,text,input,true),0.5);
	}else{
		// first build a list of text nodes
		var container=$('variable_list_container');

		var childs=container.descendants();
		var matches=new Array();

		//scan the list for matches, . a match should be considered an element that matches both the variable ID, or the variable translation
		var scanned=false;
		if(!String(text).empty()){
			scanned=true;

			text=String(text).replace(/%/g,'');

			for(var i=0;i<childs.length;i++){
				var child=childs[i];
				var matched=false;

				if(child.hasClassName('documentVars_var')){ // w found a href node, check its content to see if we have a match
					var regexp=new RegExp('(.*)'+text+'(.*)','gi');
					matched=String(child.innerHTML).match(regexp) || String(child.identify()).match(regexp);
				}

				if(matched){
					matches.push(child);
				}
			}
		}

		if(scanned){
			if(matches.length==0){
				$(input).addClassName('input_notFound');
				eventScheduler.schedule('restore_quickFilterVariables_text',function(input){$(input).removeClassName('input_notFound');}.bind(true,input),1.5);

				eventScheduler.executeTask('restore_quickFilterVariables_variables');
			}else{
				// restore old variables:)
				eventScheduler.executeTask('restore_quickFilterVariables_variables');

				var scrolled=false;
				for(var i=0;i<matches.length;i++){
					var match=matches[i];
					match.addClassName('documentVars_var_matched');

					var parent_node=match.up();
					var parent_sibling=parent_node.previous().down();

					if(parent_node.hasClassName('documentVars_varList_collapsed')){ // if the element is collapsed, then expand it
						switchClasses(parent_sibling,'documentVars_category','documentVars_category_collapsed',parent_node,'documentVars_varList','documentVars_varList_collapsed');
					}

					if(!scrolled){
						scrolled=true;
						match.scrollTo();
						match.focus();
					}
				}

				eventScheduler.schedule('restore_quickFilterVariables_variables',function(matches){for(var i=0;i<matches.length;i++){matches[i].removeClassName('documentVars_var_matched');};}.bind(true,matches),600);
			}
		}else{
			eventScheduler.executeTask('restore_quickFilterVariables_variables');
		}

		forceResizePanel('variables');
	}
}


/*
 * generalized function to prevent pressing backspace, which may lead to history.back() equivalents
 * */
function inhibitBackspace(event){
	if(event.keyCode==8) return false;
	return true;
}
Event.observe(window,'keydown',inhibitBackspace);

/*
 * Handle ceratin key combinations
 * */
function watchKeys(event){

	// ignore keypresses in the text inputs
	focusedTag=Event.element(event).tagName;
	if(	focusedTag=='TEXTAREA' || focusedTag=='INPUT' || focusedTag=='SELECT'){
		return true;
	}

	var actions=Controls.getGlobal('keyActions');

	if(actions==null)actions=new Array();
	var stopEvent=false;
	var fastSwitch=false;

	if(event.ctrlKey){
		switch(event.keyCode){
			case 83:	// ctrl+S - save page
				actions['savePage']=true;
				stopEvent=true;
			break;

			case 46:	// ctrl+DEL - delete current element
				actions['delElement']=true;
				stopEvent=true;
			break;

			case 45:	// ctrl+INS - clone current element
				actions['cloneElement']=true;
				stopEvent=true;
			break;

			case 38:	// ctrl+UP   - move current element in the orderIndex stack
				var moveUp=true;
			case 40:	// ctrl+DOWN - move current element in the orderIndex stack
				if(isNaN(actions['orderIndex']))actions['orderIndex']=0;

				actions['orderIndex']=actions['orderIndex']+(moveUp?1:-1);

				if(actions['orderIndex'] >  10)actions['orderIndex']=10;
				if(actions['orderIndex'] < -10)actions['orderIndex']=-10;
				stopEvent=true;
			break;

			case 39:	// ctrl+LEFT - move selection to the next element in the internal Controls list
				var moveUp=true;
			case 37:	// ctrl+RIGHT - move selection to the next element in the internal Controls list

				actions['moveSelection']=(moveUp?1:-1);
				stopEvent=true;
				fastSwitch=true;
			break;
		}

	}

	Controls.setGlobal('keyActions',actions);

	if(stopEvent){
		eventScheduler.schedule('handleKeyActions',handleKeyActions,(fastSwitch?0.5:0));

		Event.stop(event);
		return false;
	}

	return true;
}

/*
 * Toggle displaying of the repeatable zones
 * */
function toggleRepeatableZones(editRepeatables){
	if(editRepeatables)
		enterEditRepeatableZones();
	else
		enterEditNonRepeatableZones();
}

/*
 * Enter the "edit repeatables" mode
 * */
function enterEditRepeatableZones(){
	var elements=Controls.getElements();

	if(elements){
		for(var i=0; i<elements.length;i++){
			var control=elements[i];


			if(control.child.attributes.repeatable){
				control.child.preview.show();
			}else{
				control.child.preview.hide();
			}
		}
	}

	var margins={};
	margins.top=Number($F('page_margins_top_'));
	margins.bottom=Number($F('page_margins_bottom_'));
	margins.left=Number($F('page_margins_left_'));
	margins.right=Number($F('page_margins_right_'));

	var wh=updateRawPageDimensions($F('page_Wmm_'),$F('page_Hmm_'),{top:0,bottom:0,left:0,right:0});

	if(!Controls.getGlobal('repeatableZone_highlighter')){
		var region=new Region();
		region.attributes.morphDuration=0.5;
		region.attributes.zIndex=98;
		region.attributes.backgroundColor='#F8F8F8';
		region.attributes.opacity=0.75;
		region.attributes.border='1px dashed #444';

		region.attributes.X=mm2px($F('page_Wmm_')/2);
		region.attributes.Y=mm2px($F('page_Hmm_')/2);

	}else{
		var region=Controls.getGlobal('repeatableZone_highlighter');
	}

	region.setup({		X:mm2px(margins.left),
						Y:mm2px(margins.top),
						width:mm2px($F('page_Wmm_') - (margins.left+margins.right)),
						height:mm2px($F('page_Hmm_') - (margins.top+margins.bottom)),
						morph:true
						});
	region.show();

	eventScheduler.schedule('enterEditRepeatableZones_post',
		function(params){
			if(Controls.getGlobal('rulerIsVisible'))
				toggleRuler(true);
			grid.onPageChanged({width:params.width,height:params.height});
			markBusyPage(0);
		}.bind(true,{width:wh.w,height:wh.h}),0.25);

	if(!Controls.getGlobal('repeatableZone_highlighter')){
		Controls.setGlobal('repeatableZone_highlighter',region);
	}
}

/*
 * Exit the "edit repeatables" mode, and re-enter (the default) page-editing mode
 * */
function enterEditNonRepeatableZones(){
	var elements=Controls.getElements();

	if(elements){
		for(var i=0; i<elements.length;i++){
			var control=elements[i];


			if(control.child.attributes.repeatable){
				control.child.preview.hide();
			}else{
				control.child.preview.show();
			}
		}
	}

	var margins={};
	margins.top=Number($F('page_margins_top_'));
	margins.bottom=Number($F('page_margins_bottom_'));
	margins.left=Number($F('page_margins_left_'));
	margins.right=Number($F('page_margins_right_'));

	var wh=updateRawPageDimensions($F('page_Wmm_') - (margins.left+margins.right),$F('page_Hmm_') - (margins.top+margins.bottom),margins);

	eventScheduler.schedule('enterEditNonRepeatableZones_post',
		function(params){
			if(Controls.getGlobal('rulerIsVisible'))
				toggleRuler(true);
			grid.onPageChanged({width:params.width,height:params.height});
			markBusyPage(0);
		}.bind(true,{width:wh.w,height:wh.h}),0.1);

	if(Controls.getGlobal('repeatableZone_highlighter')){
		Controls.getGlobal('repeatableZone_highlighter').hide();
	}
}

// handle any scheduled events in here!
function handleKeyActions(){
	var actions=Controls.getGlobal('keyActions');

	if(actions['savePage']){
		fastSaveDocument(Controls.getGlobal('documentID'));
		actions['savePage']=null;
	}

	if(actions['delElement']){
		var control=Controls.getGlobal('focus');

		// check if anything is focused first:)
		if(control){
			var index=control._controlsID;

			if(control)
				Controls.remove(control);

			actions['delElement']=null;

			// try to set focus on the previous element
			var newFocus=Controls.controlList.prevValue(index);

			if(!newFocus)newFocus=Controls.controlList.nextValue(index);

			if(newFocus)
				newFocus.setFocus();
		}
	}

	if(actions['cloneElement']){
		var control=Controls.getGlobal('focus');

		if(control)
			Controls.clone(control);

		actions['cloneElement']=null;
	}

	if(actions['orderIndex']){
		var control=Controls.getGlobal('focus');

		if(control && control.child.attributes['fixed'] && control.child.attributes['orderIndex']!=null){
			var orderIndex=control.child.attributes['orderIndex'];

			orderIndex=orderIndex + actions['orderIndex'];
			control.child.attributes['orderIndex']=orderIndex;
			control.child.fillAttributes({orderIndex:orderIndex});

			control.child.onChange(false,'orderIndex');
		}

		actions['orderIndex']=null;
	}

	if(actions['moveSelection']){
		var control=Controls.getGlobal('focus');

		if(control){
			if(actions['moveSelection']>0){
				var newFocus=Controls.controlList.nextValue(control._controlsID);
			}else{
				var newFocus=Controls.controlList.prevValue(control._controlsID);
			}

			if(newFocus){
				newFocus.setFocus();
			}
		}
		actions['moveSelection']=null;
	}

	return true;
}
Event.observe(window,'keydown',watchKeys);


/*
 * updates the page status with various informations
 *
 * stat may be either string, or object.
 * if its an object, then stat.text should be defined as string
 *
 * selfCall gets true on the second self-call. if slfCall is true, then erase the old message
 * */
function updatePageStatus(stat,selfCall){
	var status={};
	var nextCall=2.5;

	if(stat){
		if(stat.text){
			status=stat;
		}else{
			status.text=String(stat);
		}
	}else{
		status.text="";
	}

	if(!selfCall){
		// global means that the message will be shown in the messageDiv
		if(status.global || status.onlyGlobal){
			var cls="";
			switch(status.status){
				case 'ok':
					cls='msgSuccess';
				break;
				case 'error':
					cls='msgError';
				break;
				case 'warning':
					cls='msgWarning';
				break;
				case 'idle':
					cls='msgInfo';
				break;
			}

			$('showMessageDiv_static').update(status.text);
			$('showMessageDiv_static').className='message '+cls;
			new Effect.Appear($('showMessageDiv_static'),{duration:0.1});

			nextCall*=5;
		}

		if(!status.onlyGlobal){
			// the message will be shown in the small messageBox in the bottom of the page
			var style={color:'#000',fontWeight:'normal'};

			switch(status.status){
				case 'ok':
					style.color='#282';
					nextCall*=1.5;
				break;
				case 'error':
					style.color='#c00';
					style.fontWeight='bold';
					nextCall*=3;
				break;
				case 'warning':
					style.color='#FFDB9A';
					nextCall*=1.75;
				break;
				case 'idle':
					style.color='#ccc';
					nextCall*=0.75;
				break;
			}

			$('pageStatus').update(status.text);
			$('pageStatus').setStyle(style);
		}

		eventScheduler.schedule('updatePageStatus',updatePageStatus.bind(true,status,true),nextCall);
	}else{
		switch(status.status){
			case 'ok':
				nextCall*=0.5;
			break;
			case 'error':
				nextCall*=2;
			break;
			case 'warning':
				nextCall*=1.5;
			break;
			case 'idle':
				nextCall*=0.5;
			break;
		}

		if($('showMessageDiv_static').visible()){
			new Effect.Fade($('showMessageDiv_static'),{duration:nextCall});
		}
		$('pageStatus').update("");

		status.text="";
	}
}

// updates the global grid mesh - sets gridType to the selected grid type
function updateGlobalGrid(gridType){
	grid.setupGrid({gridType:gridType});
	grid.focus();
}

function updateGlobalSnap(snapType){
	grid.setupSnap({snapType:snapType});
	grid.focus();
}


/*
 * when a variable is clicked.
 * 	2 actions may be taken:
 * 		- show the variable internal code
 * 		- insert/replace the variable code into any pre-selected textarea
 * */
function clickVariable(obj,value,event){
	var control=Controls.getGlobal('focus');
	var lastFocus=Controls.getGlobal('targetInput');

	var attributesControls={};
	if(control){
		attributesControls=control.child.getAttributesControls();
	}

	var insertionValue='%'+value+'%';

	if(event && event.ctrlKey)insertionValue=insertionValue+"\n";

	if(event && event.shiftKey) {
		var textElement = null;
		if(control) {
			var attributesControls = control.child.getAttributesControls();
			var attributeName = null;

			if(lastFocus){
				textElement = attributesControls[$(lastFocus).identify()];
				attributeName = lastFocus;
			} else {
				textElement = $(attributesControls.text);
				attributeName = 'text';
			}
		}

		var variableEditor = new _variableEditor(value, {textElement: textElement, control: control, attributeName: attributeName});

		return false;
	}

	// if this control has the 'text' attribnute defined, then use that one.
 	if(control || (control && attributesControls.text)){	// add the variable to the selected control
 		if(attributesControls.text){
			var attributesControls=control.child.getAttributesControls();
			if(lastFocus){
				var attributeName=$(lastFocus).identify();
				insertText(insertionValue,attributesControls[attributeName]);
				$(lastFocus).focus();
				return control.onChange(null,attributeName,'queue');
			}else{
				insertText(insertionValue,attributesControls.text);
				$(attributesControls.text).focus();
				return control.onChange(null,'text','queue');
			}
 		}else{	// the text attribute is not defined, try to make a 'lucky' insert
 			var attributesControls=control.child.getAttributesControls();
			if(lastFocus){
				var attributeName=$(lastFocus).identify();
				insertText(insertionValue,attributesControls[attributeName]);
				$(lastFocus).focus();
				return control.onChange(null,attributeName,'queue');
			}else{
				try{
					insertText(insertionValue,attributesControls.text);
					control.onChange(null,'text','queue');	// blindly call the onchange event for the text attribute
					return true;
				}catch(ex) {}
			}
 		}

		return false;
	}else{							// display the internal variable ID
		$(obj).animating=true;

		var duration=5;
		if($(obj).oldText==null)$(obj).oldText=$(obj).innerHTML;
		$(obj).update(insertionValue);
		$(obj).addClassName('documentVars_var_highlighted');
		$(obj).removeClassName('documentVars_var');

		var restore_hrefs=Controls.getGlobal('restore_hrefs');
		if(restore_hrefs==null)restore_hrefs=new Array();

		if(restore_hrefs.indexOf($(obj).identify())==-1)restore_hrefs.push($(obj).identify());

		Controls.setGlobal('restore_hrefs',restore_hrefs);

		function anonymous(){
			var restore_hrefs=Controls.getGlobal('restore_hrefs');

			if(restore_hrefs){
				for(var i=0;i<restore_hrefs.length;i++){
					var obj=restore_hrefs[i];
					$(obj).addClassName('documentVars_var');
					$(obj).removeClassName('documentVars_var_highlighted');
					$(obj).update($(obj).oldText);

					$(obj).oldText=null;
					$(obj).animating=false;
					Controls.setGlobal('restore_hrefs',null);
				}
			}
		}

		eventScheduler.schedule('restore_hrefs',anonymous.bind(obj),duration);

		$(obj).blur();
		return true;
	}
}

/*
 * General page-destroy routine for the JS side, to avoid memory leaks..even if they still happen
 * */
Event.observe(window, 'unload', function(){
	updatePageStatus({text:"Cleaning up memory",status:'warning'});

	/* cleanup everything */
	Controls.destroy();

	objectList.destroy();

	eventScheduler.destroy();

	leftTabs.destroy();

	createButtons.destroy();

	/* clear global variables */

	window.detectedSize=null;

	// destroy CloneTemplates
	for(var i in CloneTemplates){
		if(!Object.isFunction(CloneTemplates[i])){
			if(CloneTemplates[i].destroy)
				CloneTemplates[i].destroy();
			CloneTemplates[i]=null;
		}
	}

	updatePageStatus({text:"Closing page",status:'warning'});
	eventScheduler=null;

	Event.stopObserving(window,'keydown',inhibitBackspace);
	Event.stopObserving(window,'keydown',watchKeys);
})


