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: Object.extend(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.
				smartpos: true
			};
			if (_opt) Object.extend(opt, _opt);

			var embedded = opt.embedded ? this : undefined;
			this.embedded = embedded;
			// this.dynamic = opt.dynamic ? this : undefined;
			// this.dynamic = workLevel ? !!workLevel.tabs : false; // 05.07.2011 Ossig isDynamic
			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";
			opt.url = GUI.URLWindow.filterURL(url, GUI.metaWM.getQueryParams(workLevel));

			// 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 (opt.smartpos) { // 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();
			}
			*/
			/*
			var busySpinner = this.getBusySpinner(); // 30.01.2011 Ossig busySpinner not available on desktop/menu.
			if (busySpinner) busySpinner.unlock.bind(busySpinner).defer();
			*/
			this.whenContentLoad = (function (that, contentFrame) {
				var callbackQueue = [];
				function stopContentLoadHandler() {
					if (contentLoadHandler) {
						contentLoadHandler.stop();
						contentLoadHandler = undefined;
					}
				}
				var contentLoadHandler = contentFrame.on("load", function (event) {
					// var element = event.findElement();
					// var contentWindow = element.contentWindow;
					// [contentWindow].concat($A(contentWindow.frames)).pluck("document").invoke("fire", "ge:afterStore");
					stopContentLoadHandler();
					that.whenContentLoad = function (callback) {
						callback.call(window);
					};
					callbackQueue.invoke('call', window, contentFrame.contentWindow);
					callbackQueue.clear();
				});
				that.observe("destroyed", stopContentLoadHandler);
				return function (callback) {
					callbackQueue.push(callback);
				};
			})(this, iframeElement);

			this._agentDepotList = [];
			this.observe("destroyed", function () {
				var agentDepotList = this._agentDepotList;
				if (!agentDepotList) return;
				agentDepotList.invoke("stop");
				this._agentDepotList = undefined;
			} .bind(this));
		},
		pushAgent: function (agentDepot) {
			this._agentDepotList.push(agentDepot);
			var mergeAgentList = this._mergeAgentList.bind(this);
			this.whenContentLoad(function (contentWindow) {
				[contentWindow].concat($A(contentWindow.frames)).pluck("document").invoke("fire", "ge:agent", {
					mergeAgentList: mergeAgentList
				});
			});
		},
		startAgentList: function (hostWindow) {
			var agentList = this._agentDepotList.invoke("start", hostWindow);
			return agentList;
		},
		_mergeAgentList: function (hostWindow, _prevAgentList) {
			var prevAgentList = _prevAgentList.clone();
			var prevAgentDepotIDList = prevAgentList.pluck("depotID");
			var agentDepotList = this._agentDepotList;
			var agentList = agentDepotList.collect(function (agentDepot) {
				var prevAgentIndex = prevAgentDepotIDList.indexOf(agentDepot.id);
				var agent;
				if (prevAgentIndex >= 0) {
					agent = prevAgentList[prevAgentIndex];
					prevAgentList[prevAgentIndex] = undefined;
				} else {
					agent = agentDepot;
				}
				return agent;
			});
			prevAgentList.compact().invoke("stop"); // Outdated agents.
			agentList.invoke("start", hostWindow); // Start new agents.
			return agentList;
		},
		/*,
		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;
		}*/
		getBusySpinner: function () {
			var wmElement = this.windowManager.container;
			var workLevel = wmElement.retrieve("workLevel");
			return GUI.metaWM.getBusySpinner(workLevel);
		},
		getWorkLevel: function () {
			var wmElement = this.windowManager.container;
			var workLevel = wmElement.retrieve("workLevel");
			// workLevel = { levelIndex: workLevelIndex, frameIndex: workFrameIndex, tabs: workFrameTabs };
			return workLevel;
		},
		getWorkNodes: function () {
			var wmFrameElement = this.windowManager.container;
			var wmLevelElement = wmFrameElement.up(".wm.ge-level");
			return { frameNode: GUI.pinNavNode(wmFrameElement), levelNode: GUI.pinNavNode(wmLevelElement) };
		},
		getQueryParams: function () {
			return GUI.metaWM.getQueryParams(this.getWorkLevel());
		},
		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();
			/*
			document.whenReady(function () {
			var contentIFrame = this.contentframe;
			var eventHandlerList = [];
			if (contentIFrame) eventHandlerList.push(contentIFrame.on("load", function (event) {
			var element = event.findElement();
			var memo = event.memo;
			// alert("contentIFrame load");
			var contentWindow = element.contentWindow;
			[contentWindow].concat($A(contentWindow.frames)).pluck("document").invoke("fire", "ge:afterStore");
			}));
			document.whenUnload(function () {
			if (eventHandlerList) {
			eventHandlerList.invoke("stop");
			eventHandlerList = undefined;
			}
			});
			} .bind(this));
			*/
		},
		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) {
			if (!GUI.options.upload.radUpload) return;
			var contentWindow = this.contentIFrame().contentWindow;
			if (!contentWindow) return;
			var moveDataEditFrame = contentWindow; // 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;
			// if (tryGetMember(w, "closed", true)) return; // cross scripting
			if (!tryGetMember(w, "documentWhenReady")) return; // cross scripting
			// 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 close frame when not already closed");
				if (frame.closed || !frame.documentWhenReady) return;
				log("content window: do close frame. Fire ", unloadEventName, " to all (sub)frames");
				frame.documentWhenReady(frame.document, function (frame) {
					log("fire ", unloadEventName, " to ", frame.name, frame.closed);
					frame.Element.fire(frame, unloadEventName);
					frame.document.fire(unloadEventName); // 03.01.2011 Ossig Allow document.on
				} .curry(frame));
				log("content window: done");
			});
		}, */
		onTabSelect: function () {
			var w = this.contentIFrame().contentWindow;
			if (!tryGetMember(w, "documentWhenReady")) return; // cross scripting
			[w].concat($A(w.frames)).each(function (frame) {
				if (frame.closed || !frame.documentWhenReady) return;
				frame.documentWhenReady(frame.document, function (frame) {
					// frame.Element.fire(frame, "gui:tab-select");
					frame.document.fire("gui:tab-select");
				} .curry(frame));
			});
		},
		destroy: function ($super, keepTab) { // 06.12.2009 Ossig Is called delayed multiple times.
			if (this._destroyed) return;
			if (this.footbar && this.footbar instanceof GUI.WindowFootbar) {
				this.footbar.clear();
				this.footbar = true;
				if (this.geWindow) this.geWindow.footbar = undefined;
			}
			var geWindow = this.geWindow;
			if (geWindow) {
				this.geWindow = undefined;
				geWindow.close();
			}
			this.log("GUI.URLWindow.destroy.$super");
			var wmElement = this.windowManager.container;
			this._destroyed = true;
			/*
			(function () {
				var iFrame = this.contentIFrame();
				var contentWindow = iFrame && iFrame.contentWindow;
				if (contentWindow && !contentWindow.closed) {
					contentWindow.close();
				}
			}).call(this);
			*/
			$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.
			}
		},
		closeLevel: function () {
			var wmFrameElement = this.windowManager.container;
			var wmLevelElement = wmFrameElement.up(".wm.ge-level");
			if (!wmLevelElement)
				this.destroy();
			else
				GUI.metaWM.removeWorkLevel({ wmElement: wmLevelElement });
		},
		isDynamic: function () {
			var wmFrameElement = this.windowManager.container;
			var tabContext = new GUI.TabsElement().getTabContext({ wmElement: wmFrameElement });
			if (!tabContext) return false;
			var navElement = tabContext.tabNavElement;
			return navElement.hasClassName("ge-dynamic");
		},
		closeFrame: function () {
			if (!this.embedded || this.isDynamic())
				this.destroy()
			else
				this.closeLevel();
		},
		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();
			this[this.embedded ? "focus" : "activate"](); // 11.05.2011 Ossig embedded window always has to be in the background.
		} /*,
			_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));
			/*
			var busySpinner = this.getBusySpinner(); // 30.01.2011 Ossig busySpinner not available on desktop/menu.
			if (busySpinner) busySpinner.unlock();
			*/
		},
		_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);
			var busySpinner = this.getBusySpinner(); // 30.01.2011 Ossig busySpinner not available on desktop/menu.
			if (busySpinner) busySpinner.unlock();
		},
		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);
		}
	}), {
		filterURL: function (urlString, queryParams) {
			if (!urlString) urlString = "EmptyURLWindow.html";
			if (!queryParams) return urlString;
			var urlPart = urlString.split("?", 2);
			var queryParamHash = urlPart[1] ? $H(urlPart[1].toQueryParams()) : $H();
			// queryParamHash.set("Mode", 1); // 29.06.2011 Ossig Speichern&Schließen.
			queryParamHash = queryParamHash.merge(queryParams);
			return [urlPart[0], queryParamHash.toQueryString()].join("?");
		}
	}),
	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, opt) {
			if (this._destroyEvent) {
				opt = Object.extend({ loopCount: 0 }, opt || {});
				var winCount = this.windows().size();
				this.log("destroy: loopCount=", opt.loopCount, "#windows alive=", winCount);
				if (winCount > 0 && opt.loopCount < 10) {
					opt.loopCount++;
					// this._destroyEvent.defer();
					this._destroyEvent.delay(1, keepTab, opt);
					return;
				}
				this.log("destroy.$super: loopCount=", opt.loopCount);
				$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.findSpeed(function (w) {
				if (!w.contentIFrame()) return false;
				var _wContent = w.contentIFrame().contentWindow;
				return !_wContent ? undefined : _wContent == wContent;
			});
		},
		getByName: function (name) {
			if (!name) return undefined;
			return this.stack.windows.findSpeed(function (w) {
				var geWindow = w.geWindow;
				return geWindow && geWindow.name == name;
			});
		},
		/*
		_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");
		},
		onTabSelect: function () {
			var windowList = this.windows();
			windowList.invoke("onTabSelect");
		}
	}),
	MetaWindowManager: Class.create({ // 12.11.2009 Ossig Single instance.
		_wmWorkFrameHash: $H(), // workFrameIndex: {busySpinner: GUI.BusySpinner, wm: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) this._registerWorkLevel(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();
				var workFrameTabs = workLevelEntry.workFrameTabs;
				workFrameTabs.element.setOuterSize(wmInnerSize);

				// 04.01.2011 Ossig Resize WorkFrame too.
				this._onWorkFrameResize(workFrameTabs);
			}, this);
		},
		_onWorkFrameResize: function (workFrameTabs) {
			GUI.log("_onWorkFrameResize");
			var getVisiblePaneSize = workFrameTabs.getVisiblePaneSize.bind(workFrameTabs);
			var wmList = this._wmWorkFrameHash.values().pluck("wm");
			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;
		wm.destroy();
		this._tabs.remove(tabIndex);
		},*/
		_onWorkLevelRemove: function (workLevelTabs, tabIndex) {
			GUI.assert(this._workLevelTabs == workLevelTabs);
			this.removeWorkLevel({ tabIndex: tabIndex });
		},
		removeWorkLevel: function (tabContext) {
			var workLevelTabs = this._workLevelTabs;
			var tabContext = workLevelTabs.getTabContext(tabContext);
			if (!tabContext) return;
			var tabIndex = tabContext.tabIndex;
			this.log("Remove workLevel", $_id(workLevelTabs.element), "[", tabIndex, "]");
			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; // 11.09.2011 Ossig Triggered by lines below.
			var workFrameTabs = workLevelEntry.workFrameTabs;
			workFrameTabs.comLinkArr.invoke("stop"); // 13.11.2009 Ossig Sbould not happen. Will not be closed.
			/*
			var tabCount = workFrameTabs.tabLength();
			for (var tabIndex = 0; tabIndex < tabCount; tabIndex++)
			this._onWorkFrameRemove(workFrameTabs, 0);
			*/
			GUI.log("Remove all workFrameTabs");
			GE.$Range(workFrameTabs.tabLength()).each(function () {
				this._onWorkFrameRemove(workFrameTabs, 0);
			}, this);
			workLevelTabs.remove(tabIndex);
			GUI.log("Remove single workLevelTab");
		},
		_onWorkFrameRemove: function (workFrameTabs, tabIndex) {
			this.removeWorkFrame(workFrameTabs, { tabIndex: tabIndex });
		},
		removeWorkFrame: function (workFrameTabs, tabContext) {
			var tabContext = workFrameTabs.getTabContext(tabContext);
			if (!tabContext) return; // 20.07.2010 Ossig Already deleted.
			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));
			GUI.log("_wmWorkFrameHash.unset: frameIndex=", workLevel.frameIndex);
			var wmWorkFrame = this._wmWorkFrameHash.unset(workLevel.frameIndex);
			if (!wmWorkFrame) return; // 11.09.2011 Ossig Triggered by lines below.
			var wm = wmWorkFrame.wm;
			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 });
			if (!tabContext) return;
			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);
			this._onWorkLevelTabSelect(workLevelTabs, tabIndex);
		},
		_onWorkFrameSelect: function (workFrameTabs, tabIndex) {
			var tabContext = workFrameTabs.getTabContext({ tabIndex: tabIndex });
			if (!tabContext) return;
			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);
			this._onWorkFrameTabSelect(workFrameTabs, tabIndex);
		},
		_onWorkLevelTabSelect: function (workLevelTabs, workLevelTabIndex) {
			var tabContext = workLevelTabs.getTabContext({ tabIndex: workLevelTabIndex });
			var wmElement = tabContext.wmElement;
			var navNode = GUI.pinNavNode(wmElement);
			navNode.markRelatives();
			var workLevel = wmElement.retrieve("workLevel");
			var workLevelEntry = this._tabsWorkLevelHash.get(workLevel.levelIndex);
			if (!workLevelEntry) return;
			var workFrameTabs = workLevelEntry.workFrameTabs;
			this._onWorkFrameTabSelect(workFrameTabs);
		},
		_onWorkFrameTabSelect: function (workFrameTabs, workFrameTabIndex) {
			var wmList;
			if (arguments.length >= 2) {
				var tabContext = workFrameTabs.getTabContext({ tabIndex: workFrameTabIndex });
				var wmElement = tabContext.wmElement;
				var workLevel = wmElement.retrieve("workLevel");
				var wm = this._wmWorkFrameHash.get(workLevel.frameIndex).wm;
				wmList = [wm];
			} else
				wmList = this._wmWorkFrameHash.values().pluck("wm");
			var getVisiblePaneSize = workFrameTabs.getVisiblePaneSize.bind(workFrameTabs);
			wmList.each(function (wm) {
				var wmElement = wm.container;
				var paneSize = getVisiblePaneSize({ wmElement: wmElement });
				if (!paneSize) return; // 11.11.2009 Ossig pane invisible
				wm.onTabSelect();
			});
		},
		_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);
			if (GUI.options.cmsMode) { // 28.05.2010 Ossig CMS case
				workFrameHash.each(function (pair) {
					var workLevel = {};
					workFrameResult[pair.key] = workLevel;
				});
				return workFrameResult;
			};

			// var tabs = this._workLevelTabs;
			// if (Object.isString(paneNameList)) paneNameList = [paneNameList];
			this._origFrame = origFrame;
			// origFrame.Level = workLevelIndex; // 04.11.2009 Done by select

			/* 22.06.2011 Ossig menuTabs outdated.
			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: 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 activeGUI = window.remoteGUI; // 13.11.2009 Ossig remoteGUI perhaps not available.
			workFrameHash.each(function (pair) {
				var workFrameIndex = this._workFrameID++;
				var paneName = pair.value.paneName;
				var symbolName = pair.value.symbolName;
				if (activeGUI && 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");
				var busySpinner;
				if (symbolName) {
					/*
					var busyElement = new Element("div", { "class": "ge-busy-container" });
					navElement.insert({ top: busyElement });
					var symbolElement = new Element("span", { "class": "ge-tabnav-symbol ge-symbol " + symbolName });
					busyElement.insert({ top: symbolElement });
					*/
					/* jSymbolElement.spinner(); */
					/*
					var jBusyElement = $j(busyElement);
					jBusyElement.busy({ hide: false });
					symbolElement.style.display = "none";
					*/
					var symbolElement = new Element("span", { "class": "ge-tabnav-symbol ge-symbol " + symbolName });
					busySpinner = new GUI.BusySpinner({ lock: true, hideElement: symbolElement });
					navElement.insert({ top: busySpinner.element });
					busySpinner.element.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);
				GUI.log("_wmWorkFrameHash.set: frameIndex=", workLevel.frameIndex);
				this._wmWorkFrameHash.set(workLevel.frameIndex, { wm: wm, busySpinner: busySpinner });
				this._onWorkFrameResize(workFrameTabs); // this._wmWorkLevelSizeEvent(); // 13.11.2009 Ossig ComLink.
				// var tabIndex = this.getTabIndex(workLevelIndex);
				// GUI.log("workLevelIndex=", workLevelIndex, ", tabIndex=", tabIndex);
				workFrameResult[pair.key] = workLevel;
			}, this);
			// 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().pluck("wm"); } .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.findSpeed(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).wm; // 23.10.2009 Ossig Compatibility mode without tabs.
			return wm;
		},
		getBusySpinner: function (workLevel) {
			if (!workLevel) return undefined;
			var workFrame = this._wmWorkFrameHash.get(workLevel.frameIndex);
			return workFrame ? workFrame.busySpinner : undefined;
		},
		setQueryParams: function (workLevel, _queryParams) {
			if (!workLevel) return undefined;
			var workFrame = this._wmWorkFrameHash.get(workLevel.frameIndex);
			if (!workFrame) return undefined;
			workFrame.queryParams = $H(_queryParams);
		},
		getQueryParams: function (workLevel) {
			if (!workLevel) return undefined;
			var workFrame = this._wmWorkFrameHash.get(workLevel.frameIndex);
			if (!workFrame) return undefined;
			return $H(workFrame.queryParams);
		},
		getWMList: function () {
			var wmList = [this.wmDesktop, this._wmMenu].concat(this._wmWorkFrameHash.values().pluck("wm")).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;
		}
	}),
	IDFactory: Class.create({
		_index: 0,
		initialize: function (label) {
			this._label = label;
		},
		createID: function () {
			return this._label + (++this._index);
		}
	}),
	NavNode: Class.create({
		initialize: function (ID, parentNode, _opt) {
			var opt = _opt || {};
			this.ID = ID;
			this.parentNodes = $A(parentNode);
			this.childNodes = $A(opt.childNodes);
		},
		getID: function () {
			return this.ID;
		},
		_addChild: function (childNode) {
			this.childNodes = this.childNodes.concat(childNode);
		},
		_addParent: function (parentNode) {
			this.parentNodes = this.parentNodes.concat(parentNode);
		},
		linkAsChild: function (childNode) {
			if (!childNode) return;
			this._addChild(childNode);
			childNode._addParent(this);
		},
		_compactNodeList: function (nodeList) {
			var tabsElement = new GUI.TabsElement();
			return nodeList.inject({ nodeList: [], navElementList: [] }, function (compact, node) {
				var tabContext = tabsElement.getTabContext({ wmElement: $(node.getID()) });
				if (tabContext) { // wmElement maybe undefined.
					compact.nodeList.push(node);
					compact.navElementList.push(tabContext.tabNavElement);
				}
				return compact;
			});
		},
		_getElementList: function (listName) {
			var compact = this._compactNodeList(this[listName]);
			this[listName] = compact.nodeList;
			return compact.navElementList;
		},
		_clearAllMarks: function () {
			$$(".ge-nav-parent").invoke("removeClassName", "ge-nav-parent");
			$$(".ge-nav-child").invoke("removeClassName", "ge-nav-child");
			$$(".ge-nav-self").invoke("removeClassName", "ge-nav-self");
		},
		markRelatives: function () {
			this._clearAllMarks();
			var parentElements = this._getElementList("parentNodes");
			parentElements.invoke("addClassName", "ge-nav-parent");
			var childElements = this._getElementList("childNodes");
			childElements.invoke("addClassName", "ge-nav-child");
			if (parentElements.size() || childElements.size()) {
				var tabContext = new GUI.TabsElement().getTabContext({ wmElement: $(this.ID) });
				if (tabContext) tabContext.tabNavElement.addClassName("ge-nav-self");
			}
			$(this.ID).addClassName("");
		}
	}),
	pinNavNode: function (wmElement) {
		var navNode = wmElement.retrieve("navNode");
		if (!navNode) {
			navNode = new GUI.NavNode(wmElement.id);
			wmElement.store("navNode", navNode);
		}
		return navNode;
	},
	AgentDepot: Class.create({
		initialize: function (agentClass, opt) {
			this.agentClass = agentClass;
			this.opt = Object.clone(opt);
			this.agentList = [];
			this.id = GUI.idFactory.createID();
		},
		start: function (hostWindow) {
			var opt = this.opt;
			if (!opt) return undefined;
			if (this.agentList.size()) {
				this.agentList.invoke("dispose"); // 05.02.2011 Ossig Agents before reload.
				this.agentList = [];
			}
			var agent = new this.agentClass(Object.extend(opt || {}, { hostWindow: hostWindow }));
			GUI.assert(!agent.depotID, "agent.depotID conflict");
			agent.depotID = this.id; // 24.06.2011 Ossig Used by mergeAgentList.
			GUI.assert(agent.start, "agent.start missing");
			GUI.assert(agent.stop, "agent.stop missing");
			GUI.assert(agent.dispose, "agent.dispose missing");
			this.agentList.push(agent);
			return agent;
		},
		stop: function () {
			this.opt = undefined;
			if (this.agentList) {
				this.agentList.invoke("stop");
				this.agentList = undefined;
			}
		}
	})
});

Object.extend(GUI, {
	idFactory: new GUI.IDFactory("GUI_")
});

/*
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
	}
})());
*/

// GUIBase: base RemoteGUI and not anymore existing NativeGUI.
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); // 16.10.2011 Ossig undefined when storing SM out of movedata config.
		var footbar = geWindow && 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();
	},
	/*
	getBusySpinner: function(contentWindow) {
	var geWindow = this.getGEWindow(contentWindow); // 30.01.2011 Ossig geWindow undefined when LoginWindow.
	return geWindow ? geWindow.getBusySpinner() : undefined;
	},
	*/
	_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;
		new dtFrame.CountingObserver("GUIBase.GEWindowBase.registerContentWindow", function (w, registerContentWindow) {
			if (w.closed) return true;
			if (!w.document || !w.document.loaded) return false;
			registerContentWindow(w);
			return true;
		} .curry(w, this.registerContentWindow.bind(this)), 0.1, { timeSpan: 10 }); // 21.11.2010 Ossig  In case of external iframes.
		dtFrame.GUI.log("GUIBase.GEWindowBase.setLocation (end)");
	},
	_when: function (queueName, callBack) {
		if (!callBack) return;
		var callBackQueue = this[queueName];
		if (!callBackQueue) {
			callBackQueue = [];
			this[queueName] = callBackQueue;
		}
		callBackQueue.push(callBack);
	},
	whenClose: function (callBack) {
		this._when("_closeCallBackQueue", callBack);
	},
	close: function () {
		var callBackQueue = this._closeCallBackQueue;
		if (!callBackQueue) return;
		this._closeCallBackQueue = undefined;
		callBackQueue.invoke("call");
	}
});

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.findSpeed(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. // 16.10.2011 Ossig Happens
		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;
	},
	getLevelIndex: function (contentWindow) {
		var guiWindow = this._getGUIWindow(contentWindow);
		var workLevel = guiWindow && guiWindow.getWorkLevel();
		return workLevel ? workLevel.levelIndex : -1;
	},
	getWorkNodes: function (contentWindow) {
		var guiWindow = this._getGUIWindow(contentWindow);
		return guiWindow && guiWindow.getWorkNodes();
	},
	getBusySpinner: function (contentWindow) {
		var guiWindow = this._getGUIWindow(contentWindow);
		return guiWindow.getBusySpinner();
	},
	getGUIOpt: function (contentWindow) {
		if (!GUI.options.cmsMode) return undefined;
		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.closeFrame(); // 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.closeFrame(); // w.close(); // 06.12.2009 Ossig close depends on close-button, doese not work for embedded windows.
	},
	closeLevel: function (contentWindow) {
		var w = this._getGUIWindow(contentWindow);
		if (!w) return;
		w.closeLevel();
	},
	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;
	}, */
	startAgentList: function (contentWindow) {
		var w = this._getGUIWindow(contentWindow);
		if (!w) return;
		return w.startAgentList(contentWindow);
	},
	/*
	mergeAgentList: function(contentWindow, agentList) {
	var w = this._getGUIWindow(contentWindow);
	if (!w) return;
	return w.mergeAgentList(contentWindow, agentList);
	},
	*/
	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;
			*/
			if (opt.left >= 160 && opt.left < 250) { // 19.10.2006 Ossig IE7 correction.
				opt.width += opt.left - 250;
				opt.left = 0;
			}
			/*
			// 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.modalPopupWindow ? !opt.embedded : false; //  GUI.options.workTabs && GUI.options.modalPopupWindow ? !opt.embedded : false;

			var w = (function () {
				var wm = (opt && opt.wm) || GUI.metaWM.getWM(workLevel);
				var w = wm.getByName(sName);
				if (w && !w.embedded) {
					/*
					var options = w.options || {};
					var rect = { top: options.top, left: options.left, width: options.width, height: options.height };
					var iFrameElement = w.contentIFrame();
					*/
					var elementLayout = w.element && w.element.getLayout();
					var rect = elementLayout && {
						top: elementLayout.get("top"),
						left: elementLayout.get("left"),
						width: elementLayout.get("width"),
						height: elementLayout.get("height"),
						smartpos: false
					};
					if (rect) Object.extend(opt, rect);
					// GUI.log("URLWindow: purge ", sName, ", rect=", Object.inspect($H(rect)), ", lRect=", Object.inspect($H(lRect)));
					w.destroy();
				}
				return 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; // already assigned above.
		},
		close: function ($super) {
			$super();
			if (!this._w) return;
			this._w.closeFrame(); //  this._w.destroy(); // this._w.close(); // 06.12.2009 Ossig close depends on close-button, doese not work for embedded windows.
			this._w = undefined;
			GUI.log("GEWindow closed (RemoteGUI).");
		},
		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;
		}, /*
		getBusySpinner: function () {
			var w = this._w;
			return w.getBusySpinner();
		}, */
		registerContentWindow: function (contentFrame) {
			this._w.registerContentWindow(contentFrame);
		},
		setLocation: function ($super, sURL, contentFrame, openerWindow) {
			var w = this._w;
			GUI.assert(w);
			if (w) {
				sURL = GUI.URLWindow.filterURL(sURL, w.getQueryParams());
			}
			var result = $super(sURL, contentFrame, openerWindow);
			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);
		},
		whenContentLoad: function (callback) {
			var w = this._w;
			if (!w) return;
			w.whenContentLoad(callback);
		},
		pushAgent: function (agentClass, ownerWindow, opt) {
			var w = this._w;
			if (!w) return;
			var agentDepot = new GUI.AgentDepot(agentClass, Object.extend(opt || {}, { ownerWindow: ownerWindow }));
			w.pushAgent(agentDepot);
		},
		getWorkNodes: function (contentWindow) {
			var w = this._w;
			if (!w) return;
			return w.getWorkNodes();
		}
	})
});

// var remoteGUI = new RemoteGUI();

var NavTree = Class.create({
	// MenuNode, FrameSearchNode, FrameEditnode, [FrameExtraNode]
	initialize: function () {
		this._elementNodeMap = $H();
		this._idNodeMap = $H();
	},
	addNode: function (node) {
		var id = node.getID();
		if (id) this._idNodeMap.set(id, node);
		var element = node.element;
		if (element) this._elementNodeMap.set(element, node);
	},
	getNode: function (opt) {
		var node;
		var element = opt.element;
		if (element) {
			node = this._elementNodeMap.get(element);
			if (node) return node;
		}
		var id = opt.id;
		if (id) {
			node = this._idNodeMap.get(id);
			if (node) return node;
		}
		return undefined;
	}
})

Object.extend(NavTree, {
	NavID: Class.create({
		_navIndex: 0,
		createID: function () {
			return "navID" + (++this._navIndex);
		}
	}),
	NavNode: Class.create({
		_navID: undefined, // static
		initialize: function () {
			if (!this._navID)
				this._navID = new NavTree.NavID();
		},
		createNavID: function () {
			return this._navID.createID();
		},
		initialize: function (element, parentNode, childNodeList) {
			this._element = element;
			this._id = this.createNavID();
			this._parentNode = parentNode;
			this._childNodeList = $A(childnodeList);
		},
		getElement: function () {
			return this._element;
		},
		getID: function () {
			return this._id;
		},
		getParentNode: function () {
			return this._parentNode;
		},
		addChildNode: function (node) {
			this._childNodeList.push(node);
		},
		toJSON: function () {
		}
	})
});

Object.extend(NavTree, {
	FrameEditNode: Class.create(NavTree.NavNode, {
	})
});

