/*
var $j = window.jQuery ? jQuery.noConflict() : undefined;
var $p = window.$;
*/

UI.WindowManager.Stack.addMethods({ // 04.11.2009 Ossig Codefix
	destroy: function() {
	}
});

var GUIBase = Class.create({
	_windowNameKey: "GEWindowName", // 11.11.2009 Ossig read value (/ write reference member) by design.
	urlAppendWindowNameToken: function(url, name) {
		if (!Object.isString(name)) {
			var contentWindow = name;
			name = this._getContentWindowName(contentWindow);
		}
		var token = this._windowNameKey + "=" + name;
		var urlPart = url.split("#", 2);
		return urlPart[0] + "&" + token + (urlPart.length == 2 ? "#" + urlPart[1] : "");
	},
	_getContentWindowName: function(contentWindow) { // 04.09.2009 Ossig contentWindow could be a frame (unmanaged) of a frameset (managed).
		var geWindow = this.getGEWindow(contentWindow);
		return (geWindow && geWindow.getContentWindow() == contentWindow) ? geWindow.name : contentWindow.name; // 04.09.2009 Ossig Don't give frame name of the frameset.
	},
	getOpenerContentWindow: function(contentWindow) {
		var geWindow = this.getGEWindow(contentWindow);
		return geWindow ? geWindow.openerContentWindow : undefined;
	},
	setLocation: function(sURL, contentFrame, openerWindow) {
		var geWindow = this.getGEWindow(contentFrame);
		if (!geWindow) return;
		geWindow.setLocation(sURL, contentFrame, openerWindow);
	},
	getFrameSet: function(frame) { // 16.08.2009 Ossig Ancient TopFrame.
		geSystem.assert(false, "abstract function");
	},
	checkOrigFrame: function(frame, _opt) { // _opt={checkID, checkFrameSet}
		// if (arguments.length < 2) checkID = true;
		// return frame && !frame.closed && frame.NativeGUI && (!checkID || $_id(frame) == "OrigFrame") ? frame : undefined; // 15.10.2009 .closed against StartGlobalEagle. Problems with IE8
		if (!frame || frame.closed) return undefined;

		var opt = { checkID: true, checkFrameSet: false };
		Object.extend(opt, _opt || {});

		var origFrame;
		if (opt.checkFrameSet) {
			var frameSet = this.getFrameSet(frame);
			origFrame = frameSet.frames[0]; // 15.10.2009 Ossig frames[0] not available when frameset being built. origFrame==undefined when frameSet is a single window.
			GUI.log("checkOrigFrame: origFrame=", origFrame, "frame.NativeGUI=", frame.NativeGUI, "$_id(origFrame)=", $_id(origFrame), "frames[0]=", frameSet.frames[0], "frames=", $A(frameSet.frames));
		} else
			origFrame = frame;
		return origFrame && origFrame.NativeGUI && (!opt.checkID || $_id(origFrame) == "OrigFrame") ? origFrame : undefined;
	},
	initFootbar: function(contentWindow, contextButtonOpt, menuButtonOptArr, buttonOptArr) {
		var geWindow = this.getGEWindow(contentWindow);
		var footbar = geWindow.footbar;
		if (!footbar) return;
		var FootbarButton = this._FootbarButton;
		var contextButton = contextButtonOpt ? new FootbarButton(contextButtonOpt).toObject() : undefined;
		var menuButtonArr = menuButtonOptArr ? menuButtonOptArr.collect(function(buttonOpt) { return new FootbarButton(buttonOpt).toObject(); }) : undefined;
		var buttonArr = buttonOptArr ? buttonOptArr.collect(function(buttonOpt) { return new FootbarButton(buttonOpt).toObject(); }) : undefined;
		footbar.init(contextButton, menuButtonArr, buttonArr);
	},
	resetFootbarState: function(contentWindow) {
		var geWindow = this.getGEWindow(contentWindow);
		var footbar = geWindow.footbar;
		if (!footbar) return;
		footbar.resetState();
	},
	_FootbarButton: Class.create({
		initialize: function(opt) {
			function getClickCallback(contentWindow, id) {
				var button = contentWindow.$(id);
				if (!button) return undefined;
				if (button.click) return button.click.bind(button);
				var jButton = contentWindow.$j("#" + id); // 09.01.2010 Ossig For anchor element: onClick has to be defined. createEvent, initMouseEvent, dispatchEvent.
				return jButton.trigger.bind(jButton, "click");
			}
			this._opt = opt;
			if (!opt.callback && opt.id) opt.callback = getClickCallback(opt.contentWindow, opt.id);
		},
		toObject: function() {
			return Object.clone(this._opt);
		}
	}),
	renameTab: function(contentWindow, name) {
		var geWindow = this.getGEWindow(contentWindow);
		if (!geWindow) return;
		geWindow.renameTab(name);
	}
});

/* 14.09.2009 Ossig static function
Object.extend(GUIBase, {
	GEWindowBase: Class.create({
		urlAppendWindowNameToken: function(url) {
			return this.GUI.urlAppendWindowNameToken(url, this.name);
		}
	})
});
*/

GUIBase.GEWindowBase = Class.create({
	urlAppendWindowNameToken: function(url) {
		return this.activeGUI.urlAppendWindowNameToken(url, this.name);
	},
	setLocation: function(sURL, contentFrame, openerWindow) {
		// var contentWindow = this.getContentWindow(); // 13.09.2009 Ossig frameSetWindow
		if (!contentFrame) contentFrame = this.getContentWindow();
		if (!contentFrame) return;

		// 15.09.2009 Ossig window/contenFrame is being reloaded. Take dtFrame.
		var dtFrame = getDTFrame();
		dtFrame.GUI.log("GUIBase.GEWindowBase.setLocation (start)");
		if (!openerWindow) openerWindow = contentFrame;

		var sURLEx = this.urlAppendWindowNameToken(sURL, contentFrame);
		sURLEx = openerWindow.geSystem.GetAbsSystemURL(openerWindow.DotNetWindowCall(sURLEx));
		// var geOpener = contentFrame.geOpener;
		// var opener = contentFrame.opener;
		var name = $_id(contentFrame); // contentFrame.name;

		[contentFrame].concat($A(contentFrame.frames)).each(function(frame) {  // 13.09.2009 Ossig w==contentFrame
			frame.document.loaded = false;
		});

		// 30.08.2009 Ossig http://www.java2s.com/Tutorial/JavaScript/0320__Location/Changelocationhref.htm
		contentFrame.location.href = sURLEx; // Ossig: Assumed that window already exists.
		var w = contentFrame;
		/*
		var parentWindow = OrigFrame;
		// var w = parentWindow.open(sURLEx, name, openerWindow.geSystem.getWindowOpenFeature());
		var w = parentWindow.open(sURLEx, name); // 13.09.2009 Ossig w==contentFrame
		*/
		/*
		// 30.08.2009 Ossig perhaps not needed. opener implicit defined in contentFrame.
		w.OrigFrame = OrigFrame; // 27.08.2009 Ossig In case w=openerContentWindow: w.geOpener.OrigFrame=OrigFrame;
		// w.geOpener = geOpener;
		w.opener = opener; // 07.04.2004 Ossig: IE needs this additional assignment in case "reopened".
		// Position.clone(parentWindow,w);
		*/
		/*
		GUI.log("A1, w.document.loaded=", w.document.loaded);
		this.registerContentWindow(w);
		GUI.log("A2, w.document.loaded=", w.document.loaded);
		documentWhenReady(w.document, this.registerContentWindow.bind(this, w)); // 13.09.2009 Ossig Give w a chance to become initialized.
		GUI.log("A3, w.document.loaded=", w.document.loaded);
		documentWhenReady.delay(10, w.document, this.registerContentWindow.bind(this, w)); // 13.09.2009 Ossig Give w a chance to become initialized.
		GUI.log("A4, w.document.loaded=", w.document.loaded);
		*/
		/*
		documentWhenReady(w.document, function(w, callback) {
		new w.SyncFrameSetProp().whenLoadSync(w.document, callback);
		} .delay(4, w, this.registerContentWindow.bind(this, w)));
		*/
		new dtFrame.PeriodicalExecuter(function(executer) {
			dtFrame.GUI.log("ping");
			if (!w.document || w.document.loaded) return;
			dtFrame.GUI.log("pong");
			this.registerContentWindow(w);
			executer.stop();
		} .bind(this), 0.1);
		dtFrame.GUI.log("GUIBase.GEWindowBase.setLocation (end)");
	}
});

_documentWhenReady = function(callback) {
	if (document.loaded)
		callback.call(document);
	else
		document.observe('dom:loaded', callback);
}

function documentWhenReady(documentArg, callback) {
	// 26.11.2009 Ossig _window.document changes instance: _document.defaultView.document != _document.
	/*
	var _window = documentArg instanceof Window ? documentArg : documentArg.defaultView ? documentArg.defaultView : documentArg.parentWindow;
	var _document = documentArg instanceof Document ? documentArg : _window.document;
	*/
	/*
	var _window = documentArg instanceof DOMWindow ? documentArg : documentArg.defaultView ? documentArg.defaultView : documentArg.parentWindow;
	var _document = documentArg instanceof HTMLDocument ? documentArg : _window.document;
	*/
	var _window = documentArg.defaultView ? documentArg.defaultView : documentArg.parentWindow;
	var _document = documentArg;
	/*
	GUI.log("documentWhenReady -", counter++, ": _document=", _document, ", _document.whenReady=", _document.whenReady, ", _document.loaded=", _document.loaded);
	if (_document.loaded)
	callback.call(_document);
	else {
	// Event.observe(_document.defaultView, "load", callback.bind(_document)); // 13.09.2009 Ossig ProtoType for _document may not be initialized yet. bind maybe undefined.
	var defaultView = _document.defaultView;
	if (!defaultView) defaultView = _document.parentWindow;  // 15.10.2009 Ossig IE8 parentWindow
	Event.observe(defaultView, "load", callback); // 13.09.2009 Ossig ProtoType for _document may not be initialized yet. bind maybe undefined.
	}
	return;
	*/
	/*
	GUI.log("documentWhenReady: _document=", _document, ", _document.whenReady=", _document.whenReady);
	_document.whenReady ? _document.whenReady(callback) : documentWhenReady.delay(0.1, _document, callback);
	*/
	var counter = 0;
	function execute() {
		var _document = _window.document;
		// if (!_document) return true; // 26.11.2009 Ossig Happens, but no idea why.
		var stop=!_document || _window._documentWhenReady;
		GUI.log("documentWhenReady", (stop ? "pong" : "ping"), counter++, ": _document=", _document, ", _documentWhenReady=", _documentWhenReady, ", _document.loaded=", _document ? _document.loaded : undefined);
		if (_document && _window._documentWhenReady) _window._documentWhenReady(callback);
		return stop;
	}
	if (execute()) return;
	new window.PeriodicalExecuter(function(_window, callback, executer) {
		if (execute()) executer.stop();
	} .bind(this, _window, callback), 1);
}

if (!document.whenReady) { // 19.08.2009 prototype-ui
	document.whenReady = (function() {
		var queue = [];
		document.observe('dom:loaded', function() {
			queue.invoke('call', document);
			queue.clear();
			document.whenReady = function(callback) { callback.bind(document).defer() };
		});
		return function(callback) { queue.push(callback) };
	})();
}

Event.observe(window, "load", function () {
	if (document.windowLoaded) return;
	document.windowLoaded = true;
	document.fire('dom:windowloaded');
});
document.whenWindowReady = (function() {
	var queue = [];
	document.observe('dom:windowloaded', function() {
		queue.invoke('call', document);
		queue.clear();
		document.whenWindowReady = function(callback) { callback.bind(document).defer() };
	});
	return function(callback) { queue.push(callback) };
})();

function $_id(id) { // nearly the same as $(object).id
	// return Object.isString(id) || !id ? id : id.id;
	return Object.isString(id) || !id ? id : id.id ? id.id : id.name; // 05.09.2009 name technique tolerance.
}

if (!window.UI) { // 18.04.2010 Ossig proptype-ui
	document.whenReady(function() {
		window.$head = $(document.getElementsByTagName('head')[0]);
		window.$body = $(document.body);
	});
}

function getDTFrame(frame) { // 16.08.2009 Ossig DT ... DeskTop
	///<summary>getDTFrame summary</summary>
	///<param name="frame">frame Window</param>
	///<returns>main browser window</returns>
	/*
	function checkFrame(frame) { // StopGlobalEagle Popup outside GUI frame.
		return frame && frame.remoteGUI ? frame : undefined;
	}
	*/
	if (!frame) frame = window;
	/*
	while (frame.parent != frame)
	frame = frame.parent;
	return frame;
	*/
	return frame.top;
}

function reposToScreen(w, opt) {
	w.resizeTo(opt.width, opt.height); // 23.05.2006 Ossig Make window small, then it's easier to pack into the edge of the screen (Firefox).
	w.moveTo(opt.left, opt.top);
	w.resizeTo(opt.width, opt.height); // 23.05.2006 Ossig In case the window could not be resized on old position (IE).
}

/*
function _getGUIInstance(remoteGUIFlag) {
	/+
	function getOrigFrame(frame) {
		function checkFrame(frame) { // 04.09.2009 Ossig Menu FrameSet access to OrigFrame still no ready.
			return frame && !frame.closed && frame.nativeGUI ? frame : undefined;
		}
		if (!frame) frame = window;
		if (checkFrame(frame.OrigFrame)) return frame.OrigFrame;
		if (checkFrame(frame.top.opener)) return frame.top.opener;
		return frame;
	}
	+/
	if (window.console) window.console.log("_getGUIInstance: window.OrigFrame=", window.OrigFrame);
	if (!remoteGUIFlag) return window.OrigFrame.nativeGUI;
	var dtFrame = getDTFrame();
	return dtFrame.remoteGUI ? dtFrame.remoteGUI : dtFrame.nativeGUI; // Popup outside GUI frame", "return getOrigFrame().nativeGUI;
}
*/

function initGUI(remoteGUIOpt) {
	var dtFrame = getDTFrame();
	/*
	if (!dtFrame.remoteGUI && dtFrame.RemoteGUI) dtFrame.remoteGUI = new dtFrame.RemoteGUI();
	if (!window.nativeGUI && window.NativeGUI) window.nativeGUI = new window.NativeGUI();
	return remoteGUIOpt && dtFrame.remoteGUI ? dtFrame.remoteGUI.init.bind(dtFrame.remoteGUI) : window.nativeGUI.init.bind(window.nativeGUI);
	*/
	function activateGUI(activeFrame, className, instanceName, opt) {
		GUI.log("A1");
		var activeGUI = activeFrame[instanceName];
		var classInstance = activeFrame[className];
		if (!activeGUI) { // && classInstance // 17.09.2009 Ossig Has to exist.
			GUI.log("A2");
			var activeGUI = new classInstance(opt);
			GUI.log("A3");
			activeFrame[instanceName] = activeGUI;
			GUI.log("A4");
		}
		return activeGUI.init.bind(activeGUI);
	}
	return remoteGUIOpt && dtFrame.RemoteGUI ? activateGUI(dtFrame, "RemoteGUI", "remoteGUI", remoteGUIOpt) : activateGUI(window, "NativeGUI", "nativeGUI");
}

// 04.02.2010 Ossig Available in EVERY window.
var GUI = {
	log: function() { // 10.09.2009 Ossig Notfalls auf empty function legen.
		var console = window.console;
		if (!console || !Object.isFunction(console.log)) return; // 15.10.2009 Ossig IE8: console.log exists but is not function.
		console.log.apply(console, arguments);
	},
	GESymbolLink: Class.create({
		initialize: function(opt) {
			opt = Object.extend({ bgSymbol: true }, opt || {}); // symbolClassName, value, classArr, bgSymbol
			var classArrTemplate = ["ge-button-symbol", "ge-button-symbol-left"];
			var classArr = opt.classArr ? classArrTemplate.concat(opt.classArr).uniq().compact() : classArrTemplate; // 16.12.2009 Ossig Original class array may be Scalar or Array.
			var element = new Element("a", { href: "#", "class": classArr.join(" ") });
			if (opt.symbolClassName) {
				if (opt.bgSymbol) element.insert(new Element("span", { "class": "ge-symbol" }));
				element.insert(new Element("span", { "class": "ge-symbol " + opt.symbolClassName }));
			}
			element.insert(new Element("span", { "class": "ge-text" }).insert(opt.value));
			this.element = element;
		}
	}),
	sumSize: function(sizeArr) {
		function add(sum, value) {
			return sum + parseInt(value);
		}
		return {
			width: sizeArr.pluck("width").inject(0, add),
			height: sizeArr.pluck("height").inject(0, add)
		};
	},
	bodyVisible: function() {
		// return true;
		if (window.closed || !window.$body) return false;
		var innerSize = window.$body.getInnerSize();
		return innerSize.width != 0 || innerSize.height != 0;
	}
};

/* 28.03.2010 Ossig prototype-ui CSS.addRule */
if (!window.CSS) window.CSS = {};
if (!Object.isFunction(Element.appendText))
	Element.addMethods({
		appendText: function(element, text) {
			element = $(element);
			element.appendChild(document.createTextNode(String.interpret(text)));
			return element;
		}
	});
if (!CSS.addRule) {
	/*
	document.whenReady(function() {
		window.$head = $(document.getElementsByTagName('head')[0]);
	});
	*/
	Object.extend(CSS, { // 
		addRule: function(css) {
			var style = new Element('style', { type: 'text/css', media: 'screen' });
			$head.insert(style);
			if (style.styleSheet) style.styleSheet.cssText = css;
			else style.appendText(css);
			return style;
		}
	});
}
Element.addMethods({
	_getFrameSize: function(element) {
		return (
			[element.getMarginDimensions()
			, element.getBorderDimensions()
			, element.getPaddingDimensions()
			]);
	},
	// setBounds
	setInnerWidth: function(element, innerWidth) {
		element.style.width = parseInt(innerWidth) + "px"; // element.clientSize;
	},
	setInnerHeight: function(element, innerHeight) {
		element.style.height = parseInt(innerHeight) + "px"; // element.clientHeight;
	},
	/*
	removeInnerSize: function(element) {
	element.style.width = undefined;
	element.style.height = undefined;
	element.style.removeAttribute("width",false);
	},
	*/
	setInnerSize: function(element, innerSize) {
		element.setInnerWidth(innerSize.width);
		element.setInnerHeight(innerSize.height);
		// GUI.log(element.id, "setInnerSize", innerWidth, innerHeight);
	},
	// setBounds
	setOuterSize: function(element, outerSize) {
		var sizeInv = GUI.sumSize([{ width: -outerSize.width, height: -outerSize.height}].concat(element._getFrameSize()));
		element.setInnerSize({ width: -sizeInv.width, height: -sizeInv.height });
	},
	// getBounds
	getInnerSize: function(element) {
		return { width: element.clientWidth, height: element.clientHeight };
	},
	getOuterSize: function(element) {
		return element.getDimensions();
	},
	removeStyle: function(element, style) {
		styleHash = $H();
		styleHash.set(style, "");
		return element.setStyle(styleHash.toObject());
	}
});

var CountingObserver = Class.create(PeriodicalExecuter, {
	initialize: function($super, prefix, callback, frequency, pingCounter) {
		this.prefix = prefix;
		this.outerCallback=callback;
		this.pingCounter = pingCounter ? pingCounter : 0;
		$super(this.innerCallback, frequency);
	},
	innerCallback: function(executer) {
		if (this.outerCallback()) {
			executer.stop();
			GUI.log(this.prefix, "pong", this.pingCounter);
			return;
		}
		GUI.log(this.prefix, "ping", this.pingCounter++);
	}
	
});

var CountingObserver0 = Class.create(CountingObserver, {
	initialize: function($super, prefix, callback, frequency) {
		var pingCounter = 0;
		if (callback()) {
			GUI.log(prefix, "pong", pingCounter);
			return;
		}
		GUI.log(prefix, "ping", pingCounter++);
		$super(prefix, callback, frequency, pingCounter);
	}
});

var GEHash = Class.create(Hash, {
	diff: function(compareHash) {
		compareHash = $H(compareHash);
		var diffHash = this.inject($H(), function(diffHash, pair) {
			var compareValue = compareHash.get(pair.key);
			if (pair.value != compareValue)
				diffHash.set(pair.key, compareValue);
			return diffHash;
		});
		/*
		if (diffHash.size() > 0) {
			GUI.log(diffHash.inspect())
		}
		*/
		return diffHash.size() > 0 ? diffHash.toObject() : undefined;
	}
});

Object.extend(GUI, {
	/*
	Shadow_JS: Class.create(UI.Shadow, { // 11.04.2010 Ossig Assumes prototype-ui to be included.
	initialize: function($super, element, tableElement) {
	var opt = { theme: "mac_shadow", withIFrameShim: false };
	element.style.left = 0;
	element.style.top = 0;
	new window.PeriodicalExecuter(function(executer) {
	if (window.closed) {
	executer.stop();
	return;
	}
	if (GUI.bodyVisible()) {
	executer.stop();
	this.log("pong, element=", element);
	$super(element, opt);
	this.init(element, tableElement);
	return;
	}
	this.log("ping");
	} .bind(this), 1);
	},
	setShadowSize: function() {
	var dimensions = this.element.getDimensions();
	this.setSize(dimensions.width, dimensions.height);
	}
	}),
	*/
	Shadow_JS: Class.create(UI.Shadow, { // 11.04.2010 Ossig Assumes prototype-ui to be included.
		initialize: function($super, element, tableElement) {
			var opt = { theme: "mac_shadow", withIFrameShim: false };
			element.style.left = 0;
			element.style.top = 0;
			$super(element, opt);
			this.init(element, tableElement);
			/*
			new window.PeriodicalExecuter(function(executer) {
			if (window.closed) {
			executer.stop();
			return;
			}
			if (GUI.bodyVisible()) {
			executer.stop();
			this.log("pong, element=", element);
			$super(element, opt);
			this.init(element, tableElement);
			return;
			}
			this.log("ping");
			} .bind(this), 1);
			*/
		},
		setShadowSize: function() {
			var dimensions = this.element.getDimensions();
			this.setSize(dimensions.width, dimensions.height);
		}
	}),
	Shadow_CSS: Class.create({ // 11.04.2010 Ossig Assumes FF 3.6
		initialize: function(element, opt) {
			this.opt = Object.extend({ displayStyle: "block" }, opt || {});
			this.element = element;
			element.style.display = "none";
			return;
			this.init(element, tableElement);
			new window.PeriodicalExecuter(function(executer) {
				if (window.closed) executer.stop();
				if (GUI.bodyVisible()) this.onResizeElement();
			} .bind(this), 2);
		},
		setShadowSize: function() {
		},
		show: function() {
			var element = this.element;
			if (!element) return;
			// element.style.display = "table-cell";
			// element.style.display = "table";
			element.style.display = this.opt.displayStyle;
		},
		hide: function() {
			var element = this.element;
			if (!element) return;
			element.style.display = "none";
		}
	}),
	FrameSize: Class.create({
		/*
		opt={frameClass, frameMinSize, frameMaxSize, contentWindow, contentOffsetSize}
		*/
		initialize: function(frameElementArr, opt) {
			this.opt = Object.extend({ contentWindow: window, contentOffsetSize: {}, contentMinSize: {} }, opt || {});
			this.frameElementArr = frameElementArr ? frameElementArr.compact() : []; // frameWindow=frameElement.ownerDocument.parentWindow;
		},
		getDeltaSize: function(minSize) {
			var actualSize = this.getActualContentSize();
			var targetSize = this.getTargetContentSize();
			if (minSize) {
				if (targetSize.width < minSize.width) targetSize.width = minSize.width;
				if (targetSize.height < minSize.height) targetSize.height = minSize.height;
			}
			var deltaSize = GUI.sumSize([targetSize, { width: -actualSize.width, height: -actualSize.height}]);
			return deltaSize;
		},
		getActualContentSize: function() {
			// return this.opt.contentWindow.$body.getInnerSize();
			var documentElement = this.opt.contentWindow.document.documentElement;
			return { width: documentElement.clientWidth, height: documentElement.clientHeight };
		},
		getTargetContentSize: function() {
			// return GUI.sumSize([this.opt.contentOffsetSize, this.opt.contentWindow.$body.getOuterSize()]);
			var documentElement = this.opt.contentWindow.document.documentElement;
			return GUI.sumSize([this.opt.contentOffsetSize, { width: documentElement.offsetWidth, height: documentElement.offsetHeight}]);
		},
		adjustHeight: function() {
			var deltaHeight = this.getDeltaSize(this.opt.contentMinSize).height;
			GUI.log("FrameSize: deltaHeight=", deltaHeight);
			var frameElementArr = this.frameElementArr;
			if (!deltaHeight || !frameElementArr) return;
			frameElementArr.each(function(frameElement) {
				if (!frameElement) return;
				var innerHeight = frameElement.getInnerSize().height;
				var innerHeight2 = innerHeight + deltaHeight;
				GUI.log("FrameSize:", frameElement, " height:", innerHeight, " ==>", innerHeight2);
				frameElement.setInnerHeight(innerHeight2);
			});
		}
	}),
	adjustCMSFrameSize: function(contentWindow, frameElement) {
		var dtFrame = getDTFrame();
		if (dtFrame.GUI.options.cmsMode)
			dtFrame.CMS.adjustFrameSize(contentWindow, frameElement);
	}
});
[GUI.Shadow_JS, GUI.Shadow_CSS].invoke("addMethods", {
	init: function(element, tableElement) {
		this.windowInnerSize = new GEHash(window.$body.getInnerSize());
		this.viewportSize = new GEHash(document.viewport.getDimensions());
		this.windowPageSize = new GEHash({ width: document.width, height: document.height });

		var onResizeElementEvent = this.onResizeElement.bindAsEventListener(this);
		Element.observe(window, "resize", onResizeElementEvent);
		/*
		var elementArr = element.select("table");
		elementArr.concat(window, element).each(function(element) {
		Element.observe(element, "resize", onResizeElementEvent);
		});
		*/
		this._onResizeElementEvent = this._onResizeElement.bind(this);
		Element.observe(window, "scroll", this.log.bind(this, "scroll"));
		Element.observe(window, "click", this.log.bind(this, "click"));
		this.tableElementArr = element.select("table");
		this.tableWidth = this.computeTableWidth();
		this.tableElement = tableElement;
	},
	onResizeElement: function(event, unblock) {
		this._onResizeElementEvent.defer(event, unblock);
	},
	_onResizeElement_Version1: function(event, unblock) {
		if (!unblock) {
			this.log("blocked", this.blocked);
			if (this.blocked) return;
			if (!GUI.bodyVisible()) return;

			this.log({ scrollWidth: $body.scrollWidth, scrollHeight: $body.scrollHeight });

			var windowInnerSize = window.$body.getInnerSize();
			this.log("window size diff:", this.windowInnerSize.toObject(), windowInnerSize);
			// if (!this.windowInnerSize.diff(windowInnerSize)) return;
			// this.log("window size diff acknowledged");
			this.windowInnerSize = new GEHash(windowInnerSize);

			var viewportSize = document.viewport.getDimensions();
			this.log("viewport size diff:", this.viewportSize.toObject(), viewportSize);
			// if (!this.viewportSize.diff(viewportSize)) return;
			// this.log("viewport size diff acknowledged");
			this.viewportSize = new GEHash(viewportSize);

			var windowPageSize = { width: document.width, height: document.height };
			// var windowPageSize = frameElement.getDimensions();
			this.log("page size diff:", this.windowPageSize.toObject(), windowPageSize);
			if (!this.windowPageSize.diff(windowPageSize)) return;
			this.log("page size diff acknowledged");
			this.windowPageSize = new GEHash(windowPageSize);
		} else
			this.blocked = false;
		var element = this.element;
		if (element.style.width && !unblock) {
			this.blocked = true;
			// element.style.width = nothing;
			// element.style.removeAttribute("width");
			element.style.width = "";
			this._onResizeElementEvent.delay(1, undefined, true);
		}
		/*
		var dimensions = element.getDimensions();
		this.setSize(dimensions.width, dimensions.height);
		*/

		var maxWidth = this.computeTableWidth();
		this.tableWidth = maxWidth;
		var innerWidth = element.getInnerSize().width;
		this.log("width=", innerWidth, ", maxWidth=", maxWidth);
		if (innerWidth < maxWidth) element.setInnerWidth(maxWidth);
		this.setShadowSize();
	},
	_onResizeElement: function(event, unblock) {
		if (!unblock) {
			this.log("blocked", this.blocked);
			if (this.blocked) return;
			if (!GUI.bodyVisible()) return;

			this.log({ scrollWidth: $body.scrollWidth, scrollHeight: $body.scrollHeight });

			var windowInnerSize = window.$body.getInnerSize();
			this.log("window size diff:", this.windowInnerSize.toObject(), windowInnerSize);
			// if (!this.windowInnerSize.diff(windowInnerSize)) return;
			// this.log("window size diff acknowledged");
			this.windowInnerSize = new GEHash(windowInnerSize);

			var viewportSize = document.viewport.getDimensions();
			this.log("viewport size diff:", this.viewportSize.toObject(), viewportSize);
			// if (!this.viewportSize.diff(viewportSize)) return;
			// this.log("viewport size diff acknowledged");
			this.viewportSize = new GEHash(viewportSize);

			var windowPageSize = { width: document.width, height: document.height };
			// var windowPageSize = frameElement.getDimensions();
			this.log("page size diff:", this.windowPageSize.toObject(), windowPageSize);
			// if (!this.windowPageSize.diff(windowPageSize)) return;
			// this.log("page size diff acknowledged");
			this.windowPageSize = new GEHash(windowPageSize);
		} else
			this.blocked = false;
		var element = this.element;
		if (element.style.width && !unblock) {
			this.blocked = true;
			// element.style.width = nothing;
			// element.style.removeAttribute("width");
			element.style.width = "";
			this._onResizeElementEvent.delay(1, undefined, true);
		}
		/*
		var dimensions = element.getDimensions();
		this.setSize(dimensions.width, dimensions.height);
		*/

		var maxWidth = this.computeTableWidth();
		this.tableWidth = maxWidth;
		var innerWidth = element.getInnerSize().width;
		this.log("width=", innerWidth, ", maxWidth=", maxWidth);
		if (innerWidth < maxWidth) element.setInnerWidth(maxWidth);
		this.setShadowSize();
	}, /*
	_onResizeElement: function(event, unblock) {
	}, */
	computeTableWidth: function() {
		var maxWidth = this.tableElementArr.inject(0, function(maxWidth, element) {
			var dimensions = element.getDimensions();
			var width = dimensions.width;
			if (width > maxWidth) maxWidth = width;
			return maxWidth;
		});
		return maxWidth;
	},
	log: function(arg) {
		GUI.log.apply(GUI, ["_Shadow"].concat($A(arguments))); // 20.09.2009 Ossig Übergibt Argumente.
	}
});
