if (typeof Prototype == 'undefined' || !(Prototype.Version.match("1.6") || Prototype.Version.match("1.7")) )
	throw ("GlobalEagle-GUI library requires Prototype library >= 1.6.0");

Object.extend(GUI, {
	GESymbolButton: Class.create({
		initialize: function(symbolClassName, value, classArr) {
			var classArrTemplate = ["ui-state-default", "ui-corner-all", "ge-button", "ge-button-symbol-left"];
			classArr = classArr ? classArrTemplate.concat(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(" ") });
			// .insert(new Element("span", { "class": "ge-symbol" }))
			if (symbolClassName) element.insert(new Element("span", { "class": "ge-symbol " + symbolClassName }));
			element.insert(new Element("span", { "class": "ge-text" }).insert(value));
			this.element = element;
		}
	}),
	WindowFootbar: Class.create({
		initialize: function(guiWindow, opt) {
			var guiWindow_w = guiWindow.element.down(".w");
			if (!guiWindow_w) throw ("WindowFootbar");
			this._buttonArr = []; // footbarButton={symbol,name,className,callback,element}
			var footbarElement = guiWindow_w.down(".ge-footbar");
			var reconnecting = footbarElement;
			if (!footbarElement) {
				// footbarElement = new Element("div", { "class": "ge-footbar ui-corner-all" }); // 20.12.2009 Ossig ui-corner-all
				footbarElement = new Element("div", { "class": "ge-footbar" }); // 20.12.2009 Ossig ui-corner-all
				if (guiWindow.embedded) footbarElement.addClassName("ui-corner-bottom"); // 20.12.2009 Ossig
				// var footbarLine = new Element("p").insert("this is a footbarline")
				// footbarElement.insert(footbarLine).insert(footbarLine.clone(true)).insert(footbarLine.clone(true));
				/*
				footbarElement.insert(new GUI.GESymbolButton("ge-symbol-eagle", "Maske", "ge-state-disabled").element); // 14.12.2009 Ossig First element in case of overflow.
				footbarElement.insert(new GUI.GESymbolButton("ge-symbol-new", "Neu", "ge-state-disabled").element);
				footbarElement.insert(new GUI.GESymbolButton("ge-symbol-save", "Speichern", "ge-state-disabled").element);
				footbarElement.insert(new GUI.GESymbolButton("ge-symbol-print", "Drucken", "ge-state-disabled").element);
				footbarElement.insert(new GUI.GESymbolButton("ge-symbol-print", "Speichern + Drucken", "ge-state-disabled").element);
				footbarElement.insert(new GUI.GESymbolButton("ge-symbol-find", "Suchen", "ge-state-disabled").element);
				footbarElement.insert(new GUI.GESymbolButton("ge-symbol-edit", "Bearbeiten", "ge-state-disabled").element);
				*/
				guiWindow_w.insert(footbarElement);
			}
			this.element = footbarElement;
			if (!reconnecting) {
				// this.add({ symbol: "ge-symbol-eagle", className: "ge-state-disabled" }); // 18.12.2009 Ossig To be killed with first clear.
				// <a class="ge-ibutton-big ui-state-disabled ge-ibutton-big-eagle" href="#"/>
				/*
				var buttonElement = new Element("a", { "class": "ge-ibutton-big ui-state-disabled ge-ibutton-big-eagle", href: "#" });
				this._buttonArr.push({ element: buttonElement });
				// this.element.insert(buttonElement).insert("<br>").insert(buttonElement.clone(true));
				this.element.insert(buttonElement);
				*/
				/*
				function insert(symbol, name) {
				that.add({ symbol: symbol, className: "ge-state-disabled", name: name });
				}
				var that = this;
				insert("ge-symbol-eagle", "Maske");
				insert("ge-symbol-new", "Neu");
				insert("ge-symbol-save", "Speichern");
				insert("ge-symbol-print", "Drucken");
				insert("ge-symbol-print", "Speichern + Drucken");
				insert("ge-symbol-find", "Suchen");
				insert("ge-symbol-edit", "Bearbeiten");
				*/
			}
		},
		clear: function() {
			var buttonArr = this._buttonArr;
			buttonArr.each(function(footbarButton) {
				var buttonElement = footbarButton.element;
				if (!buttonElement) return;
				var callback = footbarButton.callback;
				if (callback) buttonElement.stopObserving("click", callback);
				buttonElement.remove();
			});
			buttonArr.clear();
			/*
			var footbarElement = this.element;
			footbarElement.select(".ge-button").invoke("remove");
			*/
			if (this._contextMenu) {
				this._contextMenu.dispose();
				this._contextMenu = undefined;
			}
		},
		resetState: function() {
			var buttonArr = this._buttonArr;
			buttonArr.pluck("element").compact().invoke("removeClassName", "ui-state-active");
		},
		add: function(footbarButton) {
			if (!footbarButton) return {};
			function _add(footbarButton) {
				var classArr = footbarButton.className;
				var callback = footbarButton.callback;
				if (!callback) classArr = classArr ? ["ge-state-disabled"].concat(classArr) : "ge-state-disabled"; // 08.01.2010 Ossig context button.
				var buttonElement = new GUI.GESymbolButton(footbarButton.symbol, footbarButton.name, classArr).element;
				if (callback) buttonElement.observe("click", callback);
				footbarElement.insert(buttonElement);

				var footbarButton = Object.extend(Object.clone(footbarButton), { element: buttonElement });
				buttonArr.push(footbarButton);
				return footbarButton;
			}
			var footbarElement = this.element;
			var buttonArr = this._buttonArr;
			if (Object.isArray(footbarButton))
				return footbarButton.collect(function(footbarButton) { _add(footbarButton) });
			else
				return _add(footbarButton);
		},
		init: function(contextButton, menuButtonArr, buttonArr) {
			this.clear();
			contextButtonElement = this.add(contextButton).element;
			this.add(buttonArr);
			/* 18.12.2009 Ossig Passive strategy: Generate and by on demand to be killed again by init/clear.
			if (!footbarButton || !footbarButton.length) { // 18.12.2009 Ossig At least one button visible to occupy/populate footbar.
			this.element.insert(new GUI.GESymbolButton("ge-symbol-eagle", "---", "ge-state-disabled").element); 18.12.2009 Ossig Not killed that way.
			}
			*/
			if (contextButtonElement) {
				if (menuButtonArr && menuButtonArr.length) {
					/*
					var contextMenu = new GUI.ContextMenuDyn(contextButtonElement.identify(), [
					{ symbol: "ge-symbol-print", name: "Print *", callback: alert.bind(window, "action print *") }
					]);
					*/
					var contextMenu = new GUI.ContextMenuDyn(contextButtonElement.identify(), menuButtonArr);
					this._contextMenu = contextMenu;
					contextButtonElement.removeClassName("ge-state-disabled");
				}
			}
		}
	}),
	WCoord: Class.create({
		initialize: function(left, top, step) {
			this.left = left;
			this.top = top;
			this.step = step;
		}
			, inc: function() {
				this.left += this.step;
				this.top += this.step;
			}
			, dec: function() {
				this.left -= this.step;
				this.top -= this.step;
			}
	}),
	WindowTest: Class.create(UI.Window, {
		initialize: function($super, opt) {
			$super();
			this.observe("move:started", this.onMoveStarted);
			this.observe("move:ended", this.onMoveEnded);
		},
		onMoveStarted: function() {
			GUI.log("move:started");
			this.windowManager.startModalSession(this);
			this.modalSession = true;
		},
		onMoveEnded: function() {
			this.windowManager.endModalSession(this);
			this.modalSession = false;
			GUI.log("move:ended");
		}
		/*
		if (modal) {
		this.windowManager.startModalSession(this);
		this.modalSession = true;
		}
		if (this.modalSession) {
		this.windowManager.endModalSession(this);
		this.modalSession = false;
		}
		*/
	}),
	URLWindowTest: Class.create(UI.URLWindow, {
		initialize: function($super, url, opt) {
			/*
			var winOpt = {
			width: 600,
			height: 400,
			shadow: false,
			// theme: "mac_os_x", // 08.09.2009 Ossig Not compatible to wired mode.
			theme: "gewindow",
			close: "destroy",
			// windowManager: GUI.wmDesktop,
			activeOnClick: false,
			wired: true
			};
			*/
			var winOpt = {
				// windowManager: GUI.wmDesktop; // windowManager: GUI.defaultWM?GUI.defaultWM:UI.defaultWM
				windowManager: GUI.metaWM // windowManager: GUI.defaultWM?GUI.defaultWM:UI.defaultWM
			};
			if (opt) Object.extend(winOpt, opt);
			winOpt.url = url || 'EmptyURLWindow.html';
			$super(winOpt);
			this.observe("move:started", this.onMoveStarted);
			this.observe("move:ended", this.onMoveEnded);
		},
		onMoveStarted: function() {
			GUI.log("move:started");
			this.windowManager.startModalSession(this);
			this.modalSession = true;
		},
		onMoveEnded: function() {
			this.windowManager.endModalSession(this);
			this.modalSession = false;
			GUI.log("move:ended");
		}
	}),
	URLWindow: Class.create(UI.URLWindow, {
		initialize: function($super, url, _opt) {
			this._contentFrameHash = $H();
			var workLevel = _opt ? _opt.workLevel : undefined;
			var wm = (_opt && _opt.wm) ? _opt.wm : GUI.metaWM.getWM(workLevel);
			if (_opt && _opt.cleanupBefore) {
				wm.cleanup();
			}
			var opt = {
				width: 600,
				height: 400,
				shadow: false,
				// theme: "mac_os_x", // 08.09.2009 Ossig Not compatible to wired mode.
				theme: "gewindow",
				close: "destroy",
				windowManager: wm,
				activeOnClick: false,
				wired: true,
				embedded: false, // 08.11.2009 Ossig GE extension.
				geWindow: undefined // 08.11.2009 Ossig GE extension.
			};
			if (_opt) Object.extend(opt, _opt);

			var embedded = opt.embedded ? this : undefined;
			this.embedded = embedded;
			// this.dynamic = opt.dynamic ? this : undefined;
			if (embedded) {
				Object.extend(opt, { close: false, minimize: false, maximize: false, resizable: false, draggable: false });
				// if (url) url += "&ge-embedded=1"; // 20.11.2009 Ossig Assumed ModuleName?...
			}
			this._onMouseDownEvent = this._onMouseDown.bind(this); // 09.09.2009 Ossig Is being used by $super (contentWindow frame initialisation)
			GUI.log("this._onMouseDownEvent bind, this._onMouseDownEvent=", this._onMouseDownEvent);
			this.geWindow = opt.geWindow;
			this.footbar = opt.footbar; // 18.12.2009 Ossig see createIFrame
			this.registerContentFrameEvent = this.registerContentFrame.bind(this);

			opt.url = url || 'EmptyURLWindow.html';


			// GUI.metaWM.selectTab(workLevelIndex); // 09.11.2009 Ossig Make it visible to get correct sizes. ==> Not necessary. Do it when selected.
			/*
			var iArea = element.getFrameSize({ width: -innerSizeRaw.width, height: -innerSizeRaw.height }); // 11.11.2009 Ossig invers frame reduced client area.
			var innerSize = { width: -iArea.width - 1, height: -iArea.height - 1 };
			*/
			/*
			var innerSizeRaw = opt.windowManager.viewport.getDimensions();
			var innerSize = { width: innerSizeRaw.width - 1, height: innerSizeRaw.height - 1 }; // 11.11.2009 Ossig wm container size.
			*/
			var viewport = opt.windowManager.viewport;
			var innerSizeRaw = { width: viewport.clientWidth, height: viewport.clientHeight };
			var innerSize = { width: innerSizeRaw.width - 1, height: innerSizeRaw.height - 1 }; // 11.11.2009 Ossig wm container size.

			// 11.11.2009 Ossig opt: client side without frame.
			if (embedded) {
				opt.left = 0;
				opt.top = 0;
				opt.width = innerSize.width;
				opt.height = innerSize.height;
			} else if (GUI.options.workTabs) {
				if (opt.left + opt.width > innerSize.width) {
					var left = innerSize.width - opt.width;
					opt.left = left < 0 ? 0 : left;
					if (left < 0) opt.width = innerSize.width
				}
				if (opt.top + opt.height > innerSize.height) {
					var top = innerSize.height - opt.height;
					opt.top = top < 0 ? 0 : top;
					if (top < 0) opt.height = innerSize.height;
				}
			} else {
				if (opt.left + opt.width > innerSize.width)
					opt.width = innerSize.width - opt.left;
				if (opt.top + opt.height > innerSize.height)
					opt.height = innerSize.height - opt.top;
			}

			GUI.metaWM.selectWorkFrameTab(wm.container); // 10.12.2009 Ossig Make WorkFrameTab visible.
			$super(opt); // 10.12.2009 Ossig Make visible for initial computeBorderSize. // 11.11.2009 Ossig Inner size is set?!?
			/* Does not work
			if (GUI.options.cmsMode) {
			var progressElement = $$(".cms-progress").first();
			// 14.06.2010 Ossig Rerender.
			// progressElement.hide();
			// progressElement.show();
			if (wm.windows().length) progressElement.setStyle({ zIndex: wm.getLastZIndex() });
			}
			*/
			var iframeElement = this.contentIFrame();
			// if (embedded) iframeElement.addClassName("ge-embedded");
			iframeElement.guiDataPort = Object.extend(iframeElement.guiDataPort || {}, { embedded: embedded });

			// this.setSize(opt.width, opt.height); // 11.11.2009 Ossig Set outer size ==> too big. Shadow may be the reason.

			// this.visible;
			/*
			this._onFocusedEvent = this._onFocused.bind(this)
			this.observe("focused", this._onFocusedEvent);
			this._onBlurredEvent = this._onBlurred.bind(this)
			this.observe("blurred", this._onBlurredEvent);
			this._onHidingEvent = this._onHiding.bind(this)
			this.observe("hiding", this._onHidingEvent);
			// this._onUnloadEvent = this._onUnload.bind(this);
			// Event.observe(this.element, "unload", this._onUnloadEvent);
			this._onMouseOverEvent = this._onMouseOver.bind(this);
			Event.observe(this.element, "mouseover", this._onMouseOverEvent);
			*/

			/* 20.09.2009 Ossig Does not work in wired mode.
			this.observe("resize:started", this.onResizeStarted);
			this.observe("resize:ended", this.onResizeEnded);
			this.observe("move:started", this.onResizeStarted);
			this.observe("move:ended", this.onResizeEnded);
			this.observe("mstart", this.onResizeStarted);
			this.observe("mend", this.onResizeEnded);
			Event.observe(this.element, "mstart", this.onResizeStarted.bind(this));
			Event.observe(this.element, "mend", this.onResizeEnded.bind(this));
			this.observe("shown", this.onResizeStarted);
			Event.observe(this.element, "ge:mstart", this.onResizeStarted.bind(this));
			Event.observe(this.element, "ge:mend", this.onResizeEnded.bind(this));
			*/

			// this._onShownEvent = this._onShown.bind(this);
			this.observe("shown", this._onShown);
			this.observe("focused", this._onFocused);
			this.observe("blurred", this._onBlurred);
			// this.observe("hiding", this._onBeforeHiding);
			Event.observe(this.element, "mouseover", this._onMouseOver.bind(this));
			// Event.observe(this.element, "click", this._onClick.bind(this));
			// Event.observe(this.element, "mousedown", this._onMouseDownEvent); // 09.09.2009 Ossig opt.activeOnClick
			/*
			if (embedded) {
			// this.element.addClassName("ge-embedded"); // 11.11.2009 Ossig Too late, window size already computed. Overriding getTheme.
			this.setSize(innerSize.width, innerSize.height); // this.setSize.bind(this, area.width, area.height).defer();
			}
			*/
		} /*,
			stopObserving: function(eventName, handler) {
				this.element.stopObserving('window:' + eventName, handler);
				return this;
			},
			observe: function(eventName, handler) {
				this.element.observe('window:' + eventName, handler.bind(this));
				return this;
			},
			setZIndex: function($super, zIndex) {
				var zIndex = $super(zIndex).lastZIndex;
				var contentWindow = this.contentIFrame().contentWindow;
				if (!contentWindow) return this;
				[contentWindow].concat($A(contentWindow.frames)).each(function(frame) {
					var element = frame.document.body;
					if (!element || !element.style) return;
					element.style.zIndex = zIndex++;
				});
				this.lastZIndex = zIndex;
				return this;
			}*/,
		createIFrame: function($super) { // 18.12.2009 Frame available, Content not yet created.
			if (this.footbar) {
				var footbar = new GUI.WindowFootbar(this); // Available to contentWindow.
				this.footbar = footbar;
				if (this.geWindow) this.geWindow.footbar = footbar; // 18.12.2009 Ossig Has to happen before contentWindow is opened.
			}
			$super();
		},
		contentIFrame: function() {
			// return this.iframe;
			return this.contentframe; // 06.10.2009 Ossig StarPeak prototype-ui adapter.
		},
		_getName: function() {
			return "GUI.URLWindow " + this.windowManager.container.id + "." + (this.geWindow ? this.geWindow.name : "(GEWindow)");
		},
		log: function(arg) {
			// GUI.log.call(GUI, [this._getName()].concat($A(arguments))); // 20.09.2009 Ossig Übergibt ein array Argument.
			GUI.log.apply(GUI, [this._getName()].concat($A(arguments))); // 20.09.2009 Ossig Übergibt Argumente.
		},
		startResize: function($super, handle) {
			$super(handle);
			this.onResizeStarted();
		},
		endResize: function($super) {
			this.onResizeEnded();
			$super();
		},
		startMove: function($super) {
			$super();
			// this.element.fire("mstart");
			// Element.fire(this.element, "ge:mstart");
			// this.fire("mstart");
			this.onMoveStarted();
		},
		endMove: function($super) {
			this.onMoveEnded();
			// this.fire("mend");
			// Element.fire(this.element, "ge:mend");
			// this.element.fire("mend");
			$super();
		},
		getTheme: function($super) { // 12.11.2009 Ossig Called mutliple times.
			// return this.wiredDrag ? "": $super(); // 20.09.2009 Ossig Don't find CSS style to get no opacity in this.windowManager.startModalSession.
			// return this.wiredDrag ? $super() + "_wired" : $super(); // 20.09.2009 Ossig CSS gewindow_wired_overlay.
			// var preFix = this.embedded && !this.element.hasClassName("ge-embedded") ? "ge-embedded " : ""; // this.element not defined.

			// var preFix = this.embedded && !this.element ? "ge-embedded " : ""; // 12.11.2009 Ossig !this.element when initializing.
			var preFix;
			if (this.element)
				preFix = "";
			else {
				var preFixArr = [];
				if (this.embedded) {
					preFixArr.push("ge-embedded");
					preFixArr.push("ui-corner-bottom");
				}
				if (this.footbar) preFixArr.push("ge-footbar");
				// preFixArr.push(this.dynamic?"ge-dynamic":"ge-static");
				if (preFixArr.length > 0) preFixArr.push("");
				preFix = preFixArr.join(" ");
			}
			var postFix = this.wiredDrag ? "_wired" : "";
			return preFix + $super() + postFix;
		},
		startWiredDrag: function() {
			// 20.09.2009 Moving already is dragging.
			// this.windowManager.container.insert(this.windowManager.dragOverlay.setStyle({ zIndex: this.windowManager.getLastZIndex() }));
			// return;

			if (this.wiredDrag || this.modalSession) return; // 20.09.2009 Ossig Don't allow modalSession logic mixed up.
			this.wiredDrag = true;
			this.windowManager.startModalSession(this);
			this.modalSession = true;
		},
		endWiredDrag: function() {
			// 20.09.2009 Moving already is dragging.
			// this.windowManager.dragOverlay.remove();
			// return;

			if (!this.wiredDrag) return;
			this.wiredDrag = false;
			if (!this.modalSession) return;
			this.windowManager.endModalSession(this);
			this.modalSession = false;
		},
		onMoveStarted: function() {
			this.log("onMoveStarted");
			this.startWiredDrag();
		},
		onMoveEnded: function() {
			this.log("onMoveEnded");
			this.endWiredDrag();
		},
		onResizeStarted: function() {
			this.log("onResizeStarted");
			this.startWiredDrag();
		},
		onResizeEnded: function() {
			this.log("onResizeEnded");
			this.endWiredDrag();
		},
		_showFileList: function(showState) {
			var contentWindow = this.contentIFrame().contentWindow;
			if (!contentWindow) return;
			var moveDataEditFrame = contentWindow.frames[1];
			if (!moveDataEditFrame || moveDataEditFrame.closed || !moveDataEditFrame.document.loaded) return;
			var body = $(moveDataEditFrame.document.body);
			if (!body) return; // 09.09.2009 Ossig Not yet initialized.
			var fileListArr = body.select('input[getype="filelist"]');
			this.log("getype:", fileListArr);
			// input[getype="filelist"] ==> elementarray ==> id + "_applet".up.setVisible();
			// focused
			// blurred
			var appletParentArr = fileListArr.collect(function(fileList) {
				return moveDataEditFrame.$(fileList.id + "_applet").up(); // 06.10.2009 Ossig Works using id
				// return fileList.next("table").select("applet").invoke("up")[0]; // 06.10.2009 Ossig Works using tagname
				// return fileList.next("table"); // 06.10.2009 Ossig ShowState target.
				// return fileList.next("table").down("table");
				// return fileList.next("table").down("tbody"); // 06.10.2009 Ossig Funktioniert bei Herrn Raschke FF3.0
				// return fileList.next("table").select("applet")[0]; // 06.10.2009 Ossig Will not become unvisible. Reset ZOrder of applet after moving urlWindow in wired mode.
			});
			var that = this;
			// 06.10.2009 Ossig Against switching applet too fast on and off.
			(function(urlWindow, appletParentArr, showState) {
				var showAction = showState ? "show" : "hide";
				that.log(showAction, "try delayed:", appletParentArr);
				if (that._destroyEvent) return;
				if (showState ^ urlWindow.focused) return;
				that.log(showAction, ":", appletParentArr);
				appletParentArr.invoke(showAction);
			}).delay(showState ? 0 : 1, this, appletParentArr, showState);
		},
		_onFocused: function() {
			/*
			// Show the overlay to catch events
			if (this.options.activeOnClick)
			this.overlay.setStyle({ zIndex: this.lastZIndex + 1 }).show();
			*/
			GUI.log(this.geWindow ? this.geWindow.name : "(no GEWindow)", " focused");
			this._showFileList(true);
			/* 12.10.2009 Ossig Be careful! (w==w.frames) when no frameset.
			var w = this.contentIFrame() ? this.contentIFrame().contentWindow : undefined;
			if (!w) return;
			[w].concat($A(w.frames)).each(function(frame) {
			frame.Element.fire(frame, "gui:test");
			});
			*/
		},
		_onBlurred: function() {
			GUI.log(this.geWindow ? this.geWindow.name : "(no GEWindow)", " blurred");
			this._showFileList(false);
		} /* ,
		hide: function($super) {
			this._onBeforeHiding();
		} */,
		_onBeforeDestroying: function() {
			// if (this._destroyEvent) return; // 21.10.2009 Ossig Perhaps invoked by destroy
			var w = this.contentIFrame().contentWindow;
			if (!w) return;
			// var unloadEventName = remoteGUI.eventTable.get("unload");
			var unloadEventName = remoteGUI.getEventName("unload");
			var log = this.log.bind(this);
			log("content window: try closing list of frames");
			[w].concat($A(w.frames)).each(function(frame) {
				log("content window: try closing frame");
				if (frame.closed || !frame.documentWhenReady) return;
				log("content window: fire ", unloadEventName);
				frame.documentWhenReady(frame.document, function(frame) {
					frame.Element.fire(frame, unloadEventName);
				} .curry(frame));
			});
		},
		destroy: function($super, keepTab) { // 06.12.2009 Ossig Is called delayed multiple times.
			if (this._destroyEvent) {
				if (this._destroyed) return;
				if (this.visible) {
					this.log("GUI.URLWindow.destroy: looping still visible");
					this._destroyEvent.delay(0.5);
					return;
				}
				/*
				// this.stopObserving("shown", this._onShownEvent);
				// Event.stopObserving(this.element, "unload", this._onUnloadEvent);
				Event.stopObserving(this.element, "mouseover", this._onMouseOverEvent);
				this.stopObserving("focused", this._onFocusedEvent);
				this.stopObserving("blurred", this._onBlurredEvent);
				this.stopObserving("hiding", this._onHidingEvent);
				*/
				this.log("GUI.URLWindow.destroy.$super");
				/*
				if (this.embedded && !keepTab) {
				var wmElement = this.windowManager.container;
				var workLevel = wmElement.retrieve("workLevel");
				GUI.metaWM.removeWorkFrame.bind(GUI.metaWM).defer(workLevel.tabs, { wmElement: wmElement });
				}
				*/
				var wmElement = this.windowManager.container;
				$super();
				if (this.embedded && !keepTab) { // 08.12.2009 Ossig Syncronious destroying.
					// var wmElement = this.windowManager.container;
					var workLevel = wmElement.retrieve("workLevel");
					if (workLevel) GUI.metaWM.removeWorkFrame(workLevel.tabs, { wmElement: wmElement }); // 16.12.2009 Ossig Maybe embedded Login Dialog without framing tab.
				}
				this._destroyed = true;
				return;
			}
			this._destroyEvent = this.destroy.bind(this, keepTab);
			/*
			var wContent = this.contentIFrame().contentWindow;
			if (wContent && this._onMouseOverEvent) {
			Event.stopObserving(wContent, "mouseover", this._onMouseOverEvent);
			}
			*/
			if (this.footbar && this.footbar instanceof GUI.WindowFootbar) {
				this.footbar.clear();
				this.footbar = true;
				if (this.geWindow) this.geWindow.footbar = undefined;
			}
			this._onBeforeDestroying();
			this.hide();
			this._destroyEvent.defer();
		},
		renameTab: function(name) { // URLWindow.renameTab
			var wmElement = this.windowManager.container;
			var workLevel = wmElement.retrieve("workLevel");
			if (workLevel) GUI.metaWM.renameTab(workLevel.tabs, { wmElement: wmElement }, name);
		} /*,
			_onUnload: function() {
				var OrigFrame = this.element.OrigFrame;
				if (OrigFrame) 
			}*/,
		_onMouseOver: function() {
			// this.activate();
			this.focus(); // 31.08.2009 Ossig Don't bring to front.
		},
		_onMouseDown: function() {
			GUI.log("GUI.URLWindow: _onMouseDown. this.contentIFrame().contentWindow.closed=", this.contentIFrame().contentWindow ? this.contentIFrame().contentWindow.closed : undefined);
			this.activate();
		} /*,
			_onClick: function() {
				this.activate();
			}*/,
		_onShown: function() {
			// this.observe("mouseover", this._onMouseOver.bind(this));
			var contentWindow = this.contentIFrame().contentWindow;
			if (!contentWindow) return;
			// if (!this._onMouseOverEvent) this._onMouseOverEvent = this._onMouseOver.bind(this);
			// Event.observe(contentWindow, "mouseover", this._onMouseOverEvent);
			documentWhenReady(contentWindow.document, this._onContentFrameSetLoad.bind(this, contentWindow));
			return;
		},
		_onContentFrameSetLoad: function(frameSet) {
			/*
			var onMouseDownEvent = this._onMouseDownEvent;
			Event.observe(frameSet.document, "mousedown", onMouseDownEvent);
			$A(frameSet.frames).each(function(frame) {
			documentWhenReady(frame.document, Event.observe.curry(frame, "mousedown", onMouseDownEvent));
			});
			*/
			GUI.log("mousedown: _onContentFrameSetLoad, this._onMouseDownEvent=", this._onMouseDownEvent);
			/*
			var registerContentFrame = this.registerContentFrame.bind(this);
			[frameSet].concat($A(frameSet.frames)).each(function(frame) {
			registerContentFrame(frame);
			});
			*/
			this.registerContentWindow(frameSet);
		},
		registerContentWindow: function(contentWindow) {
			var registerContentFrameEvent = this.registerContentFrameEvent;
			[contentWindow].concat($A(contentWindow.frames)).each(function(frame) {
				registerContentFrameEvent(frame);
			});
		},
		// _contentFrameHash: $H(), 11.11.2009 Ossig class member.
		registerContentFrame: function(frame) {
			GUI.log("mousedown: registerContentFrame ", frame.name, "this._onMouseDownEvent=", this._onMouseDownEvent);
			// documentWhenReady(frame.document, Event.observe.curry(frame, "mousedown", this._onMouseDownEvent));
			documentWhenReady(frame.document, function(frame) {
				if (this._contentFrameHash.get(frame))
					Event.stopObserving(frame, "mousedown", this._onMouseDownEvent);
				else
					this._contentFrameHash.set(frame, true);
				Event.observe(frame, "mousedown", this._onMouseDownEvent);
			} .bind(this, frame));
		},
		setSize: function($super, width, height, innerSize) {
			this.log("resize to {width:", width, ", height:", height, ", innerSize:", innerSize, "}");
			$super(width, height, innerSize);
		}
	}),
	OuterFrame: Class.create({
		initialize: function(outerElement, innerElement, container) {
			this.outerElement = outerElement;
			this.innerElement = innerElement;
			this.container = container;
		},
		setSize: function(outerSize) {
			GUI.log("OuterFrame setSize(", outerSize, ")");
			this.outerElement.setOuterSize(outerSize);
			this.container.setSize(this.innerElement.getInnerSize());
		}
	}),
	WindowManager: Class.create(UI.WindowManager, {
		initialize: function($super, container, opt) {
			$super(Object.extend({ container: container, zIndex: 120 }, opt || {})); // 21.10.2009 Ossig Over splitter.
			// this.container = $(container);
			// var dtBody = $(getDTFrame().document.body);
			// dtBody.observe("resize", this._onDTResize.bind(this));
			// debugger;

			/*
			var dtWin = $(getDTFrame());
			this._onDTResizeEvent = this._onDTResize.bind(this);
			Event.observe(dtWin, "resize", this._onDTResizeEvent);
			// Event.observe(dtWin, "gui:test", this._onTest.bind(this));
			this._onDTResize();
			*/
			/*
			var clientPane = this.container.up();
			this._onClientPaneResizeEvent = this._onClientPaneResize.bind(this, clientPane);
			clientPane.observe("resize", this._onClientPaneResizeEvent);
			this._onClientPaneResizeEvent();
			*/
		},
		destroy: function($super, keepTab) {
			if (this._destroyEvent) {
				var winCount = this.windows().size();
				this.log("destroy: # ", winCount, " windows alive");
				if (winCount > 0) {
					this._destroyEvent.defer();
					return;
				}
				this.log("destroy.$super");
				$super();
				return;
			}
			this.log("destroy");
			this._destroyEvent = this.destroy.bind(this);
			this.windows().invoke('destroy', keepTab);
			this._destroyEvent.defer();
		},
		getFirst: function() {
			return this.stack.windows.first();
		},
		cleanup: function() {
			this.windows().invoke('destroy');
			this.stack.destroy();
			// this.stack = new UI.WindowManager.Stack();
		},
		getByContentWindow: function(wContent) {
			if (!wContent) return undefined;
			wContent = wContent.TopFrame;
			return this.stack.windows.find(function(w) {
				if (!w.contentIFrame()) return false;
				var _wContent = w.contentIFrame().contentWindow;
				return !_wContent ? undefined : _wContent == wContent;
			});
		} /* ,
		_onTest: function() {
			GUI.log("WindowManager._onTest");
		},
		_onDTResize: function() {
			var area = UI.defaultWM.viewport.getDimensions();
			var area2 = $body.getInnerSize();
			this._resize(area);
		}*/,
		log: function() {
			GUI.log.apply(GUI, ["GUI.WindowManager", $_id(this.options.container), ": "].concat($A(arguments)));
		},
		_onClientPaneResize: function(clientPane) {
			var area = { width: clientPane.getWidth(), height: clientPane.getHeight() };
			this.setSize(area);
		},
		setSize: function(area) { // 21.10.2009 Ossig resize implemented by base class.
			// var area = Object.extend({ width: -1, height: -1 }, _area);
			// var areaFrame = Object.clone(_area);
			var container = this.container;
			/*
			var tabPanel = container.up(".ui-tabs-panel");
			this.log(container.id, "container check if hidden");
			if (tabPanel && tabPanel.hasClassName("ui-tabs-hide")) return;
			*/
			var outerSize = Object.extend(container.getOuterSize(), area); // 20.06.2010 Ossig left/right margin auto?
			this.log(container.id, "container resize to", outerSize);
			// if (areaFrame.width !== undefined) container.style.width = areaFrame.width + "px";
			// if (areaFrame.height !== undefined) container.style.height = areaFrame.height + "px";
			// if (areaFrame.width === undefined || areaFrame.height === undefined) return;
			// var area = { width: areaFrame.width - 1, height: areaFrame.height - 1 };
			// container.setSize(outerSize.width, outerSize.height);
			// container.setOuterSize(outerSize);
			container.setInnerSize(outerSize); // 20.06.2010 Ossig Chrome container negative margins when downsizing.
			var embeddedList = this.windows().pluck("embedded").compact();
			var innerSizeRaw = container.getInnerSize();
			var innerSize = { width: innerSizeRaw.width - 1, height: innerSizeRaw.height - 1 };
			this.log(container.id, "#embedded", embeddedList.size(), "resize to", innerSize);
			embeddedList.invoke("setSize", innerSize.width, innerSize.height); // 18.11.2009 Ossig Set outerSize of URLWindow to innerSize of Container.
			Element.fire.defer(getDTFrame(), "gui:ready-to-login");
		}
	}),
	MetaWindowManager: Class.create({ // 12.11.2009 Ossig Single instance.
		_wmWorkFrameHash: $H(), // workFrameIndex: WindowManager. // 11.11.2009 Ossig class member by design.
		_tabsWorkLevelHash: $H(), // levelFrameIndex: {workFrameTabs, wmElement} // 12.11.2009 Ossig class member by design.
		_workLevelID: 0, // 11.11.2009 Ossig value member.
		_workFrameID: 0, // 11.11.2009 Ossig value member.
		initialize: function(workLevelTabs, opt) {
			opt = opt || {};
			this._workLevelTabs = workLevelTabs;
			if (workLevelTabs) GUI.options.workTabs ? this._registerWorkLevel(workLevelTabs) : this._registerWorkFrame(workLevelTabs);
			// this._tabs = workFrameTabs;
			var wmDesktop = opt.wmDesktop ? opt.wmDesktop : new GUI.WindowManager("wmDesktop");
			this.wmDesktop = wmDesktop;
			this._registerDesktop();

			var menuContainer = $("wmMenu");
			if (!menuContainer && !opt.wmMenu) return; // 28.10.2009 Ossig gui.aspx
			// var activeGUI = window.remoteGUI; // Still not available.
			// if (!activeGUI.options.menuTabs) return; // 28.10.2009 Ossig gui.aspx

			var wmMenu = opt.wmMenu ? opt.wmMenu : new GUI.WindowManager(menuContainer);
			this._wmMenu = wmMenu;
			var outerFrameElement = $("menuOuterFrame");
			var innerFrameElement = $("menuInnerFrame");
			this._menuFrame = outerFrameElement ? new GUI.OuterFrame(outerFrameElement, innerFrameElement, wmMenu) : wmMenu;
			// var wmWorkLevelList = [];
			// this._wmWorkLevelList = wmWorkLevelList;
			// this._wmWorkLevelHash = $H(); // Has to be created when undefined menuContainer
			// this._workLevelID = 0;
			/* (20).times(function(index) {
			var wm = new GUI.WindowManager("wm-" + index);
			wmWorkLevelList.push(wm);
			}); */
		},
		getMenuContentWindow: function() {
			/* 
			if (!this._menuFrame) return;
			var wmMenu = this._menuFrame.container;
			*/
			var wmMenu = this._wmMenu;
			var wMenu = wmMenu ? wmMenu.getFirst() : undefined;
			var menuIFrame = wMenu ? wMenu.contentIFrame() : undefined;
			var menuContentWindow = menuIFrame ? menuIFrame.contentWindow : undefined;
			return menuContentWindow;
		},
		getOrigFrame: function() { // 29.05.2010 Ossig Access to OrigFrame from CMS desktop.
			var menuContentWindow = this.getMenuContentWindow();
			var origFrame = menuContentWindow ? menuContentWindow.OrigFrame : undefined;
			return origFrame && origFrame.frameProp && origFrame.frameProp.isReady() ? origFrame : undefined;
		},
		log: function() {
			GUI.log.apply(GUI, ["MetaWindowManager: "].concat($A(arguments)));
		},
		_onDTResize: function(e, wm) {
			// var area = UI.defaultWM.viewport.getDimensions(); // 22.10.2009 Ossig body size.
			var area2 = $body.getInnerSize();
			wm.setSize(area2);
		},
		_registerDesktop: function() {
			this._unregisterDesktop();
			var dtWin = $(getDTFrame());
			// this._wmDesktopSizeEvent = this._onDTResize.bind(this, this.wmDesktop);
			this._wmDesktopSizeEvent = this._onDTResize.bindAsEventListener(this, this.wmDesktop);
			Event.observe(dtWin, "resize", this._wmDesktopSizeEvent);
			this._wmDesktopSizeEvent();
		},
		_unregisterDesktop: function() {
			if (!this._wmDesktopSizeEvent) return;
			var dtWin = $(getDTFrame());
			Event.stopObserving(dtWin, "resize", this._wmDesktopSizeEvent);
			this._wmDesktopSizeEvent = undefined;
			// this._wmDesktop.destroy();
			// this._wmDesktop = undefined;
		},
		_onMenuPaneResize: function(wmListProp, pane) {
			GUI.log("_onMenuPaneResize");
			wmListProp().each(function(wm) {
				// var pane = wm.container.up();
				var area = pane.getDimensions();
				wm.setSize(area);
			});
		},
		/* _onWorkPaneResize: function(wmListProp, tabsElement) {
		var getPaneSize = this._tabs.getVisiblePaneSize.bind(this._tabs);
		wmListProp().each(function(wm) {
		var paneSize = getVisiblePaneSize({ wmElement: wm.container });
		if (!paneSize) return; // 11.11.2009 Ossig pane invisible
		wm.setSize(paneSize);
		});
		},*/
		_onWorkLevelResize: function(workLevelTabs) {
			GUI.log("_onWorkLevelResize");
			var getVisiblePaneSize = workLevelTabs.getVisiblePaneSize.bind(workLevelTabs);
			var workLevelList = this._tabsWorkLevelHash.values();
			workLevelList.each(function(workLevelEntry) {
				var wmElement = workLevelEntry.wmElement;
				/*
				var parentPaneElement = wmElement.up(".ui-tabs-panel");
				GUI.log("Check", wmElement, "if hidden", parentPaneElement);
				if (parentPaneElement && parentPaneElement.hasClassName("ui-tabs-hide")) {
				GUI.log("Is hidden");
				return;
				}
				GUI.log("Is not hidden");
				*/
				var paneSize = getVisiblePaneSize({ wmElement: wmElement });
				if (!paneSize) return; // 11.11.2009 Ossig pane invisible
				var tabPaneElement = paneSize.tabPaneElement;
				// tabPaneElement.setSize(paneSize.width, paneSize.height);
				tabPaneElement.setOuterSize(paneSize);
				wmElement.absolutize();
				wmElement.clonePosition(tabPaneElement, { setLeft: true, setTop: true, setHeight: false, setWidth: false, offsetLeft: 0, offsetTop: 0 });
				if (paneSize.width == 0) {
					alert("_onWorkLevelResize: with==0, height==" + paneSize.height);
					// debugger;
				}
				wmElement.setOuterSize(paneSize);
				var wmInnerSize = wmElement.getInnerSize();
				workLevelEntry.workFrameTabs.element.setOuterSize(wmInnerSize);
			});
		},
		_onWorkFrameResize: function(workFrameTabs) {
			GUI.log("_onWorkFrameResize");
			var getVisiblePaneSize = workFrameTabs.getVisiblePaneSize.bind(workFrameTabs);
			var wmList = this._wmWorkFrameHash.values();
			wmList.each(function(wm) {
				var wmElement = wm.container;
				var paneSize = getVisiblePaneSize({ wmElement: wmElement });
				if (!paneSize) return; // 11.11.2009 Ossig pane invisible
				var tabPaneElement = paneSize.tabPaneElement;
				tabPaneElement.setOuterSize(paneSize);
				wmElement.absolutize();
				wmElement.clonePosition(tabPaneElement, { setLeft: true, setTop: true, setHeight: false, setWidth: false, offsetLeft: 0, offsetTop: 0 });
				if (paneSize.width == 0) {
					alert("_onWorkFrameResize: with==0, height==" + paneSize.height);
					// debugger;
				}
				wm.setSize(paneSize);
			});
		},
		/*_onWorkPaneRemove: function(wmListProp, tabsElement, tabIndex) {
		if (arguments.length < 3) return; // 04.11.2009 Ossig Called initial.
		var tabPane0 = tabsElement.down("div");
		var tabPane = tabIndex <= 0 ? tabPane0 : tabPane0.next("div", tabIndex - 1);
		var wmElement = tabPane.down("div");
		// var workLevelIndex = wmElement.readAttribute("workLevelIndex");
		var workLevel = wmElement.retrieve("workLevel");
		GUI.log("tab remove: ", "tabIndex=", tabIndex, ", levelIndex=", $H(workLevel));
		var wm = this._wmWorkFrameHash.unset(workLevel.frameIndex);
		wm.destroy();
		this._tabs.remove(tabIndex);
		},*/
		_onWorkLevelRemove: function(workLevelTabs, workLevelTabIndex) {
			this.log("Remove workLevel", $_id(workLevelTabs.element), "[", workLevelTabIndex, "]");
			var tabContext = workLevelTabs.getTabContext({ tabIndex: workLevelTabIndex });
			var wmElement = tabContext.wmElement; // 13.11.2009 Ossig wmElement=workFrameTabs.element
			var workLevel = wmElement.retrieve("workLevel");
			var workLevelEntry = this._tabsWorkLevelHash.unset(workLevel.levelIndex);
			if (!workLevelEntry) return;
			var workFrameTabs = workLevelEntry.workFrameTabs;
			workFrameTabs.comLinkArr.invoke("stop"); // 13.11.2009 Ossig Sbould not happen. Will not be closed.
			var tabCount = workFrameTabs.length();
			for (var tabIndex = 0; tabIndex < tabCount; tabIndex++)
				this._onWorkFrameRemove(workFrameTabs, 0);
			workLevelTabs.remove(workLevelTabIndex);
		},
		_onWorkFrameRemove: function(workFrameTabs, tabIndex) {
			this.removeWorkFrame(workFrameTabs, { tabIndex: tabIndex });
		},
		removeWorkFrame: function(workFrameTabs, tabContext) {
			var tabContext = workFrameTabs.getTabContext(tabContext);
			var tabIndex = tabContext.tabIndex;
			this.log("removeWorkFrame", $_id(workFrameTabs.element), "[", tabIndex, "]");
			var wmElement = tabContext.wmElement; // 13.11.2009 Ossig wmElement=workFrameTabs.element
			var workLevel = wmElement.retrieve("workLevel");
			GUI.log("tab remove: ", "tabIndex=", tabIndex, ", levelIndex=", $H(workLevel));
			var wm = this._wmWorkFrameHash.unset(workLevel.frameIndex);
			wm.destroy(true);
			workFrameTabs.remove(tabIndex);
		},
		renameTab: function(workFrameTabs, tabContext, name) { // MetaWindowManager.renameTab
			var tabContext = workFrameTabs.getTabContext(tabContext);
			var tabIndex = tabContext.tabIndex;
			workFrameTabs.rename(tabIndex, name);
		},
		/* _onWorkPaneSelect: function(wmListProp, tabsElement, tabIndex) {
		if (arguments.length < 3) return; // 04.11.2009 Ossig Called initial.
		var tabContext = this._tabs.getTabContext({ tabIndex: tabIndex });
		var wmElement = tabContext.wmElement;
		// var workLevelIndex = parseInt(wmElement.readAttribute("workLevelIndex"));
		var workLevel = wmElement.retrieve("workLevel");
		GUI.log("tab select: ", "tabIndex=", tabIndex, ", levelIndex=", $H(workLevel));
		this._origFrame.Level = workLevel.levelIndex;
		this._wmWorkLevelSizeEvent();
		}, */
		_onWorkLevelSelect: function(workLevelTabs, tabIndex) {
			var tabContext = workLevelTabs.getTabContext({ tabIndex: tabIndex });
			var wmElement = tabContext.wmElement;
			// tabContext.tabNavElement.addClassName("ge-test");
			// var workLevelIndex = parseInt(wmElement.readAttribute("workLevelIndex"));
			var workLevel = wmElement.retrieve("workLevel");
			GUI.log("level tab select: ", "tabIndex=", tabIndex, ", levelIndex=", $H(workLevel));
			this._origFrame.Level = workLevel.levelIndex;
			this._onWorkLevelResize(workLevelTabs);
		},
		_onWorkFrameSelect: function(workFrameTabs, tabIndex) {
			var tabContext = workFrameTabs.getTabContext({ tabIndex: tabIndex });
			var wmElement = tabContext.wmElement;
			// tabContext.tabNavElement.addClassName("ge-test");
			// var workLevelIndex = parseInt(wmElement.readAttribute("workLevelIndex"));
			var workLevel = wmElement.retrieve("workLevel");
			GUI.log("work tab select: ", "tabIndex=", tabIndex, ", levelIndex=", $H(workLevel));
			this._origFrame.Level = workLevel.levelIndex;
			this._onWorkFrameResize(workFrameTabs);
		},
		_registerPane: function(observeEvent, stopObservingEvent, onResize, wmEventProp, wmListProp, data) {
			// pane = $(pane);
			this._unregisterPane(stopObservingEvent, wmEventProp); // 22.10.2009 Ossig jSplitter assumed to be constant.
			var wmEvent = onResize.bind(this, wmListProp, data);
			observeEvent(wmEvent, data);
			wmEvent();
			this[wmEventProp] = wmEvent;
		},
		_unregisterPane: function(stopObservingEvent, wmEventProp) {
			var wmEvent = this[wmEventProp];
			if (!wmEvent) return;
			stopObservingEvent(wmEvent);
			this[wmEventProp] = undefined;
		},
		registerMenuPane: function(splitterPane) {
			this._registerPane(
				splitterPane.observeResize.bind(splitterPane),
				splitterPane.stopObservingResize.bind(splitterPane),
				this._onMenuPaneResize,
				"_wmMenuSizeEvent",
				function() { return [this._menuFrame]; } .bind(this), //  function() { return [this._wmMenu]; } .bind(this),
				splitterPane.element);
			return this;
		},
		unregisterMenuPane: function(splitterPane) {
			this._unregisterPane(splitterPane.stopObservingResize.bind(splitterPane), "_wmMenuSizeEvent");
		},
		addWorkLevel: function(origFrame, opt) {
			// var tabs = this._tabs;
			var workFrameResult = {};
			var workFrameHash = $H(opt.workFrame);
			var tabs = this._workLevelTabs;
			if (!tabs) { // 28.05,.2010 Ossig CMS case
				workFrameHash.each(function(pair) {
					var workLevel = {};
					workFrameResult[pair.key] = workLevel;
				});
				return workFrameResult;
			};

			// if (Object.isString(paneNameList)) paneNameList = [paneNameList];
			this._origFrame = origFrame;
			// origFrame.Level = workLevelIndex; // 04.11.2009 Done by select

			if (Object.isString(opt)) {
				var paneName = opt;
				var workLevelIndex = this._workLevelID++;
				var workLevel = { levelIndex: workLevelIndex, frameIndex: workLevelIndex, tabs: tabs };
				var tabContext = tabs.addWorkLevel(workLevel, paneName); //  + " {level:" + workLevelIndex + ",frame:" + workFrameIndex + "}"
				var tabPaneElement = tabContext.tabPaneElement;
				var wmContainer = new Element("div", { "class": "wm", "id": "wm-" + workLevelIndex }); // , "workLevelIndex": workLevelIndex
				wmContainer.store("workLevel", workLevel);
				/*
				var wmContainer = $("wm-template").clone(true);
				wmContainer.writeAttribute({ "id": "wm-" + workLevelIndex, "workLevelIndex": workLevelIndex });
				*/
				tabPaneElement.insert({ top: wmContainer });
				tabs.select(tabContext.tabIndex); // 10.11.2009 Ossig Requires wmContainer.
				this._onWorkFrameResize(tabs); // that._wmWorkLevelSizeEvent(); // 13.11.2009 Ossig ComLink.
				// wmContainer.absolutize(); // 31.10.2009 Ossig Otherwise y=0 is top of tab anchor.
				var wm = new GUI.WindowManager(wmContainer);
				// this._wmWorkLevelList.push(wm);
				this._wmWorkFrameHash.set(workLevel.frameIndex, wm);
				// var tabIndex = this.getTabIndex(workLevelIndex);
				// GUI.log("workLevelIndex=", workLevelIndex, ", tabIndex=", tabIndex);
				return workLevel;
			}

			var workFrameTabs;
			var workLevelIndex;
			var dynamic = opt.workLevel.tabs;
			if (dynamic) {
				workFrameTabs = opt.workLevel.tabs;
				workLevelIndex = opt.workLevel.levelIndex;
			} else {
				var workLevelTabs = this._workLevelTabs;
				var paneName = opt.workLevel.paneName;
				workLevelIndex = this._workLevelID++;
				var workLevel = { levelIndex: workLevelIndex, frameIndex: workLevelIndex, tabs: workLevelTabs };
				var tabContext = workLevelTabs.addWorkLevel(workLevel, paneName);
				var tabPaneElement = tabContext.tabPaneElement;

				// var wmContainer = new Element("p");
				// wmContainer.insert(paneName);
				workFrameTabsElement = new Element("div", { "class": "ge-workframetabs", "id": "WorkFrameTabs-" + workLevelIndex });
				// workFrameTabsElement.store("workLevelIndex", workLevelIndex);
				// workFrameTabsElement.store("workLevel", workLevel);
				workFrameTabsElement.insert(new Element("ul"));

				// tabPaneElement.insert({ top: workFrameTabsElement });
				var wmElement = new Element("div", { "class": "wm ge-level", "id": "wmLevel-" + workLevelIndex });
				wmElement.store("workLevel", workLevel);
				wmElement.insert(workFrameTabsElement);
				tabPaneElement.insert({ top: wmElement });
				/* 17.11.2009 Ossig Not yet selected. Not possible to set size correctly.
				wmElement.absolutize();
				wmElement.clonePosition(tabPaneElement, { setLeft: true, setTop: true, setHeight: true, setWidth: true, offsetLeft: 0, offsetTop: 0 });
				*/

				// workLevelTabs.select(tabContext.tabIndex);
				workFrameTabs = new GUI.WorkFrameTabs(workFrameTabsElement, "WorkFrameTab-" + workLevelIndex + "-")
					.registerWorkPane(workLevelTabs);
				this._tabsWorkLevelHash.set(workLevelIndex, { workFrameTabs: workFrameTabs, wmElement: wmElement });
				workLevelTabs.select(tabContext.tabIndex); // 17.11.2009 Ossig Does not work for first tab perhaps implicitly selected?
				this._onWorkLevelResize(workLevelTabs); // 17.11.2009 Ossig Explicit try.
				this._registerWorkFrame(workFrameTabs);
			}

			// var workFrameResult = {};
			// var workFrameHash = $H(opt.workFrame);
			var that = this;
			var activeGUI = window.remoteGUI; // 13.11.2009 Ossig remoteGUI perhaps not available.
			workFrameHash.each(function(pair) {
				var workFrameIndex = that._workFrameID++;
				var paneName = pair.value.paneName;
				var symbolName = pair.value.symbolName;
				if (activeGUI && activeGUI.options.debug && activeGUI.options.debug.tabs) paneName += " {level:" + workLevelIndex + ",frame:" + workFrameIndex + "}";
				workLevel = { levelIndex: workLevelIndex, frameIndex: workFrameIndex, tabs: workFrameTabs };
				var tabContext = workFrameTabs.addWorkLevel(workLevel, { tabName: paneName, tabIndex: dynamic ? undefined : 0 });
				var navElement = tabContext.tabNavElement;
				if (dynamic) navElement.addClassName("ge-dynamic"); // tabContext.tabNavElement.select(".ui-icon-close").invoke("addClassName", "ge-dynamic");
				if (symbolName) {
					var symbolElement = new Element("span", { "class": "ge-symbol " + symbolName });
					navElement.insert({ top: symbolElement });
				}
				var tabPaneElement = tabContext.tabPaneElement;
				wmContainer = new Element("div", { "class": "wm ge-frame ui-corner-bottom", "id": "wm-" + workFrameIndex }); // 10.12.2009 Footbar // 20.11.2009 Ossig ui-corner-bottom: edges are overpainted by content.
				wmContainer.store("workLevel", workLevel);
				tabPaneElement.insert({ top: wmContainer });
				workFrameTabs.select(tabContext.tabIndex); // 10.11.2009 Ossig Requires wmContainer.
				// wmContainer.absolutize(); // 31.10.2009 Ossig Otherwise y=0 is top of tab anchor.
				var wm = new GUI.WindowManager(wmContainer);
				that._wmWorkFrameHash.set(workLevel.frameIndex, wm);
				that._onWorkFrameResize(workFrameTabs); // that._wmWorkLevelSizeEvent(); // 13.11.2009 Ossig ComLink.
				// var tabIndex = that.getTabIndex(workLevelIndex);
				// GUI.log("workLevelIndex=", workLevelIndex, ", tabIndex=", tabIndex);
				workFrameResult[pair.key] = workLevel;
			});
			// workFrameTabs.select(1);
			return workFrameResult;
		} /* ,
		removeWorkLevel: function(wmParentTab) {
			// Select Container (first div)
			// Remove WindowManager from List
			// Destroy WindowManager
			// Delete Container from wmParentTab
		} */,
		_registerWorkFrame: function(workFrameTabs) {
			new GUI.ComLink({ observer: workFrameTabs, oFn: "observeResize", oStopFn: "stopObservingResize", receiver: this, rFn: "_onWorkFrameResize" }).trigger();
			new GUI.ComLink({ observer: workFrameTabs, oFn: "observeRemove", oStopFn: "stopObservingRemove", receiver: this, rFn: "_onWorkFrameRemove" });
			new GUI.ComLink({ observer: workFrameTabs, oFn: "observeSelect", oStopFn: "stopObservingSelect", receiver: this, rFn: "_onWorkFrameSelect" });
		},
		_registerWorkLevel: function(workLevelTabs) {
			new GUI.ComLink({ observer: workLevelTabs, oFn: "observeResize", oStopFn: "stopObservingResize", receiver: this, rFn: "_onWorkLevelResize" }).trigger();
			new GUI.ComLink({ observer: workLevelTabs, oFn: "observeRemove", oStopFn: "stopObservingRemove", receiver: this, rFn: "_onWorkLevelRemove" });
			new GUI.ComLink({ observer: workLevelTabs, oFn: "observeSelect", oStopFn: "stopObservingSelect", receiver: this, rFn: "_onWorkLevelSelect" });
		},
		/* registerWorkPane: function() {
		var tabs = this._tabs;
		var getWorkLevelList = function() { return this._wmWorkFrameHash.values(); } .bind(this);
		this._registerPane(
		tabs.observeResize.bind(tabs),
		tabs.stopObservingResize.bind(tabs),
		this._onWorkPaneResize,
		"_wmWorkLevelSizeEvent",
		getWorkLevelList,
		tabs.element);
		this._registerPane(
		tabs.observeRemove.bind(tabs),
		tabs.stopObservingRemove.bind(tabs),
		this._onWorkPaneRemove,
		"_wmWorkLevelRemoveEvent",
		getWorkLevelList,
		tabs.element);
		this._registerPane(
		tabs.observeSelect.bind(tabs),
		tabs.stopObservingSelect.bind(tabs),
		this._onWorkPaneSelect,
		"_wmWorkLevelSelectEvent",
		getWorkLevelList,
		tabs.element);
		return this;
		},
		unregisterWorkPane: function() {
		var tabs = this._tabs;
		this._unregisterPane(tabs.stopObservingResize.bind(tabs), "_wmWorkLevelSizeEvent");
		this._unregisterPane(tabs.stopObservingRemove.bind(tabs), "_wmWorkLevelRemoveEvent");
		this._unregisterPane(tabs.stopObservingSelect.bind(tabs), "_wmWorkLevelSelectEvent");
		}, */
		getByContentWindow: function(contentWindow, favouredWM) {
			var guiWindow = undefined;
			var wm = favouredWM;
			if (wm) {
				guiWindow = wm.getByContentWindow(contentWindow);
				if (guiWindow) return guiWindow;
			}
			var wmList = this.getWMList();
			wmList.find(function(wm) {
				if (wm == favouredWM) return false;
				guiWindow = wm.getByContentWindow(contentWindow);
				return guiWindow;
			});
			return guiWindow; // Eighter valid or undefined;
		},
		getWM: function(workLevel) {
			// var wm = workLevelIndex != undefined ? this._wmWorkLevelList[workLevelIndex] : this.wmDesktop; // 16.10.2009 Ossig ZOrder confusion when activating different working planes.
			// var wm = this.wmDesktop;
			// var wm = workLevelIndex == undefined ? this.wmDesktop : workLevelIndex < 0 ? this._wmMenu : this._wmWorkLevelList[workLevelIndex]; // 16.10.2009 Ossig ZOrder confusion when activating different working planes.
			if (!this._wmMenu) return this.wmDesktop; // 28.10.2009 Ossig gui.aspx
			// var activeGUI = window.remoteGUI; // remoteGUI still not available.
			// if (!activeGUI.options.menuTabs) return this.wmDesktop; // 28.10.2009 Ossig gui.aspx

			// var wm = workLevelIndex == undefined ? this.wmDesktop : workLevelIndex < 0 ? this._wmMenu : this._wmWorkLevelList[0]; // 23.10.2009 Ossig Compatibility mode without tabs.
			var workLevelIndex = workLevel ? workLevel.levelIndex : undefined;
			var wm = workLevelIndex === undefined ? this.wmDesktop : workLevelIndex < 0 ? this._wmMenu : this._wmWorkFrameHash.get(workLevel.frameIndex); // 23.10.2009 Ossig Compatibility mode without tabs.
			return wm;
		},
		getWMList: function() {
			var wmList = [this.wmDesktop, this._wmMenu].concat(this._wmWorkFrameHash.values()).compact();
			return wmList;
		},
		selectWorkFrameTab: function(wmElement) {
			if (wmElement === undefined || wmElement < 0) return; // 09.11.2009 Ossig Login Dialog, Menu FrameSet.

			// var tabs = this._tabs;
			// var tabs = this._workLevelTabs;
			var workLevel = wmElement.retrieve("workLevel");
			GUI.log("select workFrameTab by workLevel", workLevel);
			if (!workLevel) return; // 23.11.2009 Ossig gui.aspx: wmElement==wmDesktop.
			var tabs = workLevel.tabs;
			if (!tabs) return;

			var tabContext = tabs.getTabContext({ wmElement: wmElement });
			if (!tabContext) return;
			tabs.select(tabContext.tabIndex);
		}
	}),
	ComLink: Class.create({
		// observer, oFn, oStopFn, oProp, receiver, rFn, rProp
		initialize: function(opt) {
			opt = Object.extend({ oFn: "observe", oStopFn: "stopObserving", oProp: "comLinkArr", rProp: "comLinkArr" }, opt);
			this.stop();
			var rCallback = opt.receiver[opt.rFn].bind(opt.receiver, opt.observer);
			var oStop = opt.observer[opt.oStopFn].bind(opt.observer);
			this.opt = { oStop: oStop, rCallback: rCallback };
			opt.observer[opt.oFn](rCallback); // 12.11.2009 Ossig Activate Listener
			this._push(opt.observer, opt.oProp);
			this._push(opt.receiver, opt.rProp);
		},
		_push: function(client, propName) {
			if (!propName) return;
			var comLinkArr = client[propName];
			if (!comLinkArr)
				comLinkArr = [this];
			else
				comLinkArr.push(this);
			client[propName] = comLinkArr.invoke("alive").compact();
		},
		stop: function() {
			var opt = this.opt;
			if (!opt) return this;
			opt.oStop(opt.rCallback);
			this.opt = undefined;
			return this;
		},
		trigger: function() {
			var opt = this.opt;
			if (opt) opt.rCallback.apply(this, arguments);
			return this;
		},
		alive: function() {
			return this.opt ? this : undefined;
		}
	})
});

/*
Object.extend(GUI.WindowManager.prototype, (function() {
	var resizeIndex = 0;
	function resize() {
		GUI.log("GUI.WindowManager.resize also in inheritance chain. resizeIndex=", resizeIndex++);
	}
	return {
		resize: resize
	}
})());
*/

var RemoteGUI = Class.create(GUIBase, {
	initialize: function(opt) {
		GUI.log("RemoteGUI.opt=", opt);
		this.options = opt || {};
	},
	/* 25.05.2010 Ossig Use OrigFrame.TopFrame instead.
	getMenuWindow: function() {
	return GUI.metaWM.getMenuContentWindow();
	},
	*/
	startWorkLevel: function(frame, opt) {
		var pane = opt.pane;
		var defWorkLevel = { levelIndex: pane ? pane.index : 0 };
		if (!this.options.menuTabs) return { edit: defWorkLevel, search: defWorkLevel };

		var paneName = (function() {
			if (!pane) return "";
			return pane.domainName ? pane.domainName + ": " + pane.name : pane.name;
		})();

		if (!this.options.workTabs) {
			var workLevel = GUI.metaWM.addWorkLevel(frame.OrigFrame, paneName); // frame.OrigFrame.Level = workLevelIndex;
			return { "edit": workLevel, "search": workLevel };
		}

		var _opt = {};
		if (opt.edit) _opt["edit"] = { paneName: opt.edit.paneName || "edit", symbolName: "ge-symbol-edit" };
		if (opt.search) _opt["search"] = { paneName: opt.search.paneName || "search", symbolName: "ge-symbol-find" };
		_opt = { workLevel: { paneName: paneName }, workFrame: _opt };
		var result = GUI.metaWM.addWorkLevel(frame.OrigFrame, _opt)
		return result;
	},
	appendWorkLevel: function(contentWindow, workLevel, url, extraTabPane) {
		var w = this._getGUIWindow(contentWindow);
		if (!w) return workLevel;
		var script = url.split("?")[0].toLowerCase();
		// if (script.indexOf("search.asp") < 0) return workLevel;
		var title = extraTabPane.paneName || url.toQueryParams()["XX_Header"] || "extraTabPane";
		var wmElement = w.windowManager.container;
		var workLevel = wmElement.retrieve("workLevel");
		var result = GUI.metaWM.addWorkLevel(contentWindow.OrigFrame, {
			workLevel: workLevel,
			workFrame: { "append": { paneName: title} }
		});
		var resultWorkLevel = result["append"];
		return resultWorkLevel;
	},
	getFirstFreeLevel: function(origFrame) {
		return {}; // 04.12.2009 Ossig Always free workLevel.levelIndex available.
	},
	getFrameSet: function(frame) { // 16.08.2009 Ossig Ancient TopFrame.
		// if (!frame.frameElement) return frame; // 16.08.2009 Ossig frameElement only defined for frame.
		var parentFrame = frame.parent;
		return parentFrame.frameElement ? parentFrame : frame; // 16.08.2009 Ossig getDTFrame.frameElement==false (No frameset above).
	},
	init: function(contentWindow) {
		var TopFrame = this.getFrameSet(contentWindow);
		var guiDataPort = TopFrame.frameElement.guiDataPort;
		var contentDoc = contentWindow.document;
		contentDoc.whenReady(function(embedded) {
			/*
			if (embedded)
			this.body.addClassName("ge-embedded");
			else
			this.body.removeClassName("ge-embedded");
			*/
			if (!embedded)
				this.body.addClassName("ge-not-embedded");
		} .bind(contentDoc, guiDataPort.embedded));
		contentWindow.TopFrame = TopFrame;
		var iframeElement = contentWindow.frameElement;
		var check = this.checkOrigFrame.bind(this);
		if (!contentWindow.OrigFrame) {
			var origFrameArr = [
				check(contentWindow)
				, check(iframeElement.OrigFrame)
				, check(contentWindow.opener)
				, check(contentWindow, { checkFrameSet: true })
				, check(contentWindow.TopFrame.OrigFrame, { checkID: false })
				, contentWindow.TopFrame // Last choice not undefined
			];
			// GUI.log(origFrameArr);
			contentWindow.OrigFrame = origFrameArr.find(Prototype.K);
		}
		contentWindow.frameSetProp = contentWindow == contentWindow.TopFrame ? new contentWindow.FrameSetProp() : undefined;
		var activeGUI = this;
		contentWindow.geOpener = activeGUI.getOpenerContentWindow(contentWindow);
		GUI.log("==> RemoteGUI.init: window", contentWindow, "OrigFrame", contentWindow.OrigFrame, "geOpener", contentWindow.geOpener);
		return activeGUI;
	},
	closeTimerWindow: function(_window, clientPathGenericModules) {
		// _window._OpenTimerWindow(clientPathGenericModules,-1,-1,-1).close(); // 20.09.2009 Ossig Problem with popup blocker.
	},
	_getGUIWindow: function(contentWindow) {
		// if (!contentWindow) contentWindow = window;
		if (!contentWindow || contentWindow.closed) return undefined;
		var wm = GUI.metaWM;
		if (!wm) return undefined;
		var guiWindow = wm.getByContentWindow(contentWindow);
		if (contentWindow.geSystem) contentWindow.geSystem.assert(guiWindow); // 04.09.2009 Ossig No assertion when called from initWindow.
		return guiWindow;
	},
	getIFrame: function(contentWindow) {
		var guiWindow = this._getGUIWindow(contentWindow);
		return guiWindow ? guiWindow.contentIFrame() : undefined;
	},
	getGEWindow: function(contentWindow) {
		var guiWindow = this._getGUIWindow(contentWindow);
		return guiWindow ? guiWindow.geWindow : undefined;
	},
	getGUIOpt: function(contentWindow) {
		var guiWindow = this._getGUIWindow(contentWindow);
		var wm = guiWindow ? guiWindow.windowManager : undefined;
		// var guiOpt = wm ? { guiOpt: { wm: wm}} : undefined; // 31.05.2010 Ossig guiOpt needed for startWorkLevel
		var guiOpt = wm ? {wm: wm} : undefined;
		return guiOpt;
	},
	enforceCloseWindow: function(contentWindow) {
		var w = this._getGUIWindow(contentWindow);
		if (!w) return;
		w.destroy(); // w.close(); // 06.12.2009 Ossig close depends on close-button, doese not work for embedded windows.
	},
	closeWindow: function(contentWindow) {
		var w = this._getGUIWindow(contentWindow);
		if (!w) return;
		w.destroy(); // w.close(); // 06.12.2009 Ossig close depends on close-button, doese not work for embedded windows.
	},
	focusWindow: function(contentWindow) {
		var w = this._getGUIWindow(contentWindow);
		if (!w) return;
		w.activate();
		contentWindow.focus();
	},
	registerWindow: function(contentWindow) {
		/*
		if (!contentWindow || contentWindow.closed) return;
		var w = this._getGUIWindow(contentWindow);
		w.registerContentFrame(contentWindow);
		*/
		var w = this.getGEWindow(contentWindow);
		if (!w) return;
		w.registerContentWindow(contentWindow);
	},
	_eventTable: $H({
		unload: "gui:unload"
	}),
	getEventName: function(eventName) {
		var name = this._eventTable.get(eventName);
		return name ? name : eventName;
	},
	// opt.onShown
	// opt.geWindow
	GEWindow: Class.create(GUIBase.GEWindowBase, {
		initialize: function($super, openerContentWindow, sURL, sName, _opt, bReplace) {
			$super();
			_opt = _opt || {};
			var activeGUI = window.remoteGUI;
			this.activeGUI = activeGUI;
			this.name = sName;
			this.openerContentWindow = openerContentWindow;
			// var sURLEx = sURL + "&" + this.windowNameKey + "=" + sName;
			var sURLEx = this.urlAppendWindowNameToken(sURL);
			if (openerContentWindow) sURLEx = openerContentWindow.geSystem.GetAbsSystemURL(openerContentWindow.DotNetWindowCall(sURLEx));
			var opt = { left: 100, top: 100, width: 400, height: 300, onShown: undefined, geWindow: this };
			// opt.embedded = _opt.workLevel.levelIndex < 0 ? activeGUI.options.menuTabs : activeGUI.options.workTabs && !_opt.shadow;
			Object.extend(opt, _opt);
			opt.shadow = !opt.embedded;

			/* if (opt.left >= 160 && opt.left < 250) { // 19.10.2006 Ossig IE7 correction.
			opt.width += opt.left - 250;
			opt.left = 250;
			// opt.width += 160 - 250;
			} */
			/* if (opt.left >= 160) {
			opt.left -= 250;
			if (opt.left < 0) {
			opt.width += opt.left;
			opt.left = 0;
			}
			} */
			if (opt.left >= 160 && opt.left < 250) { // 19.10.2006 Ossig IE7 correction.
				opt.width += opt.left - 250;
				opt.left = 250;
			}
			if (opt.left >= 250 && activeGUI.options.menuTabs) opt.left -= 250;
			/*
			// var area = GUI.desktopWM.viewport.getDimensions();
			var area = GUI.metaWM.wmDesktop.viewport.getDimensions();
			if (opt.left + opt.width > area.width)
			opt.width = area.width - opt.left;
			if (opt.top + opt.height > area.height)
			opt.height = area.height - opt.top;
			*/

			var OrigFrame = undefined;
			var guiDataPort = undefined;
			if (openerContentWindow) {
				// var sFeatures = geSystem.getWindowOpenFeature(opt.width, opt.height);
				OrigFrame = openerContentWindow.OrigFrame; // 27.08.2009 Ossig store in case of openerContentWindow == w when window.name is equal.
				guiDataPort = openerContentWindow.TopFrame.frameElement.guiDataPort;
			}
			var workLevel = opt.workLevel;
			if (workLevel.levelIndex >= 0 && workLevel.frameIndex === undefined && guiDataPort) { // guiDataPort.workLevel
				workLevel = Object.clone(guiDataPort.workLevel); // 10.11.2009 Ossig window.openWindow frameIndex clientside inheritance without touching serverside LocLevel logic.
				opt.workLevel = workLevel;
			} else
				workLevel = Object.clone(workLevel);
			var popupModal = GUI.options.workTabs && GUI.options.modalPopupWindow ? !opt.embedded : false;
			var w = new GUI.URLWindow(sURLEx, opt).show(popupModal);
			var iframeElement = w.contentIFrame();
			iframeElement.OrigFrame = OrigFrame;
			iframeElement.guiDataPort = Object.extend(iframeElement.guiDataPort || {}, { workLevel: workLevel });
			// iframeElement.geOpener = OrigFrame; // openerContentWindow;
			// var iframeWindow = w.contentIFrame().contentWindow; // 17.08.2009 Ossig Still is undefined
			// return new RemoteGUI.GEWindow(iframeElement.contentWindow, w);
			if (opt.onShown)
				w.observe("shown", opt.onShown);
			// this._openerWindow=openerWindow;
			// w.observe("shown", w.activate);
			this._w = w;
			this.name = sName;
		},
		close: function() {
			if (!this._w) return;
			this._w.destroy(); // this._w.close(); // 06.12.2009 Ossig close depends on close-button, doese not work for embedded windows.
			this._w = undefined;
		},
		focus: function(contentFrame) {
			var w = this._w;
			if (!w) return;
			w.activate();
			if (!contentFrame) contentFrame = w.contentIFrame().contentWindow;
			if (!contentFrame) return;
			contentFrame.focus();
		},
		getContentWindow: function() {
			var w = this._w;
			var contentWindow = !w ? undefined : w.contentIFrame().contentWindow;
			return contentWindow;
		},
		registerContentWindow: function(contentFrame) {
			this._w.registerContentWindow(contentFrame);
		},
		setLocation: function($super, sURL, contentFrame, openerWindow) {
			var result = $super(sURL, contentFrame, openerWindow);
			var w = this._w;
			if (w) {
				GUI.metaWM.selectWorkFrameTab.bind(GUI.metaWM, w.windowManager.container).defer(); // 19.11.2009 Ossig Don't select not yet reloaded pane ==> defer.
				w.activate(); // 28.05.2010 Ossig CMS: In case of multiple embedded windows: Bring to front.
			}
			return result;
		},
		renameTab: function(name) {
			var w = this._w;
			if (!w) return;
			w.renameTab(name);
		}
	})
});

// var remoteGUI = new RemoteGUI();