]+>/gi, "");
+}
+
+qx.Class.startsWith = function(fullstr, substr) {
+ return !fullstr.indexOf(substr);
+}
+
+qx.Class.endsWith = function(fullstr, substr) {
+ return fullstr.lastIndexOf(substr) === fullstr.length-substr.length;
+}
+
+qx.Class.pad = function(str, length, ch)
+{
+ if (typeof ch === "undefined") {
+ ch = "0";
+ }
+
+ var temp = "";
+
+ for (var i=length, l=str.length; l " + vUri);
+ }
+
+ return vUri;
+}
+
+qx.Proto._computePath = function(vPath, vForce)
+{
+ switch(vPath.charAt(0))
+ {
+ case "/":
+ case ".":
+ return vPath;
+
+ default:
+ if (qx.lang.String.startsWith(vPath, qx.net.Protocol.URI_HTTP) || qx.lang.String.startsWith(vPath, qx.net.Protocol.URI_HTTPS) || qx.lang.String.startsWith(vPath, qx.net.Protocol.URI_FILE)) {
+ return vPath;
+ }
+
+ var vAlias = vPath.substring(0, vPath.indexOf("/"));
+ var vResolved = this._aliases[vAlias];
+
+ if (qx.util.Validation.isValidString(vResolved)) {
+ return vResolved + vPath.substring(vAlias.length);
+ }
+
+ return vPath;
+ }
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this._aliases = null;
+ this._uris = null;
+
+ return qx.core.Target.prototype.dispose.call(this);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/AppearanceManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/AppearanceManager.js
new file mode 100644
index 0000000000..680bd09073
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/AppearanceManager.js
@@ -0,0 +1,139 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.manager.object.AppearanceManager", qx.manager.object.ObjectManager,
+function() {
+ qx.manager.object.ObjectManager.call(this);
+
+ // Themes
+ this._appearanceThemes = {};
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFAULT SETTINGS
+---------------------------------------------------------------------------
+*/
+
+qx.Settings.setDefault("appearanceTheme", "qx.theme.appearance.Classic");
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "appearanceTheme", type : "object", allowNull : false, instance : "qx.renderer.theme.AppearanceTheme" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTRATION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.registerAppearanceTheme = function(vThemeClass)
+{
+ this._appearanceThemes[vThemeClass.classname] = vThemeClass;
+
+ if (vThemeClass.classname == this.getSetting("appearanceTheme")) {
+ this.setAppearanceTheme(vThemeClass.getInstance());
+ }
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyAppearanceTheme = function(propValue, propOldValue, propData)
+{
+ var vComp = qx.core.Init.getInstance().getComponent();
+
+ if (vComp && vComp.isUiReady()) {
+ qx.ui.core.ClientDocument.getInstance()._recursiveAppearanceThemeUpdate(propValue, propOldValue);
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ // Themes
+ this._appearanceThemes = null;
+
+ return qx.manager.object.ObjectManager.prototype.dispose.call(this);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ColorManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ColorManager.js
new file mode 100644
index 0000000000..6eb4038bd8
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ColorManager.js
@@ -0,0 +1,227 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#optional(qx.ui.form.Button)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.manager.object.ColorManager", qx.manager.object.ObjectManager,
+function()
+{
+ qx.manager.object.ObjectManager.call(this);
+
+ // Themes
+ this._colorThemes = {};
+
+ // Contains the qx.renderer.color.ColorObjects which
+ // represent a themed color.
+ this._dependentObjects = {};
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFAULT SETTINGS
+---------------------------------------------------------------------------
+*/
+
+qx.Settings.setDefault("colorTheme", "qx.theme.color.WindowsRoyale");
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "colorTheme", type : "object", allowNull : false, instance : "qx.renderer.theme.ColorTheme" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTRATION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.registerColorTheme = function(vThemeClass)
+{
+ this._colorThemes[vThemeClass.classname] = vThemeClass;
+
+ if (vThemeClass.classname == this.getSetting("colorTheme")) {
+ this.setColorTheme(vThemeClass.getInstance());
+ }
+}
+
+qx.Proto.setColorThemeById = function(vId) {
+ this.setColorTheme(this._colorThemes[vId].getInstance());
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PUBLIC METHODS FOR qx.renderer.color.ColorOBJECTS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.add = function(oObject)
+{
+ var vValue = oObject.getValue();
+
+ this._objects[vValue] = oObject;
+
+ if (oObject.isThemedColor()) {
+ this._dependentObjects[vValue] = oObject;
+ }
+}
+
+qx.Proto.remove = function(oObject)
+{
+ var vValue = oObject.getValue();
+
+ delete this._objects[vValue];
+ delete this._dependentObjects[vValue];
+}
+
+qx.Proto.has = function(vValue) {
+ return this._objects[vValue] != null;
+}
+
+qx.Proto.get = function(vValue) {
+ return this._objects[vValue];
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyColorTheme = function(propValue, propOldValue, propData)
+{
+ propValue.compile();
+
+ for (var i in this._dependentObjects) {
+ this._dependentObjects[i]._updateTheme(propValue);
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITY
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.createThemeList = function(vParent, xCor, yCor)
+{
+ var vButton;
+ var vThemes = this._colorThemes;
+ var vIcon = "icon/16/colors.png";
+ var vPrefix = "Color Theme: ";
+ var vEvent = "execute";
+
+ for (var vId in vThemes)
+ {
+ var vObj = vThemes[vId].getInstance();
+ var vButton = new qx.ui.form.Button(vPrefix + vObj.getTitle(), vIcon);
+
+ vButton.setLocation(xCor, yCor);
+ vButton.addEventListener(vEvent, new Function("qx.manager.object.ColorManager.getInstance().setColorThemeById('" + vId + "')"));
+
+ vParent.add(vButton);
+
+ yCor += 30;
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ // Themes
+ this._colorThemes = null;
+
+ // Cleanup dependent objects
+ for (var i in this._dependentObjects) {
+ delete this._dependentObjects[i];
+ }
+
+ delete this._dependentObjects;
+
+ return qx.manager.object.ObjectManager.prototype.dispose.call(this);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/IframeManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/IframeManager.js
new file mode 100644
index 0000000000..79695169b2
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/IframeManager.js
@@ -0,0 +1,75 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/**
+ * This singleton manages multiple instances of qx.ui.embed.Iframe.
+ *
+ * The problem: When dragging over an iframe then all mouse events will be
+ * passed to the document of the iframe, not the main document.
+ *
+ * The solution: In order to be able to track mouse events over iframes, this
+ * manager will block all iframes during a drag with a glasspane.
+ */
+qx.OO.defineClass("qx.manager.object.IframeManager", qx.manager.object.ObjectManager,
+function(){
+ qx.manager.object.ObjectManager.call(this);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.handleMouseDown = function(evt) {
+ var iframeMap = this.getAll();
+
+ for (var key in iframeMap) {
+ var iframe = iframeMap[key];
+ iframe.block();
+ }
+}
+
+qx.Proto.handleMouseUp = function(evt) {
+ var iframeMap = this.getAll();
+
+ for (var key in iframeMap) {
+ var iframe = iframeMap[key];
+ iframe.release();
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ImageManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ImageManager.js
new file mode 100644
index 0000000000..f1fbfe6fb9
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ImageManager.js
@@ -0,0 +1,305 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#optional(qx.ui.form.Button)
+
+************************************************************************ */
+
+/*!
+ This singleton manage the global image path (prefix) and allowes themed icons.
+*/
+qx.OO.defineClass("qx.manager.object.ImageManager", qx.manager.object.ObjectManager,
+function()
+{
+ qx.manager.object.ObjectManager.call(this);
+
+ // Themes
+ this._iconThemes = {};
+ this._widgetThemes = {};
+
+ // Contains known image sources (all of them, if loaded or not)
+ // The value is a number which represents the number of image
+ // instances which use this source
+ this._sources = {};
+
+ // Change event connection to AliasManager
+ qx.manager.object.AliasManager.getInstance().addEventListener("change", this._onaliaschange, this);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFAULT SETTINGS
+---------------------------------------------------------------------------
+*/
+
+qx.Settings.setDefault("iconTheme", "qx.theme.icon.CrystalSvg");
+qx.Settings.setDefault("widgetTheme", "qx.theme.widget.Windows");
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "iconTheme", type : "object", instance : "qx.renderer.theme.IconTheme" });
+qx.OO.addProperty({ name : "widgetTheme", type : "object", instance : "qx.renderer.theme.WidgetTheme" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTRATION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.registerIconTheme = function(vThemeClass)
+{
+ this._iconThemes[vThemeClass.classname] = vThemeClass;
+
+ if (vThemeClass.classname == this.getSetting("iconTheme")) {
+ this.setIconTheme(vThemeClass.getInstance());
+ }
+}
+
+qx.Proto.registerWidgetTheme = function(vThemeClass)
+{
+ this._widgetThemes[vThemeClass.classname] = vThemeClass;
+
+ if (vThemeClass.classname == this.getSetting("widgetTheme")) {
+ this.setWidgetTheme(vThemeClass.getInstance());
+ }
+}
+
+qx.Proto.setIconThemeById = function(vId) {
+ this.setIconTheme(this._iconThemes[vId].getInstance());
+}
+
+qx.Proto.setWidgetThemeById = function(vId) {
+ this.setWidgetTheme(this._widgetThemes[vId].getInstance());
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onaliaschange = function() {
+ this._updateImages();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyIconTheme = function(propValue, propOldValue, propData)
+{
+ propValue ? qx.manager.object.AliasManager.getInstance().add("icon", propValue.getSetting("imageUri")) : qx.manager.object.AliasManager.getInstance().remove("icon");
+ return true;
+}
+
+qx.Proto._modifyWidgetTheme = function(propValue, propOldValue, propData)
+{
+ propValue ? qx.manager.object.AliasManager.getInstance().add("widget", propValue.getSetting("imageUri")) : qx.manager.object.AliasManager.getInstance().remove("widget");
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PRELOAD API
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getPreloadImageList = function()
+{
+ var vPreload = {};
+
+ for (var vSource in this._sources)
+ {
+ if (this._sources[vSource]) {
+ vPreload[vSource] = true;
+ }
+ }
+
+ return vPreload;
+}
+
+qx.Proto.getPostPreloadImageList = function()
+{
+ var vPreload = {};
+
+ for (var vSource in this._sources)
+ {
+ if (!this._sources[vSource]) {
+ vPreload[vSource] = true;
+ }
+ }
+
+ return vPreload;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INTERNAL HELPER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._updateImages = function()
+{
+ var vAll = this.getAll();
+ var vPreMgr = qx.manager.object.ImagePreloaderManager.getInstance();
+ var vAliasMgr = qx.manager.object.AliasManager.getInstance();
+ var vObject;
+
+ // Recreate preloader of affected images
+ for (var vHashCode in vAll)
+ {
+ vObject = vAll[vHashCode];
+ vObject.setPreloader(vPreMgr.create(vAliasMgr.resolvePath(vObject.getSource(), true)));
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITY
+---------------------------------------------------------------------------
+*/
+
+// TODO: rename to createIconThemeList
+qx.Proto.createThemeList = function(vParent, xCor, yCor)
+{
+ var vButton;
+ var vThemes = this._iconThemes;
+ var vIcon = "icon/16/icons.png";
+ var vPrefix = "Icon Theme: ";
+ var vEvent = "execute";
+
+ for (var vId in vThemes)
+ {
+ var vObj = vThemes[vId].getInstance();
+ var vButton = new qx.ui.form.Button(vPrefix + vObj.getTitle(), vIcon);
+
+ vButton.setLocation(xCor, yCor);
+ vButton.addEventListener(vEvent, new Function("qx.manager.object.ImageManager.getInstance().setIconThemeById('" + vId + "')"));
+
+ vParent.add(vButton);
+
+ yCor += 30;
+ }
+}
+
+qx.Proto.preload = function(vPath) {
+ qx.manager.object.ImagePreloaderManager.getInstance().create(qx.manager.object.AliasManager.getInstance().resolvePath(vPath));
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ // Change event connection to AliasManager
+ qx.manager.object.AliasManager.getInstance().removeEventListener("change", this._onaliaschange, this);
+
+ // Delete counter field
+ this._sources = null;
+
+ // Themes
+ this._iconThemes = null;
+ this._widgetThemes = null;
+
+ return qx.manager.object.ObjectManager.prototype.dispose.call(this);
+}
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ImagePreloaderManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ImagePreloaderManager.js
new file mode 100644
index 0000000000..8c0d68eb6b
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ImagePreloaderManager.js
@@ -0,0 +1,82 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+
+************************************************************************ */
+
+/*!
+ This singleton manage all qx.io.image.Preloader instances.
+*/
+qx.OO.defineClass("qx.manager.object.ImagePreloaderManager", qx.manager.object.ObjectManager,
+function() {
+ qx.manager.object.ObjectManager.call(this);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.add = function(vObject) {
+ this._objects[vObject.getUri()] = vObject;
+}
+
+qx.Proto.remove = function(vObject) {
+ delete this._objects[vObject.getUri()];
+}
+
+qx.Proto.has = function(vSource) {
+ return this._objects[vSource] != null;
+}
+
+qx.Proto.get = function(vSource) {
+ return this._objects[vSource];
+}
+
+qx.Proto.create = function(vSource)
+{
+ if (this._objects[vSource]) {
+ return this._objects[vSource];
+ }
+
+ return new qx.io.image.Preloader(vSource);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/MenuManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/MenuManager.js
new file mode 100644
index 0000000000..b7914b4bcf
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/MenuManager.js
@@ -0,0 +1,92 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_menu)
+
+************************************************************************ */
+
+/*!
+ This singleton manages multiple instances of qx.ui.menu.Menu and their state.
+*/
+qx.OO.defineClass("qx.manager.object.MenuManager", qx.manager.object.ObjectManager,
+function(){
+ qx.manager.object.ObjectManager.call(this);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.update = function(vTarget, vEventName)
+{
+ var vMenu, vHashCode;
+ var vAll = this.getAll();
+
+ for (vHashCode in vAll)
+ {
+ vMenu = vAll[vHashCode];
+
+ if(!vMenu.getAutoHide()) {
+ continue;
+ }
+
+ if (vTarget && vTarget.getMenu && vTarget.getMenu()) {
+ continue;
+ }
+
+ // Hide on global events (mouseup, window focus, window blur, ...)
+ if (!vTarget)
+ {
+ vMenu.hide();
+ continue;
+ }
+
+ // Hide only if the target is not a button inside this
+ // or any sub menu and is not the opener
+ if (vMenu.getOpener() !== vTarget && ((vTarget && !vMenu.isSubButton(vTarget)) || vEventName !== "mousedown"))
+ {
+ vMenu.hide();
+ continue;
+ }
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ObjectManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ObjectManager.js
new file mode 100644
index 0000000000..c1160ab64b
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ObjectManager.js
@@ -0,0 +1,117 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+/*!
+ This class allows basic managment of assigned objects.
+*/
+qx.OO.defineClass("qx.manager.object.ObjectManager", qx.core.Target,
+function()
+{
+ qx.core.Target.call(this);
+
+ this._objects = {};
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ USER API
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.add = function(vObject)
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this._objects[vObject.toHashCode()] = vObject;
+ return true;
+}
+
+qx.Proto.remove = function(vObject)
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ delete this._objects[vObject.toHashCode()];
+ return true;
+}
+
+qx.Proto.has = function(vObject) {
+ return this._objects[vObject.toHashCode()] != null;
+}
+
+qx.Proto.get = function(vObject) {
+ return this._objects[vObject.toHashCode()];
+}
+
+qx.Proto.getAll = function() {
+ return this._objects;
+}
+
+qx.Proto.enableAll = function()
+{
+ for (var vHashCode in this._objects) {
+ this._objects[vHashCode].setEnabled(true);
+ };
+};
+
+qx.Proto.disableAll = function()
+{
+ for (var vHashCode in this._objects) {
+ this._objects[vHashCode].setEnabled(false);
+ };
+};
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if(this.getDisposed()) {
+ return;
+ }
+
+ if (this._objects)
+ {
+ for (var i in this._objects) {
+ delete this._objects[i];
+ }
+
+ delete this._objects;
+ }
+
+ return qx.core.Target.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/PopupManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/PopupManager.js
new file mode 100644
index 0000000000..218c988c83
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/PopupManager.js
@@ -0,0 +1,77 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_popup)
+
+************************************************************************ */
+
+/*!
+ This singleton is used to manager multiple instances of popups and their state.
+*/
+qx.OO.defineClass("qx.manager.object.PopupManager", qx.manager.object.ObjectManager,
+function() {
+ qx.manager.object.ObjectManager.call(this);
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.update = function(vTarget)
+{
+ // be sure that target is correctly set (needed for contains() later)
+ if (!(vTarget instanceof qx.ui.core.Widget)) {
+ vTarget = null;
+ }
+
+ var vPopup, vHashCode;
+ var vAll = this.getAll();
+
+ for (vHashCode in vAll)
+ {
+ vPopup = vAll[vHashCode];
+
+ if(!vPopup.getAutoHide() || vTarget == vPopup || vPopup.contains(vTarget)) {
+ continue;
+ }
+
+ vPopup.hide();
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ToolTipManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ToolTipManager.js
new file mode 100644
index 0000000000..f29be08eda
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/ToolTipManager.js
@@ -0,0 +1,191 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_popup)
+
+************************************************************************ */
+
+/*!
+ This manages ToolTip instances
+*/
+qx.OO.defineClass("qx.manager.object.ToolTipManager", qx.manager.object.ObjectManager,
+function() {
+ qx.manager.object.ObjectManager.call(this);
+});
+
+qx.OO.addProperty({ name : "currentToolTip", type : "object", instance : "qx.ui.popup.ToolTip" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyCurrentToolTip = function(propValue, propOldValue, propData)
+{
+ // Return if the new tooltip is a child of the old one
+ if(propOldValue && propOldValue.contains(propValue)) {
+ return;
+ }
+
+ // If old tooltip existing, hide it and clear widget binding
+ if(propOldValue)
+ {
+ propOldValue.hide();
+
+ propOldValue._stopShowTimer();
+ propOldValue._stopHideTimer();
+ }
+
+ // If new tooltip is not null, set it up and start the timer
+ if(propValue) {
+ propValue._startShowTimer();
+ }
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT INTERFACE: MOUSE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.handleMouseOver = function(e)
+{
+ var vTarget = e.getTarget();
+ var vToolTip;
+
+ // Allows us to use DOM Nodes as tooltip target :)
+ if (!(vTarget instanceof qx.ui.core.Widget) && vTarget.nodeType == 1) {
+ vTarget = qx.event.handler.EventHandler.getTargetObject(vTarget);
+ }
+
+ //Search first parent which has a tooltip
+ while(vTarget != null && !(vToolTip = vTarget.getToolTip())) {
+ vTarget = vTarget.getParent();
+ }
+
+ // Bind tooltip to widget
+ if (vToolTip != null) {
+ vToolTip.setBoundToWidget(vTarget);
+ }
+
+ // Set Property
+ this.setCurrentToolTip(vToolTip);
+}
+
+qx.Proto.handleMouseOut = function(e)
+{
+ var vTarget = e.getTarget();
+ var vRelatedTarget = e.getRelatedTarget();
+
+ var vToolTip = this.getCurrentToolTip();
+
+ // If there was a tooltip and
+ // - the destination target is the current tooltip
+ // or
+ // - the current tooltip contains the destination target
+ if(vToolTip && (vRelatedTarget == vToolTip || vToolTip.contains(vRelatedTarget))) {
+ return;
+ }
+
+ // If the destination target exists and the target contains it
+ if(vRelatedTarget && vTarget && vTarget.contains(vRelatedTarget)) {
+ return;
+ }
+
+ // If there was a tooltip and there is no new one
+ if(vToolTip && !vRelatedTarget) {
+ this.setCurrentToolTip(null);
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT INTERFACE: FOCUS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.handleFocus = function(e)
+{
+ var vTarget = e.getTarget();
+ var vToolTip = vTarget.getToolTip();
+
+ // Only set new tooltip if focus widget
+ // has one
+ if(vToolTip != null)
+ {
+ // Bind tooltip to widget
+ vToolTip.setBoundToWidget(vTarget);
+
+ // Set Property
+ this.setCurrentToolTip(vToolTip);
+ }
+}
+
+qx.Proto.handleBlur = function(e)
+{
+ var vTarget = e.getTarget();
+
+ if(!vTarget) {
+ return;
+ }
+
+ var vToolTip = this.getCurrentToolTip();
+
+ // Only set to null if blured widget is the
+ // one which has created the current tooltip
+ if(vToolTip && vToolTip == vTarget.getToolTip()) {
+ this.setCurrentToolTip(null);
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/WindowManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/WindowManager.js
new file mode 100644
index 0000000000..96e13acd4d
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/object/WindowManager.js
@@ -0,0 +1,158 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_window)
+
+************************************************************************ */
+
+/*!
+ This singleton manages qx.ui.window.Windows
+*/
+qx.OO.defineClass("qx.manager.object.WindowManager", qx.manager.object.ObjectManager,
+function() {
+ qx.manager.object.ObjectManager.call(this);
+});
+
+qx.OO.addProperty({ name : "activeWindow", type : "object" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyActiveWindow = function(propValue, propOldValue, propData)
+{
+ qx.manager.object.PopupManager.getInstance().update();
+
+ if (propOldValue) {
+ propOldValue.setActive(false);
+ }
+
+ if (propValue) {
+ propValue.setActive(true);
+ }
+
+ if (propOldValue && propOldValue.getModal()) {
+ propOldValue.getTopLevelWidget().release(propOldValue);
+ }
+
+ if (propValue && propValue.getModal()) {
+ propValue.getTopLevelWidget().block(propValue);
+ }
+
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.update = function(oTarget)
+{
+ var vWindow, vHashCode;
+ var vAll = this.getAll();
+
+ for (var vHashCode in vAll)
+ {
+ vWindow = vAll[vHashCode];
+
+ if(!vWindow.getAutoHide()) {
+ continue;
+ }
+
+ vWindow.hide();
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MANAGER INTERFACE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.compareWindows = function(w1, w2)
+{
+ switch(w1.getWindowManager().getActiveWindow())
+ {
+ case w1:
+ return 1;
+
+ case w2:
+ return -1;
+ }
+
+ return w1.getZIndex() - w2.getZIndex();
+}
+
+qx.Proto.add = function(vWindow)
+{
+ qx.manager.object.ObjectManager.prototype.add.call(this, vWindow);
+
+ // this.debug("Add: " + vWindow);
+ this.setActiveWindow(vWindow);
+}
+
+qx.Proto.remove = function(vWindow)
+{
+ qx.manager.object.ObjectManager.prototype.remove.call(this, vWindow);
+
+ // this.debug("Remove: " + vWindow);
+
+ if (this.getActiveWindow() == vWindow)
+ {
+ var a = [];
+ for (var i in this._objects) {
+ a.push(this._objects[i]);
+ }
+
+ var l = a.length;
+
+ if (l==0)
+ {
+ this.setActiveWindow(null);
+ }
+ else if (l==1)
+ {
+ this.setActiveWindow(a[0]);
+ }
+ else if (l>1)
+ {
+ a.sort(this.compareWindows);
+ this.setActiveWindow(a[l-1]);
+ }
+ }
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/DomSelectionManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/DomSelectionManager.js
new file mode 100644
index 0000000000..3205dc40ea
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/DomSelectionManager.js
@@ -0,0 +1,242 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.manager.selection.DomSelectionManager", qx.manager.selection.SelectionManager,
+function(vBoundedWidget)
+{
+ qx.manager.selection.SelectionManager.call(this, vBoundedWidget);
+
+ // the children does not fire onmouseover events so we could
+ // not enable this and make it functional
+ this.setDragSelection(false);
+
+ this._selectedItems.getItemHashCode = this.getItemHashCode;
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO BOUNDED WIDGET (DOM NODES)
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getItemEnabled = function(oItem) {
+ return true;
+}
+
+qx.Proto.getItemClassName = function(vItem) {
+ return vItem.className || "";
+}
+
+qx.Proto.setItemClassName = function(vItem, vClassName) {
+ return vItem.className = vClassName;
+}
+
+qx.Proto.getItemBaseClassName = function(vItem)
+{
+ var p = vItem.className.split(" ")[0];
+ return p ? p : "Status";
+}
+
+qx.Proto.getNextSibling = function(vItem) {
+ return vItem.nextSibling;
+}
+
+qx.Proto.getPreviousSibling = function(vItem) {
+ return vItem.previousSibling;
+}
+
+qx.Proto.getFirst = function() {
+ return this.getItems()[0];
+}
+
+qx.Proto.getLast = function()
+{
+ var vItems = this.getItems();
+ return vItems[vItems.length-1];
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO ITEM DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getItemLeft = function(vItem) {
+ return vItem.offsetLeft;
+}
+
+qx.Proto.getItemTop = function(vItem) {
+ return vItem.offsetTop;
+}
+
+qx.Proto.getItemWidth = function(vItem) {
+ return vItem.offsetWidth;
+}
+
+qx.Proto.getItemHeight = function(vItem) {
+ return vItem.offsetHeight;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO ITEM PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getItemHashCode = function(oItem)
+{
+ if (oItem._hash) {
+ return oItem._hash;
+ }
+
+ return oItem._hash = qx.core.Object.toHashCode(oItem);
+}
+
+qx.Proto.isBefore = function(vItem1, vItem2)
+{
+ var pa = vItem1.parentNode;
+
+ for (var i=0, l=pa.childNodes.length; i0; i--)
+ {
+ vChild = vParent.childNodes[i];
+
+ if (vFound == false)
+ {
+ if (vChild == vItem) {
+ vFound = true;
+ }
+ }
+ else
+ {
+ if (vChild.offsetLeft == vLeft)
+ {
+ return vChild;
+ }
+ }
+ }
+}
+
+qx.Proto.getUnder = function(vItem)
+{
+ var vParent = vItem.parentNode;
+ var vFound = false;
+ var vLeft = vItem.offsetLeft;
+ var vChild;
+
+ for (var i=0, l=vParent.childNodes.length; i return
+ if (this.getItemSelected(vItem) == vSelected) {
+ return;
+ }
+
+ // Otherwise render new state
+ this.renderItemSelectionState(vItem, vSelected);
+
+ // Add item to selection hash / delete it from there
+ vSelected ? this._selectedItems.add(vItem) : this._selectedItems.remove(vItem);
+
+ // Dispatch change Event
+ this._dispatchChange();
+
+ break;
+
+
+
+ // Multiple item selection is NOT allowed
+ case false:
+ var item0 = this.getSelectedItems()[0];
+
+
+
+ if (vSelected)
+ {
+ // Precheck for any changes
+ var old = item0;
+
+ if (this.isEqual(vItem, old)) {
+ return;
+ }
+
+ // Reset rendering of previous selected item
+ if (old != null) {
+ this.renderItemSelectionState(old, false);
+ }
+
+ // Render new item as selected
+ this.renderItemSelectionState(vItem, true);
+
+ // Reset current selection hash
+ this._selectedItems.removeAll();
+
+ // Add new one
+ this._selectedItems.add(vItem);
+
+ // Dispatch change Event
+ this._dispatchChange();
+ }
+ else
+ {
+ // Pre-check if item is currently selected
+ // Do not allow deselection in single selection mode
+ if (!this.isEqual(item0, vItem))
+ {
+ // Reset rendering as selected item
+ this.renderItemSelectionState(vItem, false);
+
+ // Reset current selection hash
+ this._selectedItems.removeAll();
+
+ // Dispatch change Event
+ this._dispatchChange();
+ }
+ }
+
+ break;
+
+ }
+}
+
+
+
+
+
+
+
+
+/*!
+ Get the selected items (objects)
+*/
+qx.Proto.getSelectedItems = function() {
+ return this._selectedItems.toArray();
+}
+
+qx.Proto.getSelectedItem = function() {
+ return this._selectedItems.getFirst();
+}
+
+/*!
+Select given items
+
+#param vItems[Array of Widgets]: Items to select
+*/
+qx.Proto.setSelectedItems = function(vItems)
+{
+ var oldVal = this._getChangeValue();
+
+ // Temporary disabling of event fire
+ var oldFireChange = this.getFireChange();
+ this.setFireChange(false);
+
+ // Deselect all currently selected items
+ this._deselectAll();
+
+ // Apply new selection
+ var vItem;
+ var vItemLength = vItems.length;
+
+ for (var i=0; i" + vItem2.toText());
+ // this.debug("SELECT_RANGE: " + vItem1.pos + "<->" + vItem2.pos);
+
+ // Pre-Check a revert call if vItem2 is before vItem1
+ if (this.isBefore(vItem2, vItem1)) {
+ return this._selectItemRange(vItem2, vItem1, vDeselect);
+ }
+
+ // Deselect all
+ if (vDeselect) {
+ this._deselectAll();
+ }
+
+ var vCurrentItem = vItem1;
+
+ while (vCurrentItem != null)
+ {
+ if (this.getItemEnabled(vCurrentItem))
+ {
+ // Add item to selection
+ this._selectedItems.add(vCurrentItem);
+
+ // Render new state for item
+ this.renderItemSelectionState(vCurrentItem, true);
+ }
+
+ // Stop here if we reached target item
+ if (this.isEqual(vCurrentItem, vItem2)) {
+ break;
+ }
+
+ // Get next item
+ vCurrentItem = this.getNext(vCurrentItem);
+ }
+
+ return true;
+}
+
+/*!
+Internal method for deselection of ranges.
+
+#param vItem1[qx.ui.core.Widget]: Start item
+#param vItem2[qx.ui.core.Widget]: Stop item
+*/
+qx.Proto._deselectItemRange = function(vItem1, vItem2)
+{
+ // Pre-Check a revert call if vItem2 is before vItem1
+ if (this.isBefore(vItem2, vItem1)) {
+ return this._deselectItemRange(vItem2, vItem1);
+ }
+
+ var vCurrentItem = vItem1;
+
+ while (vCurrentItem != null)
+ {
+ // Add item to selection
+ this._selectedItems.remove(vCurrentItem);
+
+ // Render new state for item
+ this.renderItemSelectionState(vCurrentItem, false);
+
+ // Stop here if we reached target item
+ if (this.isEqual(vCurrentItem, vItem2)) {
+ break;
+ }
+
+ // Get next item
+ vCurrentItem = this.getNext(vCurrentItem);
+ }
+}
+
+
+/*
+---------------------------------------------------------------------------
+ MOUSE EVENT HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._activeDragSession = false;
+
+qx.Proto.handleMouseDown = function(vItem, e)
+{
+ // Only allow left and right button
+ if (!e.isLeftButtonPressed() && !e.isRightButtonPressed()) {
+ return;
+ }
+
+ // Keep selection on right click on already selected item
+ if (e.isRightButtonPressed() && this.getItemSelected(vItem)) {
+ return;
+ }
+
+ // Shift Key
+ // or
+ // Click on an unseleted item (without Strg)
+ if (e.getShiftKey() || this.getDragSelection() || (!this.getItemSelected(vItem) && !e.getCtrlKey()))
+ {
+ // Handle event
+ this._onmouseevent(vItem, e);
+ }
+ else
+ {
+ // Update lead item
+ this.setLeadItem(vItem);
+ }
+
+
+ // Handle dragging
+ this._activeDragSession = this.getDragSelection();
+
+ if (this._activeDragSession)
+ {
+ // Add mouseup listener and register as capture widget
+ this.getBoundedWidget().addEventListener("mouseup", this._ondragup, this);
+ this.getBoundedWidget().setCapture(true);
+ }
+}
+
+qx.Proto._ondragup = function(e)
+{
+ this.getBoundedWidget().removeEventListener("mouseup", this._ondragup, this);
+ this.getBoundedWidget().setCapture(false);
+ this._activeDragSession = false;
+}
+
+qx.Proto.handleMouseUp = function(vItem, e)
+{
+ if (!e.isLeftButtonPressed()) {
+ return;
+ }
+
+ if (e.getCtrlKey() || this.getItemSelected(vItem) && !this._activeDragSession) {
+ this._onmouseevent(vItem, e);
+ }
+
+ if (this._activeDragSession)
+ {
+ this._activeDragSession = false;
+ this.getBoundedWidget().setCapture(false);
+ }
+}
+
+qx.Proto.handleMouseOver = function(oItem, e)
+{
+ if (! this.getDragSelection() || !this._activeDragSession) {
+ return;
+ }
+
+ this._onmouseevent(oItem, e, true);
+}
+
+// currently unused placeholder
+qx.Proto.handleClick = function(vItem, e) {}
+
+// currently unused placeholder
+qx.Proto.handleDblClick = function(vItem, e) {}
+
+
+/*!
+Internal handler for all mouse events bound to this manager.
+*/
+qx.Proto._onmouseevent = function(oItem, e, bOver)
+{
+ if (!this.getItemEnabled(oItem)) {
+ return;
+ }
+
+ // ********************************************************************
+ // Init
+ // ********************************************************************
+
+ // Cache current (old) values
+ var oldVal = this._getChangeValue();
+ var oldLead = this.getLeadItem();
+
+ // Temporary disabling of event fire
+ var oldFireChange = this.getFireChange();
+ this.setFireChange(false);
+
+ // Cache selection and count
+ var selectedItems = this.getSelectedItems();
+ var selectedCount = selectedItems.length;
+
+ // Update lead item
+ this.setLeadItem(oItem);
+
+ // Cache current anchor item
+ var currentAnchorItem = this.getAnchorItem();
+
+ // Cache keys pressed
+ var vCtrlKey = e.getCtrlKey();
+ var vShiftKey = e.getShiftKey();
+
+
+ // ********************************************************************
+ // Do we need to update the anchor?
+ // ********************************************************************
+
+ if (!currentAnchorItem || selectedCount == 0 || (vCtrlKey && !vShiftKey && this.getMultiSelection() && !this.getDragSelection()))
+ {
+ this.setAnchorItem(oItem);
+ currentAnchorItem = oItem;
+ }
+
+
+
+ // ********************************************************************
+ // Mode #1: Replace current selection with new one
+ // ********************************************************************
+ if ((!vCtrlKey && !vShiftKey && !this._activeDragSession || !this.getMultiSelection()))
+ {
+ if (!this.getItemEnabled(oItem)) {
+ return;
+ }
+
+ // Remove current selection
+ this._deselectAll();
+
+ // Update anchor item
+ this.setAnchorItem(oItem);
+
+ if (this._activeDragSession)
+ {
+ // a little bit hacky, but seems to be a fast way to detect if we slide to top or to bottom
+ this.scrollItemIntoView((this.getBoundedWidget().getScrollTop() > (this.getItemTop(oItem)-1) ? this.getPrevious(oItem) : this.getNext(oItem)) || oItem);
+ }
+
+ if (!this.getItemSelected(oItem)) {
+ this.renderItemSelectionState(oItem, true);
+ }
+
+ // Clear up and add new one
+ //this._selectedItems.removeAll();
+ this._selectedItems.add(oItem);
+
+ this._addToCurrentSelection = true;
+ }
+
+
+ // ********************************************************************
+ // Mode #2: (De-)Select item range in mouse drag session
+ // ********************************************************************
+ else if (this._activeDragSession && bOver)
+ {
+ if (oldLead) {
+ this._deselectItemRange(currentAnchorItem, oldLead);
+ }
+
+ // Drag down
+ if (this.isBefore(currentAnchorItem, oItem))
+ {
+ if (this._addToCurrentSelection)
+ {
+ this._selectItemRange(currentAnchorItem, oItem, false);
+ }
+ else
+ {
+ this._deselectItemRange(currentAnchorItem, oItem);
+ }
+ }
+
+ // Drag up
+ else
+ {
+ if (this._addToCurrentSelection)
+ {
+ this._selectItemRange(oItem, currentAnchorItem, false);
+ }
+ else
+ {
+ this._deselectItemRange(oItem, currentAnchorItem);
+ }
+ }
+
+ // a little bit hacky, but seems to be a fast way to detect if we slide to top or to bottom
+ this.scrollItemIntoView((this.getBoundedWidget().getScrollTop() > (this.getItemTop(oItem)-1) ? this.getPrevious(oItem) : this.getNext(oItem)) || oItem);
+ }
+
+
+ // ********************************************************************
+ // Mode #3: Add new item to current selection (ctrl pressed)
+ // ********************************************************************
+ else if (this.getMultiSelection() && vCtrlKey && !vShiftKey)
+ {
+ if (!this._activeDragSession) {
+ this._addToCurrentSelection = !(this.getCanDeselect() && this.getItemSelected(oItem));
+ }
+
+ this.setItemSelected(oItem, this._addToCurrentSelection);
+ this.setAnchorItem(oItem);
+ }
+
+
+ // ********************************************************************
+ // Mode #4: Add new (or continued) range to selection
+ // ********************************************************************
+ else if (this.getMultiSelection() && vCtrlKey && vShiftKey)
+ {
+ if (!this._activeDragSession) {
+ this._addToCurrentSelection = !(this.getCanDeselect() && this.getItemSelected(oItem));
+ }
+
+ if (this._addToCurrentSelection)
+ {
+ this._selectItemRange(currentAnchorItem, oItem, false);
+ }
+ else
+ {
+ this._deselectItemRange(currentAnchorItem, oItem);
+ }
+ }
+
+ // ********************************************************************
+ // Mode #5: Replace selection with new range selection
+ // ********************************************************************
+ else if (this.getMultiSelection() && !vCtrlKey && vShiftKey)
+ {
+ if (this.getCanDeselect())
+ {
+ this._selectItemRange(currentAnchorItem, oItem, true);
+ }
+
+ else
+ {
+ if (oldLead) {
+ this._deselectItemRange(currentAnchorItem, oldLead);
+ }
+
+ this._selectItemRange(currentAnchorItem, oItem, false);
+ }
+ }
+
+
+
+ // Recover change event status
+ this.setFireChange(oldFireChange);
+
+ // Dispatch change Event
+ if(oldFireChange && this._hasChanged(oldVal)) {
+ this._dispatchChange();
+ }
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ KEY EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.handleKeyDown = function(vDomEvent) {
+ this.warn(
+ "qx.manager.selection.SelectionManager.handleKeyDown is deprecated! " +
+ "Use keypress insted and bind it to the onkeypress event."
+ );
+ this.handleKeyPress(vDomEvent);
+}
+
+
+/**
+ * Handles key event to perform selection and navigation
+ *
+ * @param vDomEvent (Element) DOM event object
+ */
+qx.Proto.handleKeyPress = function(vDomEvent)
+{
+ var oldVal = this._getChangeValue();
+
+ // Temporary disabling of event fire
+ var oldFireChange = this.getFireChange();
+ this.setFireChange(false);
+
+ // Ctrl+A: Select all
+ if (vDomEvent.getKeyIdentifier() == "A" && vDomEvent.getCtrlKey())
+ {
+ if (this.getMultiSelection())
+ {
+ this._selectAll();
+
+ // Update lead item to this new last
+ // (or better here: first) selected item
+ this.setLeadItem(this.getFirst());
+ }
+ }
+
+ // Default operation
+ else
+ {
+ var aIndex = this.getAnchorItem();
+ var itemToSelect = this.getItemToSelect(vDomEvent);
+
+ // this.debug("Anchor: " + (aIndex ? aIndex.getLabel() : "null"));
+ // this.debug("ToSelect: " + (itemToSelect ? itemToSelect.getLabel() : "null"));
+
+ if (itemToSelect && this.getItemEnabled(itemToSelect))
+ {
+ // Update lead item to this new last selected item
+ this.setLeadItem(itemToSelect);
+
+ // Scroll new item into view
+ this.scrollItemIntoView(itemToSelect);
+
+ // Stop event handling
+ vDomEvent.preventDefault();
+
+ // Select a range
+ if (vDomEvent.getShiftKey() && this.getMultiSelection())
+ {
+ // Make it a little bit more failsafe:
+ // Set anchor if not given already. Allows us to select
+ // a range without any previous selection.
+ if (aIndex == null) {
+ this.setAnchorItem(itemToSelect);
+ }
+
+ // Select new range (and clear up current selection first)
+ this._selectItemRange(this.getAnchorItem(), itemToSelect, true);
+ }
+ else if (!vDomEvent.getCtrlKey())
+ {
+ // Clear current selection
+ this._deselectAll();
+
+ // Update new item to be selected
+ this.renderItemSelectionState(itemToSelect, true);
+
+ // Add item to new selection
+ this._selectedItems.add(itemToSelect);
+
+ // Update anchor to this new item
+ // (allows following shift range selection)
+ this.setAnchorItem(itemToSelect);
+ }
+ else if (vDomEvent.getKeyIdentifier() == "Space")
+ {
+ if (this._selectedItems.contains(itemToSelect))
+ {
+ // Update new item to be selected
+ this.renderItemSelectionState(itemToSelect, false);
+
+ // Add item to new selection
+ this._selectedItems.remove(itemToSelect);
+
+ // Fix anchor item
+ this.setAnchorItem(this._selectedItems.getFirst());
+ }
+ else
+ {
+ // Clear current selection
+ if (!vDomEvent.getCtrlKey() || !this.getMultiSelection()) {
+ this._deselectAll();
+ }
+
+ // Update new item to be selected
+ this.renderItemSelectionState(itemToSelect, true);
+
+ // Add item to new selection
+ this._selectedItems.add(itemToSelect);
+
+ // Update anchor to this new item
+ // (allows following shift range selection)
+ this.setAnchorItem(itemToSelect);
+ }
+ }
+ }
+ }
+
+ // Recover change event status
+ this.setFireChange(oldFireChange);
+
+ // Dispatch change Event
+ if (oldFireChange && this._hasChanged(oldVal)) {
+ this._dispatchChange();
+ }
+}
+
+qx.Proto.getItemToSelect = function(vKeyboardEvent)
+{
+ // Don't handle ALT here
+ if (vKeyboardEvent.getAltKey()) {
+ return null;
+ }
+
+ // Handle event by keycode
+ switch (vKeyboardEvent.getKeyIdentifier())
+ {
+ case "Home":
+ return this.getHome(this.getLeadItem());
+
+ case "End":
+ return this.getEnd(this.getLeadItem());
+
+
+ case "Down":
+ return this.getDown(this.getLeadItem());
+
+ case "Up":
+ return this.getUp(this.getLeadItem());
+
+
+ case "Left":
+ return this.getLeft(this.getLeadItem());
+
+ case "Right":
+ return this.getRight(this.getLeadItem());
+
+
+ case "PageUp":
+ return this.getPageUp(this.getLeadItem()) || this.getHome(this.getLeadItem());
+
+ case "PageDown":
+ return this.getPageDown(this.getLeadItem()) || this.getEnd(this.getLeadItem());
+
+
+ case "Space":
+ if (vKeyboardEvent.getCtrlKey()) {
+ return this.getLeadItem();
+ }
+ }
+
+ return null;
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHANGE HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._dispatchChange = function()
+{
+ if (!this.getFireChange()) {
+ return;
+ }
+
+ if (this.hasEventListeners("changeSelection")) {
+ this.dispatchEvent(new qx.event.type.DataEvent("changeSelection", this.getSelectedItems()), true);
+ }
+}
+
+qx.Proto._hasChanged = function(sOldValue) {
+ return sOldValue != this._getChangeValue();
+}
+
+qx.Proto._getChangeValue = function() {
+ return this._selectedItems.getChangeValue();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ POSITION HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getHome = function() {
+ return this.getFirst();
+}
+
+qx.Proto.getEnd = function() {
+ return this.getLast();
+}
+
+qx.Proto.getDown = function(vItem)
+{
+ if (!vItem) {
+ return this.getFirst();
+ }
+
+ return this.getMultiColumnSupport() ? (this.getUnder(vItem) || this.getLast()) : this.getNext(vItem);
+}
+
+qx.Proto.getUp = function(vItem)
+{
+ if (!vItem) {
+ return this.getLast();
+ }
+
+ return this.getMultiColumnSupport() ? (this.getAbove(vItem) || this.getFirst()) : this.getPrevious(vItem);
+}
+
+qx.Proto.getLeft = function(vItem)
+{
+ if (!this.getMultiColumnSupport()) {
+ return null;
+ }
+
+ return !vItem ? this.getLast() : this.getPrevious(vItem);
+}
+
+qx.Proto.getRight = function(vItem)
+{
+ if (!this.getMultiColumnSupport()) {
+ return null;
+ }
+
+ return !vItem ? this.getFirst() : this.getNext(vItem);
+}
+
+qx.Proto.getAbove = function(vItem)
+{
+ throw new Error("getAbove(): Not implemented yet");
+}
+
+qx.Proto.getUnder = function(vItem)
+{
+ throw new Error("getUnder(): Not implemented yet");
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PAGE HANDLING
+---------------------------------------------------------------------------
+*/
+
+/*!
+Jump a "page" up.
+
+#param vItem[qx.ui.core.Widget]: Relative to this widget
+*/
+qx.Proto.getPageUp = function(vItem)
+{
+ var vBoundedWidget = this.getBoundedWidget();
+ var vParentScrollTop = vBoundedWidget.getScrollTop();
+ var vParentClientHeight = vBoundedWidget.getClientHeight();
+
+ // Find next item
+ var newItem;
+ var nextItem = this.getLeadItem();
+ if (!nextItem) {
+ nextItem = this.getFirst();
+ }
+
+ // Normally we should reach the status "lead" for the
+ // nextItem after two iterations.
+ var tryLoops = 0;
+ while (tryLoops < 2)
+ {
+ while (nextItem && (this.getItemTop(nextItem) - this.getItemHeight(nextItem) >= vParentScrollTop)) {
+ nextItem = this.getUp(nextItem);
+ }
+
+ // This should never occour after the fix above
+ if (nextItem == null) {
+ break;
+ }
+
+ // If the nextItem is not anymore the leadItem
+ // Means: There has occured a change.
+ // We break here. This is normally the second step.
+ if (nextItem != this.getLeadItem())
+ {
+ // be sure that the top is reached
+ this.scrollItemIntoView(nextItem, true);
+ break;
+ }
+
+ // Update scrolling (this is normally the first step)
+ // this.debug("Scroll-Up: " + (vParentScrollTop + vParentClientHeight - 2 * this.getItemHeight(nextItem)));
+ vBoundedWidget.setScrollTop(vParentScrollTop - vParentClientHeight - this.getItemHeight(nextItem));
+
+ // Use the real applied value instead of the calulated above
+ vParentScrollTop = vBoundedWidget.getScrollTop();
+
+ // Increment counter
+ tryLoops++;
+ }
+
+ return nextItem;
+}
+
+/*!
+Jump a "page" down.
+
+#param vItem[qx.ui.core.Widget]: Relative to this widget
+*/
+qx.Proto.getPageDown = function(vItem)
+{
+ var vBoundedWidget = this.getBoundedWidget();
+ var vParentScrollTop = vBoundedWidget.getScrollTop();
+ var vParentClientHeight = vBoundedWidget.getClientHeight();
+
+ // this.debug("Bound: " + (vBoundedWidget._getTargetNode() != vBoundedWidget.getElement()));
+
+ // this.debug("ClientHeight-1: " + vBoundedWidget._getTargetNode().clientHeight);
+ // this.debug("ClientHeight-2: " + vBoundedWidget.getElement().clientHeight);
+
+ // Find next item
+ var newItem;
+ var nextItem = this.getLeadItem();
+ if (!nextItem) {
+ nextItem = this.getFirst();
+ }
+
+ // Normally we should reach the status "lead" for the
+ // nextItem after two iterations.
+ var tryLoops = 0;
+ while (tryLoops < 2)
+ {
+ // this.debug("Loop: " + tryLoops);
+ // this.debug("Info: " + nextItem + " :: " + (this.getItemTop(nextItem) + (2 * this.getItemHeight(nextItem))) + " <> " + (vParentScrollTop + vParentClientHeight));
+ // this.debug("Detail: " + vParentScrollTop + ", " + vParentClientHeight);
+
+ // Find next
+ while (nextItem && ((this.getItemTop(nextItem) + (2 * this.getItemHeight(nextItem))) <= (vParentScrollTop + vParentClientHeight))) {
+ nextItem = this.getDown(nextItem);
+ }
+
+ // This should never occour after the fix above
+ if (nextItem == null) {
+ break;
+ }
+
+ // If the nextItem is not anymore the leadItem
+ // Means: There has occured a change.
+ // We break here. This is normally the second step.
+ if (nextItem != this.getLeadItem()) {
+ break;
+ }
+
+ // Update scrolling (this is normally the first step)
+ // this.debug("Scroll-Down: " + (vParentScrollTop + vParentClientHeight - 2 * this.getItemHeight(nextItem)));
+ vBoundedWidget.setScrollTop(vParentScrollTop + vParentClientHeight - 2 * this.getItemHeight(nextItem));
+
+ // Use the real applied value instead of the calulated above
+ vParentScrollTop = vBoundedWidget.getScrollTop();
+
+ // Increment counter
+ tryLoops++;
+ }
+
+ //this.debug("Select: " + nextItem._labelObject.getHtml());
+
+ return nextItem;
+}
+
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (this._selectedItems)
+ {
+ this._selectedItems.dispose();
+ this._selectedItems = null;
+ }
+
+ return qx.core.Target.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/TreeFullControlSelectionManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/TreeFullControlSelectionManager.js
new file mode 100644
index 0000000000..625296430a
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/TreeFullControlSelectionManager.js
@@ -0,0 +1,206 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_treefullcontrol)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.manager.selection.TreeFullControlSelectionManager", qx.manager.selection.SelectionManager,
+function(vBoundedWidget) {
+ qx.manager.selection.SelectionManager.call(this, vBoundedWidget);
+});
+
+/*!
+Should multiple selection be allowed?
+*/
+qx.OO.changeProperty({ name : "multiSelection", type : "boolean", defaultValue : false });
+
+/*!
+Enable drag selection?
+*/
+qx.OO.changeProperty({ name : "dragSelection", type : "boolean", defaultValue : false });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO BOUNDED WIDGET
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._getFirst = function() {
+ return qx.lang.Array.getFirst(this.getItems());
+}
+
+qx.Proto._getLast = function() {
+ return qx.lang.Array.getLast(this.getItems());
+}
+
+qx.Proto.getItems = function() {
+ return this.getBoundedWidget().getItems();
+}
+
+qx.Proto.getNext = function(vItem)
+{
+ if (vItem)
+ {
+ if (qx.ui.treefullcontrol.Tree.isOpenTreeFolder(vItem))
+ {
+ return vItem.getFirstVisibleChildOfFolder();
+ }
+ else if (vItem.isLastVisibleChild())
+ {
+ var vCurrent = vItem;
+
+ while(vCurrent && vCurrent.isLastVisibleChild()) {
+ vCurrent = vCurrent.getParentFolder();
+ }
+
+ if (vCurrent &&
+ vCurrent instanceof qx.ui.treefullcontrol.AbstractTreeElement &&
+ vCurrent.getNextVisibleSibling() &&
+ vCurrent.getNextVisibleSibling() instanceof qx.ui.treefullcontrol.AbstractTreeElement) {
+ return vCurrent.getNextVisibleSibling();
+ }
+ }
+ else
+ {
+ return vItem.getNextVisibleSibling();
+ }
+ }
+ else
+ {
+ return this.getBoundedWidget().getFirstTreeChild();
+ }
+}
+
+qx.Proto.getPrevious = function(vItem)
+{
+ if (vItem)
+ {
+ if (vItem == this.getBoundedWidget())
+ {
+ return;
+ }
+ else if (vItem.isFirstVisibleChild())
+ {
+ if (vItem.getParentFolder() instanceof qx.ui.treefullcontrol.TreeFolder) {
+ return vItem.getParentFolder();
+ }
+ }
+ else
+ {
+ var vPrev = vItem.getPreviousVisibleSibling();
+
+ if (vPrev instanceof qx.ui.treefullcontrol.AbstractTreeElement)
+ {
+ while (vPrev instanceof qx.ui.treefullcontrol.AbstractTreeElement)
+ {
+ if (qx.ui.treefullcontrol.Tree.isOpenTreeFolder(vPrev))
+ {
+ vPrev = vPrev.getLastVisibleChildOfFolder();
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ return vPrev;
+ }
+ }
+ else
+ {
+ return this.getBoundedWidget().getLastTreeChild();
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO ITEM DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getItemTop = function(vItem)
+{
+ // Alternate method:
+ // return qx.dom.Location.getPageBoxTop(vItem.getElement()) - qx.dom.Location.getPageInnerTop(this.getBoundedWidget().getElement());
+
+ var vBoundedWidget = this.getBoundedWidget();
+ var vElement = vItem.getElement();
+ var vOffset = 0;
+
+ while (vElement && vElement.qx_Widget != vBoundedWidget)
+ {
+ vOffset += vElement.offsetTop;
+ vElement = vElement.parentNode;
+ }
+
+ return vOffset;
+}
+
+qx.Proto.getItemHeight = function(vItem)
+{
+ if (vItem instanceof qx.ui.treefullcontrol.TreeFolder &&
+ vItem._horizontalLayout)
+ {
+ return vItem._horizontalLayout.getOffsetHeight();
+ }
+ else
+ {
+ return vItem.getOffsetHeight();
+ }
+}
+
+qx.Proto.scrollItemIntoView = function(vItem)
+{
+ if (vItem instanceof qx.ui.treefullcontrol.TreeFolder &&
+ vItem._horizontalLayout)
+ {
+ return vItem._horizontalLayout.scrollIntoView();
+ }
+ else
+ {
+ return vItem.scrollIntoView();
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ITEM STATE MANAGMENT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.renderItemSelectionState = function(vItem, vIsSelected) {
+ vItem.setSelected(vIsSelected);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/TreeSelectionManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/TreeSelectionManager.js
new file mode 100644
index 0000000000..d4dfe91041
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/TreeSelectionManager.js
@@ -0,0 +1,198 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_tree)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.manager.selection.TreeSelectionManager", qx.manager.selection.SelectionManager,
+function(vBoundedWidget) {
+ qx.manager.selection.SelectionManager.call(this, vBoundedWidget);
+});
+
+/*!
+Should multiple selection be allowed?
+*/
+qx.OO.changeProperty({ name : "multiSelection", type : "boolean", defaultValue : false });
+
+/*!
+Enable drag selection?
+*/
+qx.OO.changeProperty({ name : "dragSelection", type : "boolean", defaultValue : false });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO BOUNDED WIDGET
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._getFirst = function() {
+ return qx.lang.Array.getFirst(this.getItems());
+}
+
+qx.Proto._getLast = function() {
+ return qx.lang.Array.getLast(this.getItems());
+}
+
+qx.Proto.getItems = function() {
+ return this.getBoundedWidget().getItems();
+}
+
+qx.Proto.getNext = function(vItem)
+{
+ if (vItem)
+ {
+ if (qx.ui.tree.Tree.isOpenTreeFolder(vItem))
+ {
+ return vItem.getFirstVisibleChildOfFolder();
+ }
+ else if (vItem.isLastVisibleChild())
+ {
+ var vCurrent = vItem;
+
+ while(vCurrent && vCurrent.isLastVisibleChild()) {
+ vCurrent = vCurrent.getParentFolder();
+ }
+
+ if (vCurrent && vCurrent instanceof qx.ui.tree.AbstractTreeElement && vCurrent.getNextVisibleSibling() && vCurrent.getNextVisibleSibling() instanceof qx.ui.tree.AbstractTreeElement) {
+ return vCurrent.getNextVisibleSibling();
+ }
+ }
+ else
+ {
+ return vItem.getNextVisibleSibling();
+ }
+ }
+ else
+ {
+ return this.getBoundedWidget().getFirstTreeChild();
+ }
+}
+
+qx.Proto.getPrevious = function(vItem)
+{
+ if (vItem)
+ {
+ if (vItem == this.getBoundedWidget())
+ {
+ return;
+ }
+ else if (vItem.isFirstVisibleChild())
+ {
+ if (vItem.getParentFolder() instanceof qx.ui.tree.TreeFolder) {
+ return vItem.getParentFolder();
+ }
+ }
+ else
+ {
+ var vPrev = vItem.getPreviousVisibleSibling();
+
+ while (vPrev instanceof qx.ui.tree.AbstractTreeElement)
+ {
+ if (qx.ui.tree.Tree.isOpenTreeFolder(vPrev))
+ {
+ vPrev = vPrev.getLastVisibleChildOfFolder();
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return vPrev;
+ }
+ }
+ else
+ {
+ return this.getBoundedWidget().getLastTreeChild();
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO ITEM DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getItemTop = function(vItem)
+{
+ // Alternate method:
+ // return qx.dom.Location.getPageBoxTop(vItem.getElement()) - qx.dom.Location.getPageInnerTop(this.getBoundedWidget().getElement());
+
+ var vBoundedWidget = this.getBoundedWidget();
+ var vElement = vItem.getElement();
+ var vOffset = 0;
+
+ while (vElement && vElement.qx_Widget != vBoundedWidget)
+ {
+ vOffset += vElement.offsetTop;
+ vElement = vElement.parentNode;
+ }
+
+ return vOffset;
+}
+
+qx.Proto.getItemHeight = function(vItem)
+{
+ if (vItem instanceof qx.ui.tree.TreeFolder && vItem._horizontalLayout)
+ {
+ return vItem._horizontalLayout.getOffsetHeight();
+ }
+ else
+ {
+ return vItem.getOffsetHeight();
+ }
+}
+
+qx.Proto.scrollItemIntoView = function(vItem)
+{
+ if (vItem instanceof qx.ui.tree.TreeFolder && vItem._horizontalLayout)
+ {
+ return vItem._horizontalLayout.scrollIntoView();
+ }
+ else
+ {
+ return vItem.scrollIntoView();
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ITEM STATE MANAGMENT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.renderItemSelectionState = function(vItem, vIsSelected) {
+ vItem.setSelected(vIsSelected);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/VirtualSelectionManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/VirtualSelectionManager.js
new file mode 100644
index 0000000000..a3dbe19a68
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/manager/selection/VirtualSelectionManager.js
@@ -0,0 +1,143 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+/*!
+ This class represents a selection and manage incoming events for widgets which need selection support.
+*/
+qx.OO.defineClass("qx.manager.selection.VirtualSelectionManager", qx.manager.selection.SelectionManager,
+function(vBoundedWidget) {
+ qx.manager.selection.SelectionManager.call(this, vBoundedWidget);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO BOUNDED WIDGET
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getFirst = function() {
+ return qx.lang.Array.getFirst(this.getItems());
+}
+
+qx.Proto.getLast = function() {
+ return qx.lang.Array.getLast(this.getItems());
+}
+
+qx.Proto.getItems = function() {
+ return this.getBoundedWidget().getData();
+}
+
+qx.Proto.getNextSibling = function(vItem)
+{
+ var vData = this.getItems();
+ return vData[vData.indexOf(vItem)+1];
+}
+
+qx.Proto.getPreviousSibling = function(vItem)
+{
+ var vData = this.getItems();
+ return vData[vData.indexOf(vItem)-1];
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO ITEM PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getItemHashCode = function(oItem)
+{
+ if (oItem._hash) {
+ return oItem._hash;
+ }
+
+ return oItem._hash = qx.core.Object.toHashCode(oItem);
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO ITEM DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.scrollItemIntoView = function(vItem, vTopLeft) {
+ this.getBoundedWidget().scrollItemIntoView(vItem, vTopLeft);
+}
+
+qx.Proto.getItemLeft = function(vItem) {
+ return this.getBoundedWidget().getItemLeft(vItem);
+}
+
+qx.Proto.getItemTop = function(vItem) {
+ return this.getBoundedWidget().getItemTop(vItem);
+}
+
+qx.Proto.getItemWidth = function(vItem) {
+ return this.getBoundedWidget().getItemWidth(vItem);
+}
+
+qx.Proto.getItemHeight = function(vItem) {
+ return this.getBoundedWidget().getItemHeight(vItem);
+}
+
+/*!
+ In a qx.ui.listview.ListView there are no disabled entries support currently.
+*/
+qx.Proto.getItemEnabled = function(vItem) {
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ITEM STATE MANAGMENT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.renderItemSelectionState = function(vItem, vIsSelected) {
+ this.getBoundedWidget()._updateSelectionState(vItem, vIsSelected);
+}
+
+qx.Proto.renderItemAnchorState = function(vItem, vIsAnchor) {
+ this.getBoundedWidget()._updateAnchorState(vItem, vIsAnchor);
+}
+
+qx.Proto.renderItemLeadState = function(vItem, vIsLead) {
+ this.getBoundedWidget()._updateLeadState(vItem, vIsLead);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/net/Http.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/net/Http.js
new file mode 100644
index 0000000000..33a907596f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/net/Http.js
@@ -0,0 +1,31 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.net.Http",
+{
+ METHOD_GET : "GET",
+ METHOD_POST : "POST",
+ METHOD_PUT : "PUT",
+ METHOD_HEAD : "HEAD",
+ METHOD_DELETE : "DELETE"
+});
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/net/Protocol.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/net/Protocol.js
new file mode 100644
index 0000000000..f28f0770c4
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/net/Protocol.js
@@ -0,0 +1,35 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.net.Protocol",
+{
+ HTTP : "http",
+ HTTPS : "https",
+ FTP : "ftp",
+ FILE : "file",
+
+ URI_HTTP : "http://",
+ URI_HTTPS : "https://",
+ URI_FTP : "ftp://",
+ URI_FILE : "file://"
+});
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/border/Border.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/border/Border.js
new file mode 100644
index 0000000000..37bee9153c
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/border/Border.js
@@ -0,0 +1,1184 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#require(qx.sys.Client)
+#load(qx.renderer.border.BorderObject)
+
+************************************************************************ */
+
+/*!
+ Border implementation for qx.ui.core.Widget instances.
+*/
+qx.OO.defineClass("qx.renderer.border.Border", qx.core.Object,
+function(vWidth, vStyle, vColor)
+{
+ qx.core.Object.call(this);
+
+ this._themedEdges = {};
+ this._initCache();
+
+ if (qx.util.Validation.isValidNumber(vWidth))
+ {
+ this.setWidth(vWidth);
+
+ if (qx.util.Validation.isValidString(vStyle)) {
+ this.setStyle(vStyle);
+ }
+
+ if (qx.util.Validation.isValid(vColor)) {
+ this.setColor(vColor);
+ }
+ }
+});
+
+
+qx.Class.enhancedCrossBrowserMode = true;
+
+qx.Proto._needsCompilationTop = true;
+qx.Proto._needsCompilationRight = true;
+qx.Proto._needsCompilationBottom = true;
+qx.Proto._needsCompilationLeft = true;
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "topWidth", type : "number", defaultValue : 0, impl : "borderTopProperty" });
+qx.OO.addProperty({ name : "rightWidth", type : "number", defaultValue : 0, impl : "borderRightProperty" });
+qx.OO.addProperty({ name : "bottomWidth", type : "number", defaultValue : 0, impl : "borderBottomProperty" });
+qx.OO.addProperty({ name : "leftWidth", type : "number", defaultValue : 0, impl : "borderLeftProperty" });
+
+qx.OO.addProperty({ name : "topStyle", type : "string", defaultValue : "none", impl : "borderTopProperty" });
+qx.OO.addProperty({ name : "rightStyle", type : "string", defaultValue : "none", impl : "borderRightProperty" });
+qx.OO.addProperty({ name : "bottomStyle", type : "string", defaultValue : "none", impl : "borderBottomProperty" });
+qx.OO.addProperty({ name : "leftStyle", type : "string", defaultValue : "none", impl : "borderLeftProperty" });
+
+qx.OO.addProperty({ name : "topColor", impl : "borderTopProperty", type : "object", instance : "qx.renderer.color.Color", convert : qx.renderer.color.ColorCache });
+qx.OO.addProperty({ name : "rightColor", impl : "borderRightProperty", type : "object", instance : "qx.renderer.color.Color", convert : qx.renderer.color.ColorCache });
+qx.OO.addProperty({ name : "bottomColor", impl : "borderBottomProperty", type : "object", instance : "qx.renderer.color.Color", convert : qx.renderer.color.ColorCache });
+qx.OO.addProperty({ name : "leftColor", impl : "borderLeftProperty", type : "object", instance : "qx.renderer.color.Color", convert : qx.renderer.color.ColorCache });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITY
+---------------------------------------------------------------------------
+*/
+
+qx.renderer.border.Border.fromString = function(vDefString)
+{
+ var vBorder = new qx.renderer.border.Border;
+ var vAllParts = vDefString.split(/\s+/);
+ var vPart, vTemp;
+
+ for (var i=0; i 1)
+ {
+ propString = "";
+
+ for (var i=0, l=propValue.length, p; i= 0 && vInValue <= 255)
+ {
+ this._red = this._green = this._blue = vInValue;
+ this._isRgbColor = true;
+ }
+ else
+ {
+ throw invalid;
+ }
+
+ break;
+
+ case "object":
+ if (qx.util.Validation.isValidArray(vInValue) && vInValue.length == 3)
+ {
+ this._red = vInValue[0];
+ this._green = vInValue[1];
+ this._blue = vInValue[2];
+
+ this._isRgbColor = true;
+ break;
+ }
+
+ default:
+ throw invalid;
+ }
+
+ if (!this._isRgbColor)
+ {
+ this._red = this._green = this._blue = null;
+ this._style = this._isHtmlColor ? vInValue : null;
+ }
+ else
+ {
+ this._style = null;
+
+ if (!(this._red >= 0 && this._red <= 255 && this._green >= 0 && this._green <= 255 && this._blue >= 0 && this._blue <= 255)) {
+ throw invalid;
+ }
+ }
+
+ return this._value = vInValue;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ delete this._value;
+ delete this._style;
+
+ delete this._red;
+ delete this._green;
+ delete this._blue;
+
+ delete this._isRgbColor;
+ delete this._isHtmlColor;
+ delete this._isThemedColor;
+
+ return qx.core.Object.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/color/ColorCache.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/color/ColorCache.js
new file mode 100644
index 0000000000..add29d1190
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/color/ColorCache.js
@@ -0,0 +1,83 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.color.ColorCache");
+
+qx.renderer.color.ColorCache = function(propValue)
+{
+ var propKey;
+ var propKeyAsStyle = false;
+
+ switch(typeof propValue)
+ {
+ case "string":
+ if (propValue != "") {
+ propValue = propKey = propValue.toLowerCase();
+ break;
+ }
+
+ return propValue;
+
+ case "number":
+ if (propValue >= 0 && propValue <= 255)
+ {
+ propKey = propValue.toString();
+ break;
+ }
+
+ return propValue;
+
+ case "object":
+ if (propValue == null || propValue instanceof qx.renderer.color.Color) {
+ return propValue;
+ }
+
+ // Try to detect array of RGB values
+ if (typeof propValue.join === "function" && propValue.length == 3)
+ {
+ propKey = "rgb(" + propValue.join(",") + ")";
+ propKeyAsStyle = true;
+ break;
+ }
+
+ default:
+ return propValue;
+ }
+
+ if (qx.renderer.color.ColorCache._data[propKey]) {
+ return qx.renderer.color.ColorCache._data[propKey];
+ }
+
+ // this.debug("Create new color instance: " + propKey);
+
+ var vColorObject = qx.renderer.color.ColorCache._data[propKey] = qx.renderer.color.Color.themedNames[propValue] ? new qx.renderer.color.ColorObject(propValue) : new qx.renderer.color.Color(propValue);
+
+ if (propKeyAsStyle) {
+ vColorObject._style = propKey;
+ }
+
+ return vColorObject;
+}
+
+qx.renderer.color.ColorCache._data = {};
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/color/ColorObject.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/color/ColorObject.js
new file mode 100644
index 0000000000..57b65668a6
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/color/ColorObject.js
@@ -0,0 +1,154 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.color.ColorObject", qx.renderer.color.Color,
+function(vValue)
+{
+ // this.debug("Value: " + vValue);
+ this.setValue(vValue);
+
+ if(qx.manager.object.ColorManager.getInstance().has(this._value)) {
+ return qx.manager.object.ColorManager.getInstance().get(this._value);
+ }
+
+ qx.core.Object.call(this);
+
+ // Register this color object to manager instance
+ qx.manager.object.ColorManager.getInstance().add(this);
+
+ // Here will all objects with a dependency to this
+ // color stored.
+ this._dependentObjects = {};
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITY
+---------------------------------------------------------------------------
+*/
+
+qx.renderer.color.ColorObject.fromString = function(vDefString) {
+ return new qx.renderer.color.ColorObject(vDefString);
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PUBLIC METHODS
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Set a new value from selected theme (only for Operating System Colors)
+*/
+qx.Proto._updateTheme = function(vTheme)
+{
+ if (!this._isThemedColor) {
+ throw new Error("Could not redefine themed value of non os colors!");
+ }
+
+ this._applyThemedValue();
+ this._syncObjects();
+}
+
+qx.Proto._applyThemedValue = function()
+{
+ var vTheme = qx.manager.object.ColorManager.getInstance().getColorTheme();
+ var vRgb = vTheme.getValueByName(this._value);
+
+ if (vRgb)
+ {
+ this._red = vRgb[0];
+ this._green = vRgb[1];
+ this._blue = vRgb[2];
+ }
+
+ this._style = vTheme.getStyleByName(this._value);
+ this._hex = null;
+}
+
+qx.Proto._syncObjects = function()
+{
+ for (var i in this._dependentObjects) {
+ this._dependentObjects[i]._updateColors(this, this._style);
+ }
+}
+
+qx.Proto.setValue = function(vValue)
+{
+ this._normalize(vValue);
+ this._syncObjects();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ OBJECT MANAGMENT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.add = function(vObject) {
+ this._dependentObjects[vObject.toHashCode()] = vObject;
+}
+
+qx.Proto.remove = function(vObject) {
+ delete this._dependentObjects[vObject.toHashCode()];
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._dependentObjects)
+ {
+ for (var i in this._dependentObjects) {
+ delete this._dependentObjects[i];
+ }
+
+ delete this._dependentObjects;
+ }
+
+ return qx.renderer.color.Color.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/font/Font.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/font/Font.js
new file mode 100644
index 0000000000..ceac713d8f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/font/Font.js
@@ -0,0 +1,218 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+#load(qx.renderer.font.FontObject)
+
+************************************************************************ */
+
+/*!
+ Font implementation for qx.ui.core.Widget instances.
+*/
+
+qx.OO.defineClass("qx.renderer.font.Font", qx.core.Object,
+function(vSize, vName)
+{
+ qx.core.Object.call(this);
+
+ this._defs = {};
+
+ if (qx.util.Validation.isValidNumber(vSize)) {
+ this.setSize(vSize);
+ }
+
+ if (qx.util.Validation.isValidString(vName)) {
+ this.setName(vName);
+ }
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "size", type : "number", impl : "style" });
+qx.OO.addProperty({ name : "name", type : "string", impl : "style" });
+qx.OO.addProperty({ name : "bold", type : "boolean", defaultValue : false, impl : "style" });
+qx.OO.addProperty({ name : "italic", type : "boolean", defaultValue : false, impl : "style" });
+qx.OO.addProperty({ name : "underline", type : "boolean", defaultValue : false, impl : "style" });
+qx.OO.addProperty({ name : "strikeout", type : "boolean", defaultValue : false, impl : "style" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyStyle = function(propValue, propOldValue, propData)
+{
+ this._needsCompilation = true;
+ return true;
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITY
+---------------------------------------------------------------------------
+*/
+
+qx.renderer.font.Font.fromString = function(s)
+{
+ var vFont = new qx.renderer.font.Font;
+ var vAllParts = s.split(/\s+/);
+ var vName = [];
+ var vPart;
+
+ for (var i = 0; i < vAllParts.length; i++)
+ {
+ switch(vPart = vAllParts[i])
+ {
+ case "bold":
+ vFont.setBold(true);
+ break;
+
+ case "italic":
+ vFont.setItalic(true);
+ break;
+
+ case "underline":
+ vFont.setUnderline(true);
+ break;
+
+ case "strikeout":
+ vFont.setStrikeout(true);
+ break;
+
+ default:
+ var vTemp = parseFloat(vPart);
+
+ if(vTemp == vPart || qx.lang.String.contains(vPart, "px"))
+ {
+ vFont.setSize(vTemp);
+ }
+ else
+ {
+ vName.push(vPart);
+ }
+
+ break;
+ }
+ }
+
+ if(vName.length > 0) {
+ vFont.setName(vName.join(" "));
+ }
+
+ return vFont;
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITY
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._needsCompilation = true;
+
+qx.Proto._compile = function()
+{
+ var vName = this.getName();
+ var vSize = this.getSize();
+ var vBold = this.getBold();
+ var vItalic = this.getItalic();
+ var vUnderline = this.getUnderline();
+ var vStrikeout = this.getStrikeout();
+ var vDecoration = "";
+
+ if (this.getUnderline()) {
+ vDecoration = "underline";
+ }
+
+ if (this.getStrikeout()) {
+ vDecoration += " " + "strikeout";
+ }
+
+ this._defs.fontFamily = qx.util.Validation.isValidString(vName) ? vName : "";
+ this._defs.fontSize = qx.util.Validation.isValidNumber(vSize) ? vSize + "px" : "";
+ this._defs.fontWeight = this.getBold() ? "bold" : "normal";
+ this._defs.fontStyle = this.getItalic() ? "italic" : "normal";
+ this._defs.textDecoration = qx.util.Validation.isValidString(vDecoration) ? vDecoration : "";
+
+ this._needsCompilation = false;
+}
+
+qx.Proto._applyWidget = function(vWidget)
+{
+ if (this._needsCompilation) {
+ this._compile();
+ }
+
+ vWidget.setStyleProperty("fontFamily", this._defs.fontFamily);
+ vWidget.setStyleProperty("fontSize", this._defs.fontSize);
+ vWidget.setStyleProperty("fontWeight", this._defs.fontWeight);
+ vWidget.setStyleProperty("fontStyle", this._defs.fontStyle);
+ vWidget.setStyleProperty("textDecoration", this._defs.textDecoration);
+}
+
+qx.Proto._resetWidget = function(vWidget)
+{
+ vWidget.removeStyleProperty("fontFamily");
+ vWidget.removeStyleProperty("fontSize");
+ vWidget.removeStyleProperty("fontWeight");
+ vWidget.removeStyleProperty("fontStyle");
+ vWidget.removeStyleProperty("textDecoration");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ delete this._defs;
+
+ return qx.core.Object.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/font/FontCache.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/font/FontCache.js
new file mode 100644
index 0000000000..03b1ee769e
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/font/FontCache.js
@@ -0,0 +1,70 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.font.FontCache");
+
+qx.renderer.font.FontCache = function(propValue, propData)
+{
+ var propKey;
+ var propKeyAsStyle = false;
+
+ switch(typeof propValue)
+ {
+ case "string":
+ if (propValue != "")
+ {
+ propValue = propKey = propValue.toLowerCase();
+ break;
+ }
+
+ return propValue;
+
+ case "number":
+ propKey = propValue.toString();
+ break;
+
+ case "object":
+ if (propValue == null || propValue instanceof qx.renderer.font.Font) {
+ return propValue;
+ }
+
+ // Try to detect array of RGB values
+ if (typeof propValue.join === "function")
+ {
+ propKey = propValue.join(" ").toLowerCase();
+ break;
+ }
+
+ default:
+ return propValue;
+ }
+
+ if (qx.renderer.font.FontCache._data[propKey]) {
+ return qx.renderer.font.FontCache._data[propKey];
+ }
+
+ return qx.renderer.font.FontCache._data[propKey] = qx.renderer.font.Font.fromString(propKey);
+}
+
+qx.renderer.font.FontCache._data = {};
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/font/FontObject.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/font/FontObject.js
new file mode 100644
index 0000000000..674b1f9215
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/font/FontObject.js
@@ -0,0 +1,93 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.font.FontObject", qx.renderer.font.Font,
+function(vSize, vName)
+{
+ this._dependentObjects = {};
+
+ qx.renderer.font.Font.call(this, vSize, vName);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ WIDGET CONNECTION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.addListenerWidget = function(o) {
+ this._dependentObjects[o.toHashCode()] = o;
+}
+
+qx.Proto.removeListenerWidget = function(o) {
+ delete this._dependentObjects[o.toHashCode()];
+}
+
+qx.Proto._sync = function(vEdge)
+{
+ var vAll = this._dependentObjects;
+ var vCurrent;
+
+ for (vKey in vAll)
+ {
+ vCurrent = vAll[vKey];
+
+ if (vCurrent.isCreated()) {
+ vCurrent._updateFont(vEdge);
+ }
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (typeof this._dependentObjects === "object")
+ {
+ for (vKey in this._dependentObjects) {
+ delete this._dependentObjects[vKey];
+ }
+
+ delete this._dependentObjects;
+ }
+
+ return qx.renderer.font.Font.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/CanvasLayoutImpl.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/CanvasLayoutImpl.js
new file mode 100644
index 0000000000..dec4297676
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/CanvasLayoutImpl.js
@@ -0,0 +1,297 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#module(ui_layout)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.layout.CanvasLayoutImpl", qx.renderer.layout.LayoutImpl,
+function(vWidget) {
+ qx.renderer.layout.LayoutImpl.call(this, vWidget);
+});
+
+
+
+/*!
+ Global Structure:
+ [01] COMPUTE BOX DIMENSIONS FOR AN INDIVIDUAL CHILD
+ [02] COMPUTE NEEDED DIMENSIONS FOR AN INDIVIDUAL CHILD
+ [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
+ [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
+ [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
+ [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
+ [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
+ [08] CHILDREN ADD/REMOVE/MOVE HANDLING
+ [09] FLUSH LAYOUT QUEUES OF CHILDREN
+ [10] LAYOUT CHILD
+ [11] DISPOSER
+
+
+ Inherits from qx.renderer.layout.LayoutImpl:
+ [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
+ [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
+ [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
+ [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
+ [08] CHILDREN ADD/REMOVE/MOVE HANDLING
+ [09] FLUSH LAYOUT QUEUES OF CHILDREN
+ [11] DISPOSER
+*/
+
+
+
+/*
+---------------------------------------------------------------------------
+ [01] COMPUTE BOX DIMENSIONS FOR AN INDIVIDUAL CHILD
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Compute and return the box width of the given child
+*/
+qx.Proto.computeChildBoxWidth = function(vChild)
+{
+ var vValue = null;
+
+ if (vChild._computedLeftTypeNull || vChild._computedRightTypeNull)
+ {
+ vValue = vChild.getWidthValue();
+ }
+ else if (vChild._hasParent)
+ {
+ vValue = this.getWidget().getInnerWidth() - vChild.getLeftValue() - vChild.getRightValue();
+ }
+
+ return vValue || vChild._computeBoxWidthFallback();
+}
+
+/*!
+ Compute and return the box height of the given child
+*/
+qx.Proto.computeChildBoxHeight = function(vChild)
+{
+ var vValue = null;
+
+ if (vChild._computedTopTypeNull || vChild._computedBottomTypeNull)
+ {
+ vValue = vChild.getHeightValue();
+ }
+ else if (vChild._hasParent)
+ {
+ vValue = this.getWidget().getInnerHeight() - vChild.getTopValue() - vChild.getBottomValue();
+ }
+
+ return vValue || vChild._computeBoxHeightFallback();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [02] COMPUTE NEEDED DIMENSIONS FOR AN INDIVIDUAL CHILD
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Compute and return the needed width of the given child
+*/
+qx.Proto.computeChildNeededWidth = function(vChild)
+{
+ var vLeft = vChild._computedLeftTypePercent ? null : vChild.getLeftValue();
+ var vRight = vChild._computedRightTypePercent ? null : vChild.getRightValue();
+ var vMinBox = vChild._computedMinWidthTypePercent ? null : vChild.getMinWidthValue();
+ var vMaxBox = vChild._computedMaxWidthTypePercent ? null : vChild.getMaxWidthValue();
+
+ if (vLeft != null && vRight != null)
+ {
+ var vBox = vChild.getPreferredBoxWidth() || 0;
+ }
+ else
+ {
+ var vBox = (vChild._computedWidthTypePercent ? null : vChild.getWidthValue()) || vChild.getPreferredBoxWidth() || 0;
+ }
+
+ return qx.lang.Number.limit(vBox, vMinBox, vMaxBox) + vLeft + vRight + vChild.getMarginLeft() + vChild.getMarginRight();
+}
+
+/*!
+ Compute and return the needed height of the given child
+*/
+qx.Proto.computeChildNeededHeight = function(vChild)
+{
+ var vTop = vChild._computedTopTypePercent ? null : vChild.getTopValue();
+ var vBottom = vChild._computedBottomTypePercent ? null : vChild.getBottomValue();
+ var vMinBox = vChild._computedMinHeightTypePercent ? null : vChild.getMinHeightValue();
+ var vMaxBox = vChild._computedMaxHeightTypePercent ? null : vChild.getMaxHeightValue();
+
+ if (vTop != null && vBottom != null)
+ {
+ var vBox = vChild.getPreferredBoxHeight() || 0;
+ }
+ else
+ {
+ var vBox = (vChild._computedHeightTypePercent ? null : vChild.getHeightValue()) || vChild.getPreferredBoxHeight() || 0;
+ }
+
+ return qx.lang.Number.limit(vBox, vMinBox, vMaxBox) + vTop + vBottom + vChild.getMarginTop() + vChild.getMarginBottom();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Actions that should be done if the inner width of the widget was changed.
+ Normally this includes update to percent values and ranges.
+*/
+qx.Proto.updateChildOnInnerWidthChange = function(vChild)
+{
+ // this makes sure that both functions get executed before return
+ var vUpdatePercent = vChild._recomputePercentX();
+ var vUpdateRange = vChild._recomputeRangeX();
+
+ return vUpdatePercent || vUpdateRange;
+}
+
+/*!
+ Actions that should be done if the inner height of the widget was changed.
+ Normally this includes update to percent values and ranges.
+*/
+qx.Proto.updateChildOnInnerHeightChange = function(vChild)
+{
+ // this makes sure that both functions get executed before return
+ var vUpdatePercent = vChild._recomputePercentY();
+ var vUpdateRange = vChild._recomputeRangeY();
+
+ return vUpdatePercent || vUpdateRange;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [10] LAYOUT CHILD
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This is called from qx.ui.core.Widget and it's task is to apply the layout
+ (excluding border and padding) to the child.
+*/
+qx.Proto.layoutChild = function(vChild, vJobs)
+{
+ this.layoutChild_sizeX_essentialWrapper(vChild, vJobs);
+ this.layoutChild_sizeY_essentialWrapper(vChild, vJobs);
+
+ this.layoutChild_sizeLimitX(vChild, vJobs);
+ this.layoutChild_sizeLimitY(vChild, vJobs);
+
+ this.layoutChild_locationX(vChild, vJobs);
+ this.layoutChild_locationY(vChild, vJobs);
+
+ this.layoutChild_marginX(vChild, vJobs);
+ this.layoutChild_marginY(vChild, vJobs);
+}
+
+if (qx.sys.Client.getInstance().isMshtml() || qx.sys.Client.getInstance().isOpera())
+{
+ qx.Proto.layoutChild_sizeX = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.width || vJobs.minWidth || vJobs.maxWidth || vJobs.left || vJobs.right)
+ {
+ if (vChild._computedMinWidthTypeNull && vChild._computedWidthTypeNull && vChild._computedMaxWidthTypeNull && !(!vChild._computedLeftTypeNull && !vChild._computedRightTypeNull))
+ {
+ vChild._resetRuntimeWidth();
+ }
+ else
+ {
+ vChild._applyRuntimeWidth(vChild.getBoxWidth());
+ }
+ }
+ }
+
+ qx.Proto.layoutChild_sizeY = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.height || vJobs.minHeight || vJobs.maxHeight || vJobs.top || vJobs.bottom)
+ {
+ if (vChild._computedMinHeightTypeNull && vChild._computedHeightTypeNull && vChild._computedMaxHeightTypeNull && !(!vChild._computedTopTypeNull && !vChild._computedBottomTypeNull))
+ {
+ vChild._resetRuntimeHeight();
+ }
+ else
+ {
+ vChild._applyRuntimeHeight(vChild.getBoxHeight());
+ }
+ }
+ }
+}
+else
+{
+ qx.Proto.layoutChild_sizeX = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.width) {
+ vChild._computedWidthTypeNull ? vChild._resetRuntimeWidth() : vChild._applyRuntimeWidth(vChild.getWidthValue());
+ }
+ }
+
+ qx.Proto.layoutChild_sizeY = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.height) {
+ vChild._computedHeightTypeNull ? vChild._resetRuntimeHeight() : vChild._applyRuntimeHeight(vChild.getHeightValue());
+ }
+ }
+}
+
+qx.Proto.layoutChild_locationX = function(vChild, vJobs)
+{
+ var vWidget = this.getWidget();
+
+ if (vJobs.initial || vJobs.left || vJobs.parentPaddingLeft) {
+ vChild._computedLeftTypeNull ? vChild._computedRightTypeNull && vWidget.getPaddingLeft() > 0 ? vChild._applyRuntimeLeft(vWidget.getPaddingLeft()) : vChild._resetRuntimeLeft() : vChild._applyRuntimeLeft(vChild.getLeftValue() + vWidget.getPaddingLeft());
+ }
+
+ if (vJobs.initial || vJobs.right || vJobs.parentPaddingRight) {
+ vChild._computedRightTypeNull ? vChild._computedLeftTypeNull && vWidget.getPaddingRight() > 0 ? vChild._applyRuntimeRight(vWidget.getPaddingRight()) : vChild._resetRuntimeRight() : vChild._applyRuntimeRight(vChild.getRightValue() + vWidget.getPaddingRight());
+ }
+}
+
+qx.Proto.layoutChild_locationY = function(vChild, vJobs)
+{
+ var vWidget = this.getWidget();
+
+ if (vJobs.initial || vJobs.top || vJobs.parentPaddingTop) {
+ vChild._computedTopTypeNull ? vChild._computedBottomTypeNull && vWidget.getPaddingTop() > 0 ? vChild._applyRuntimeTop(vWidget.getPaddingTop()) : vChild._resetRuntimeTop() : vChild._applyRuntimeTop(vChild.getTopValue() + vWidget.getPaddingTop());
+ }
+
+ if (vJobs.initial || vJobs.bottom || vJobs.parentPaddingBottom) {
+ vChild._computedBottomTypeNull ? vChild._computedTopTypeNull && vWidget.getPaddingBottom() > 0 ? vChild._applyRuntimeBottom(vWidget.getPaddingBottom()) : vChild._resetRuntimeBottom() : vChild._applyRuntimeBottom(vChild.getBottomValue() + vWidget.getPaddingBottom());
+ }
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/DockLayoutImpl.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/DockLayoutImpl.js
new file mode 100644
index 0000000000..c948fca9b6
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/DockLayoutImpl.js
@@ -0,0 +1,488 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_layout)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.layout.DockLayoutImpl", qx.renderer.layout.LayoutImpl,
+function(vWidget) {
+ qx.renderer.layout.LayoutImpl.call(this, vWidget);
+});
+
+
+/*!
+ Global Structure:
+ [01] COMPUTE BOX DIMENSIONS FOR AN INDIVIDUAL CHILD
+ [02] COMPUTE NEEDED DIMENSIONS FOR AN INDIVIDUAL CHILD
+ [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
+ [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
+ [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
+ [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
+ [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
+ [08] CHILDREN ADD/REMOVE/MOVE HANDLING
+ [09] FLUSH LAYOUT QUEUES OF CHILDREN
+ [10] LAYOUT CHILD
+ [11] DISPOSER
+
+
+ Inherits from qx.renderer.layout.LayoutImpl:
+ [02] COMPUTE NEEDED DIMENSIONS FOR AN INDIVIDUAL CHILD
+ [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
+ [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
+ [08] CHILDREN ADD/REMOVE/MOVE HANDLING
+ [11] DISPOSER
+*/
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [00] ADDITIONAL GLOBAL DATA AND METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.renderer.layout.DockLayoutImpl.METHOD_LOCATION = "layoutChild_location_";
+
+qx.renderer.layout.DockLayoutImpl._childRanking = {
+ vertical : function(c) { return c.getVerticalAlign() ? 1e6 : c.getHorizontalAlign() ? 2e6 : 3e6; },
+ horizontal : function(c) { return c.getHorizontalAlign() ? 1e6 : c.getVerticalAlign() ? 2e6 : 3e6; },
+ ordered : function(c) { return c.getHorizontalAlign() || c.getVerticalAlign() ? 1e6 : 2e6; }
+}
+
+qx.renderer.layout.DockLayoutImpl._childCheck =
+{
+ common : function(vChild) {
+ if (!(vChild._computedLeftTypeNull && vChild._computedRightTypeNull && vChild._computedTopTypeNull && vChild._computedBottomTypeNull)) {
+ throw new Error("qx.renderer.layout.DockLayoutImpl: It is not allowed to define any location values for children: " + vChild + "!");
+ }
+ },
+
+ horizontal : function(vChild)
+ {
+ if (!(vChild._computedMinHeightTypeNull && vChild._computedHeightTypeNull && vChild._computedMaxHeightTypeNull)) {
+ throw new Error("qx.renderer.layout.DockLayoutImpl: It is not allowed to define any vertical dimension for 'horizontal' placed children: " + vChild + "!");
+ }
+ },
+
+ vertical : function(vChild)
+ {
+ if (!(vChild._computedMinWidthTypeNull && vChild._computedWidthTypeNull && vChild._computedMaxWidthTypeNull)) {
+ throw new Error("qx.renderer.layout.DockLayoutImpl: It is not allowed to define any horizontal dimension for 'vertical' placed children: " + vChild + "!");
+ }
+ },
+
+ "default" : function(vChild)
+ {
+ qx.renderer.layout.DockLayoutImpl._childCheck.horizontal(vChild);
+ qx.renderer.layout.DockLayoutImpl._childCheck.vertical(vChild);
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [01] COMPUTE BOX DIMENSIONS FOR AN INDIVIDUAL CHILD
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Compute and return the box width of the given child
+*/
+qx.Proto.computeChildBoxWidth = function(vChild)
+{
+ if (this.getChildAlignMode(vChild) == "horizontal") {
+ return vChild.getWidthValue() || vChild._computeBoxWidthFallback();
+ }
+
+ return this.getWidget().getInnerWidth() - this._lastLeft - this._lastRight;
+}
+
+/*!
+ Compute and return the box height of the given child
+*/
+qx.Proto.computeChildBoxHeight = function(vChild)
+{
+ if (this.getChildAlignMode(vChild) == "vertical") {
+ return vChild.getHeightValue() || vChild._computeBoxHeightFallback();
+ }
+
+ return this.getWidget().getInnerHeight() - this._lastTop - this._lastBottom;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Actions that should be done if the inner width of the widget was changed.
+ Normally this includes update to percent values and ranges.
+*/
+qx.Proto.updateChildOnInnerWidthChange = function(vChild)
+{
+ vChild._recomputePercentX();
+ vChild.addToLayoutChanges("location");
+
+ // inform the caller if there were any notable changes occured
+ return true;
+}
+
+/*!
+ Actions that should be done if the inner height of the widget was changed.
+ Normally this includes update to percent values and ranges.
+*/
+qx.Proto.updateChildOnInnerHeightChange = function(vChild)
+{
+ vChild._recomputePercentY();
+ vChild.addToLayoutChanges("location");
+
+ // inform the caller if there were any notable changes occured
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Invalidate and recompute things because of job in queue (before the rest of job handling will be executed).
+*/
+qx.Proto.updateSelfOnJobQueueFlush = qx.util.Return.returnFalse;
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Updates children on special jobs
+*/
+qx.Proto.updateChildrenOnJobQueueFlush = function(vQueue)
+{
+ if (vQueue.mode || vQueue.addChild || vQueue.removeChild) {
+ this.getWidget()._addChildrenToLayoutQueue("location");
+ }
+}
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [09] FLUSH LAYOUT QUEUES OF CHILDREN
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This method have full control of the order in which the
+ registered (or also non-registered) children should be
+ layouted on the horizontal axis.
+*/
+qx.Proto.flushChildrenQueue = function(vChildrenQueue)
+{
+ var vWidget=this.getWidget(), vChildren=vWidget.getVisibleChildren(), vChildrenLength=vChildren.length, vMode=vWidget.getMode();
+
+ // reset layout
+ this._lastLeft = this._lastRight = this._lastTop = this._lastBottom = 0;
+
+ // sorting children
+ var vRankImpl = qx.renderer.layout.DockLayoutImpl._childRanking[vMode];
+ var vOrderedChildren = qx.lang.Array.copy(vChildren).sort(function(c1, c2) {
+ return (vRankImpl(c1) + vChildren.indexOf(c1)) - (vRankImpl(c2) + vChildren.indexOf(c2));
+ });
+
+ // flushing children
+ for (var i=0; i vInnerWidth)
+ {
+ vRowHeightSum += vRowHeight + vVerticalSpacing;
+ vRowWidth = chc.getNeededWidth();
+ vRowHeight = chc.getNeededHeight();
+ }
+ else
+ {
+ vRowHeight = Math.max(vRowHeight, chc.getNeededHeight());
+ }
+
+ vRowWidth += vHorizontalSpacing;
+ }
+
+ return vRowHeightSum + vRowHeight;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Things to do and layout when any of the childs changes it's outer width.
+ Needed by layouts where the children depends on each-other, like flow- or box-layouts.
+*/
+qx.Proto.updateSelfOnChildOuterWidthChange = function(vChild)
+{
+ // If a child only change it's width also recompute the height
+ // as the layout flows around here
+ //this.getWidget()._recomputeNeededHeightHelper();
+ this.getWidget()._invalidatePreferredInnerHeight();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Actions that should be done if the inner width of the widget was changed.
+ Normally this includes update to percent values and ranges.
+*/
+qx.Proto.updateChildOnInnerWidthChange = function(vChild)
+{
+ vChild._recomputePercentX();
+ vChild.addToLayoutChanges("location");
+
+ return true;
+}
+
+/*!
+ Actions that should be done if the inner height of the widget was changed.
+ Normally this includes update to percent values and ranges.
+*/
+qx.Proto.updateChildOnInnerHeightChange = function(vChild)
+{
+ vChild._recomputePercentY();
+ vChild.addToLayoutChanges("location");
+
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Updates children on special jobs
+*/
+qx.Proto.updateChildrenOnJobQueueFlush = function(vQueue)
+{
+ if (vQueue.horizontalSpacing || vQueue.verticalSpacing || vQueue.reverseChildrenOrder || vQueue.horizontalChildrenAlign || vQueue.verticalChildrenAlign) {
+ this.getWidget()._addChildrenToLayoutQueue("location");
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [08] CHILDREN ADD/REMOVE/MOVE HANDLING
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This method combines calls of methods which should be done if a widget should be removed from the current layout.
+ Needed by layouts where the children depends on each-other, like flow- or box-layouts.
+*/
+qx.Proto.updateChildrenOnRemoveChild = function(vChild, vIndex)
+{
+ var w=this.getWidget(), ch=w.getVisibleChildren(), chl=ch.length, chc, i=-1;
+
+ if (w.getReverseChildrenOrder())
+ {
+ while((chc=ch[++i]) && i vWidget.getInnerWidth())
+ {
+ // evaluate width of previous row
+ vRowMax = vTempChild.getOuterHeight();
+ while((vTempChild = vTempChild[vMethodContinue]()) && vTempChild._cachedRow == vChild._cachedRow) {
+ vRowMax = Math.max(vRowMax, vTempChild.getOuterHeight());
+ }
+
+ // switch to new row
+ vChild._cachedLocationHorizontal = 0;
+ vChild._cachedLocationVertical += vWidget.getVerticalSpacing() + vRowMax;
+ vChild._cachedRow++;
+ }
+ }
+
+ // add margins and parent padding
+ if (vWidget.getHorizontalChildrenAlign() == "right")
+ {
+ vChild._resetRuntimeLeft();
+ vChild._applyRuntimeRight(vWidget.getPaddingRight() + vChild._cachedLocationHorizontal);
+ }
+ else
+ {
+ vChild._resetRuntimeRight();
+ vChild._applyRuntimeLeft(vWidget.getPaddingLeft() + vChild._cachedLocationHorizontal);
+ }
+
+ if (vWidget.getVerticalChildrenAlign() == "bottom")
+ {
+ vChild._resetRuntimeTop();
+ vChild._applyRuntimeBottom(vWidget.getPaddingBottom() + vChild._cachedLocationVertical);
+ }
+ else
+ {
+ vChild._resetRuntimeBottom();
+ vChild._applyRuntimeTop(vWidget.getPaddingTop() + vChild._cachedLocationVertical);
+ }
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/GridLayoutImpl.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/GridLayoutImpl.js
new file mode 100644
index 0000000000..ecb8c899a7
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/GridLayoutImpl.js
@@ -0,0 +1,300 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_layout)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.layout.GridLayoutImpl", qx.renderer.layout.LayoutImpl,
+function(vWidget) {
+ qx.renderer.layout.LayoutImpl.call(this, vWidget);
+});
+
+
+
+
+/*!
+ Global Structure:
+
+ [01] COMPUTE BOX DIMENSIONS FOR AN INDIVIDUAL CHILD
+ [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
+ [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
+ [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
+ [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
+ [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
+ [08] CHILDREN ADD/REMOVE/MOVE HANDLING
+ [09] FLUSH LAYOUT QUEUES OF CHILDREN
+ [10] LAYOUT CHILD
+ [11] DISPOSER
+
+ Inherits from qx.renderer.layout.LayoutImpl:
+
+ [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
+ [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
+ [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
+ [08] CHILDREN ADD/REMOVE/MOVE HANDLING
+ [09] FLUSH LAYOUT QUEUES OF CHILDREN
+ [11] DISPOSER
+*/
+
+
+
+/*
+---------------------------------------------------------------------------
+ [01] COMPUTE BOX DIMENSIONS FOR AN INDIVIDUAL CHILD
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Compute and return the box width of the given child.
+*/
+qx.Proto.computeChildBoxWidth = function(vChild)
+{
+ var vWidget = this.getWidget();
+ var vColWidth = vWidget.getColumnInnerWidth(vChild._col, vChild._row);
+
+ // extend colwidth to spanned area
+ if (vWidget.isSpanStart(vChild._col, vChild._row))
+ {
+ var vEntry = vWidget.getSpanEntry(vChild._col, vChild._row);
+ for (var i=1; i 0;
+ for (vIterator=vFlexibleChildrenLength-1; vIterator>=0; vIterator--)
+ {
+ vCurrentChild = vFlexibleChildren[vIterator];
+
+ if (vUp)
+ {
+ vAdjust = (vCurrentChild.getMaxWidthValue() || Infinity) - vCurrentChild._computedWidthFlexValue;
+
+ if (vAdjust > 0)
+ {
+ vCurrentChild._allocationLoops = Math.floor(vAdjust / vCurrentChild._computedWidthParsed);
+ }
+ else
+ {
+ qx.lang.Array.removeAt(vFlexibleChildren, vIterator);
+
+ vCurrentChild._computedWidthFlexValue = Math.round(vCurrentChild._computedWidthFlexValue);
+ vUsedWidth += Math.round(vCurrentChild._computedWidthFlexValue + vAdjust);
+ }
+ }
+ else
+ {
+ vAdjust = qx.util.Validation.isValidNumber(vCurrentChild.getMinWidthValue()) ? vCurrentChild._computedWidthFlexValue - vCurrentChild.getMinWidthValue() : vCurrentChild._computedWidthFlexValue;
+
+ if (vAdjust > 0)
+ {
+ vCurrentChild._allocationLoops = Math.floor(vAdjust / vCurrentChild._computedWidthParsed);
+ }
+ else
+ {
+ qx.lang.Array.removeAt(vFlexibleChildren, vIterator);
+
+ vCurrentChild._computedWidthFlexValue = Math.round(vCurrentChild._computedWidthFlexValue);
+ vUsedWidth += Math.round(vCurrentChild._computedWidthFlexValue - vAdjust);
+ }
+ }
+ }
+
+ // *************************************************************
+ // 6. Try to reallocate the width between flexible children
+ // so that the requirements through min/max limits
+ // are satisfied.
+ // *************************************************************
+ while (vAllocationDiff != 0 && vFlexibleChildrenLength > 0)
+ {
+ vFlexibleChildrenLength = vFlexibleChildren.length;
+ vMinAllocationLoops = Infinity;
+ vFactorSum = 0;
+
+ // Find minimal loop amount
+ for (vIterator=0; vIterator=0; vIterator--)
+ {
+ vCurrentChild = vFlexibleChildren[vIterator];
+ vCurrentChild._computedWidthFlexValue += vCurrentAllocationSum / vFactorSum * vCurrentChild._computedWidthParsed;
+
+ if (vCurrentChild._allocationLoops == vMinAllocationLoops)
+ {
+ vCurrentChild._computedWidthFlexValue = Math.round(vCurrentChild._computedWidthFlexValue);
+
+ vUsedWidth += vCurrentChild._computedWidthFlexValue;
+ delete vCurrentChild._allocationLoops;
+ qx.lang.Array.removeAt(vFlexibleChildren, vIterator);
+ }
+ else
+ {
+ if (vAllocationDiff == 0)
+ {
+ vCurrentChild._computedWidthFlexValue = Math.round(vCurrentChild._computedWidthFlexValue);
+ vUsedWidth += vCurrentChild._computedWidthFlexValue;
+ delete vCurrentChild._allocationLoops;
+ }
+ else
+ {
+ vCurrentChild._allocationLoops -= vMinAllocationLoops;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // *************************************************************
+ // 7. Fix rounding errors
+ // *************************************************************
+ vCurrentChild._computedWidthFlexValue += vAvailWidth - vUsedWidth;
+}
+
+qx.Proto.invalidateChildrenFlexWidth = function() {
+ delete this._childrenFlexWidthComputed;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Compute and return the width needed by all children of this widget
+*/
+qx.Proto.computeChildrenNeededWidth = function()
+{
+ var w = this.getWidget();
+ return qx.renderer.layout.LayoutImpl.prototype.computeChildrenNeededWidth_sum.call(this) + ((w.getVisibleChildrenLength()-1) * w.getSpacing());
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Things to do and layout when any of the childs changes its outer width.
+ Needed by layouts where the children depends on each-other, like flow- or box-layouts.
+*/
+qx.Proto.updateSelfOnChildOuterWidthChange = function(vChild)
+{
+ // if a childrens outer width changes we need to update our accumulated
+ // width of all childrens (used for center or right alignments)
+ this.getWidget()._invalidateAccumulatedChildrenOuterWidth();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Actions that should be done if the inner width of the widget was changed.
+ Normally this includes update to percent values and ranges.
+*/
+qx.Proto.updateChildOnInnerWidthChange = function(vChild)
+{
+ if (this.getWidget().getHorizontalChildrenAlign() == "center") {
+ vChild.addToLayoutChanges("locationX");
+ }
+
+ // use variables here to be sure to call both methods.
+ var vUpdatePercent = vChild._recomputePercentX();
+ var vUpdateFlex = vChild._recomputeFlexX();
+
+ // inform the caller if there were any notable changes occured
+ return vUpdatePercent || vUpdateFlex;
+}
+
+/*!
+ Actions that should be done if the inner height of the widget was changed.
+ Normally this includes update to percent values and ranges.
+*/
+qx.Proto.updateChildOnInnerHeightChange = function(vChild)
+{
+ // use variables here to be sure to call both methods.
+ var vUpdatePercent = vChild._recomputePercentY();
+ var vUpdateStretch = vChild._recomputeStretchingY();
+
+ // priority to childs internal alignment
+ if ((vChild.getVerticalAlign() || this.getWidget().getVerticalChildrenAlign()) == "middle") {
+ vChild.addToLayoutChanges("locationY");
+ }
+
+ // inform the caller if there were any notable changes occured
+ return vUpdatePercent || vUpdateStretch;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Invalidate and recompute things because of job in queue (before the rest of job handling will be executed).
+*/
+qx.Proto.updateSelfOnJobQueueFlush = function(vJobQueue)
+{
+ if (vJobQueue.addChild || vJobQueue.removeChild) {
+ this.getWidget()._invalidateAccumulatedChildrenOuterWidth();
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Updates children on special jobs
+*/
+qx.Proto.updateChildrenOnJobQueueFlush = function(vQueue)
+{
+ var vStretchX=false, vStretchY=false;
+ var vWidget = this.getWidget();
+
+ // switching the orientation need updates for stretching on both axis
+ if (vQueue.orientation) {
+ vStretchX = vStretchY = true;
+ }
+
+ // different updates depending from the current orientation (or the new one)
+ if (vQueue.spacing || vQueue.orientation || vQueue.reverseChildrenOrder || vQueue.horizontalChildrenAlign) {
+ vWidget._addChildrenToLayoutQueue("locationX");
+ }
+
+ if (vQueue.verticalChildrenAlign) {
+ vWidget._addChildrenToLayoutQueue("locationY");
+ }
+
+ if (vQueue.stretchChildrenOrthogonalAxis) {
+ vStretchY = true;
+ }
+
+ // if stretching should be reworked reset the previous one and add
+ // a layout job to update the width respectively height.
+ if (vStretchX)
+ {
+ vWidget._recomputeChildrenStretchingX();
+ vWidget._addChildrenToLayoutQueue("width");
+ }
+
+ if (vStretchY)
+ {
+ vWidget._recomputeChildrenStretchingY();
+ vWidget._addChildrenToLayoutQueue("height");
+ }
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [08] CHILDREN ADD/REMOVE/MOVE HANDLING
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This method combines calls of methods which should be done if a widget should be removed from the current layout.
+ Needed by layouts where the children depends on each-other, like flow- or box-layouts.
+*/
+qx.Proto.updateChildrenOnRemoveChild = function(vChild, vIndex)
+{
+ var w=this.getWidget(), ch=w.getVisibleChildren(), chl=ch.length, chc, i=-1;
+
+ // Fix index to be at the first flex child
+ if (this.getEnableFlexSupport())
+ {
+ for (i=0; i=0 && !vChildrenQueue[ch[i].toHashCode()]; i--) {}
+
+ // layout all children before this last child
+ for (var j=0; j<=i; j++) {
+ w._layoutChild(chc=ch[j]);
+ }
+
+ break;
+
+ case "center":
+ case "center-reversed":
+ // re-layout all children
+ i = -1;
+ while(chc=ch[++i]) {
+ w._layoutChild(chc);
+ }
+
+ break;
+
+ default:
+ // layout all childs from the first child
+ // with an own layout request to the end
+ i = -1;
+ var changed=false;
+ while(chc=ch[++i])
+ {
+ if (changed || vChildrenQueue[chc.toHashCode()])
+ {
+ w._layoutChild(chc);
+ changed = true;
+ }
+ }
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [10] LAYOUT CHILD
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This is called from qx.ui.core.Widget and it's task is to apply the layout
+ (excluding border and padding) to the child.
+*/
+qx.Proto.layoutChild = function(vChild, vJobs)
+{
+ this.layoutChild_sizeX(vChild, vJobs);
+ this.layoutChild_sizeY(vChild, vJobs);
+
+ this.layoutChild_sizeLimitX(vChild, vJobs);
+ this.layoutChild_sizeLimitY(vChild, vJobs);
+
+ this.layoutChild_locationX(vChild, vJobs);
+ this.layoutChild_locationY(vChild, vJobs);
+
+ this.layoutChild_marginX(vChild, vJobs);
+ this.layoutChild_marginY(vChild, vJobs);
+}
+
+if (qx.sys.Client.getInstance().isMshtml() || qx.sys.Client.getInstance().isOpera() || qx.sys.Client.getInstance().isWebkit() )
+{
+ qx.Proto.layoutChild_sizeX = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.width || vJobs.minWidth || vJobs.maxWidth)
+ {
+ if (vChild._isWidthEssential() && (!vChild._computedWidthTypeNull || !vChild._computedMinWidthTypeNull || !vChild._computedMaxWidthTypeNull))
+ {
+ vChild._applyRuntimeWidth(vChild.getBoxWidth());
+ }
+ else
+ {
+ vChild._resetRuntimeWidth();
+ }
+ }
+ }
+
+ qx.Proto.layoutChild_sizeY = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.height || vJobs.minHeight || vJobs.maxHeight)
+ {
+ if ((vChild._isHeightEssential() && (!vChild._computedHeightTypeNull || !vChild._computedMinHeightTypeNull || !vChild._computedMaxHeightTypeNull)) || (vChild.getAllowStretchY() && this.getWidget().getStretchChildrenOrthogonalAxis()))
+ {
+ vChild._applyRuntimeHeight(vChild.getBoxHeight());
+ }
+ else
+ {
+ vChild._resetRuntimeHeight();
+ }
+ }
+ }
+}
+else
+{
+ qx.Proto.layoutChild_sizeX = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.width)
+ {
+ if (vChild._isWidthEssential() && !vChild._computedWidthTypeNull)
+ {
+ vChild._applyRuntimeWidth(vChild.getWidthValue());
+ }
+ else
+ {
+ vChild._resetRuntimeWidth();
+ }
+ }
+ }
+
+ qx.Proto.layoutChild_sizeY = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.height)
+ {
+ if (vChild._isHeightEssential() && !vChild._computedHeightTypeNull)
+ {
+ vChild._applyRuntimeHeight(vChild.getHeightValue());
+ }
+ else
+ {
+ vChild._resetRuntimeHeight();
+ }
+ }
+ }
+}
+
+qx.Proto.layoutChild_locationX = function(vChild, vJobs)
+{
+ var vWidget = this.getWidget();
+
+ // handle first child
+ if (vWidget.getFirstVisibleChild() == vChild)
+ {
+ switch(vWidget.getLayoutMode())
+ {
+ case "right":
+ case "left-reversed":
+ var vPos = vWidget.getPaddingRight() + vWidget.getAccumulatedChildrenOuterWidth() - vChild.getOuterWidth();
+ break;
+
+ case "center":
+ case "center-reversed":
+ var vPos = vWidget.getPaddingLeft() + Math.round((vWidget.getInnerWidth() - vWidget.getAccumulatedChildrenOuterWidth()) / 2);
+ break;
+
+ default:
+ var vPos = vWidget.getPaddingLeft();
+ }
+ }
+
+ // handle any following child
+ else
+ {
+ var vPrev = vChild.getPreviousVisibleSibling();
+
+ switch(vWidget.getLayoutMode())
+ {
+ case "right":
+ case "left-reversed":
+ var vPos = vPrev._cachedLocationHorizontal - vChild.getOuterWidth() - vWidget.getSpacing();
+ break;
+
+ default:
+ var vPos = vPrev._cachedLocationHorizontal + vPrev.getOuterWidth() + vWidget.getSpacing();
+ }
+ }
+
+ // store for next sibling
+ vChild._cachedLocationHorizontal = vPos;
+
+ // apply styles
+ switch(vWidget.getLayoutMode())
+ {
+ case "right":
+ case "right-reversed":
+ case "center-reversed":
+ // add relative positions (like 'position:relative' in css)
+ vPos += !vChild._computedRightTypeNull ? vChild.getRightValue() : !vChild._computedLeftTypeNull ? -(vChild.getLeftValue()) : 0;
+
+ vChild._resetRuntimeLeft();
+ vChild._applyRuntimeRight(vPos);
+ break;
+
+ default:
+ // add relative positions (like 'position:relative' in css)
+ vPos += !vChild._computedLeftTypeNull ? vChild.getLeftValue() : !vChild._computedRightTypeNull ? -(vChild.getRightValue()) : 0;
+
+ vChild._resetRuntimeRight();
+ vChild._applyRuntimeLeft(vPos);
+ }
+}
+
+qx.Proto.layoutChild_locationY = function(vChild, vJobs)
+{
+ var vWidget = this.getWidget();
+
+ // special stretching support
+ if (qx.sys.Client.getInstance().isGecko() && vChild.getAllowStretchY() && vWidget.getStretchChildrenOrthogonalAxis() && vChild._computedHeightTypeNull)
+ {
+ vChild._applyRuntimeTop(vWidget.getPaddingTop() || 0);
+ vChild._applyRuntimeBottom(vWidget.getPaddingBottom() || 0);
+
+ return;
+ }
+
+ // priority to childs internal alignment
+ var vAlign = vChild.getVerticalAlign() || vWidget.getVerticalChildrenAlign();
+
+ // handle middle alignment
+ var vPos = vAlign == "middle" ? Math.round((vWidget.getInnerHeight() - vChild.getOuterHeight()) / 2) : 0;
+
+ // the bottom alignment use the real 'bottom' styleproperty to
+ // use the best available method in modern browsers
+ if (vAlign == "bottom")
+ {
+ // add parent padding
+ vPos += vWidget.getPaddingBottom();
+
+ // relative positions (like 'position:relative' in css)
+ if (!vChild._computedBottomTypeNull) {
+ vPos += vChild.getBottomValue();
+ }
+ else if (!vChild._computedTopTypeNull) {
+ vPos -= vChild.getTopValue();
+ }
+
+ // apply styles
+ vChild._resetRuntimeTop();
+ vChild._applyRuntimeBottom(vPos);
+ }
+ else
+ {
+ // add parent padding
+ vPos += vWidget.getPaddingTop();
+
+ // relative positions (like 'position:relative' in css)
+ if (!vChild._computedTopTypeNull) {
+ vPos += vChild.getTopValue();
+ }
+ else if (!vChild._computedBottomTypeNull) {
+ vPos -= vChild.getBottomValue();
+ }
+
+ // apply styles
+ vChild._resetRuntimeBottom();
+ vChild._applyRuntimeTop(vPos);
+ }
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/LayoutImpl.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/LayoutImpl.js
new file mode 100644
index 0000000000..5855d7d420
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/layout/LayoutImpl.js
@@ -0,0 +1,442 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#module(ui_layout)
+#require(qx.sys.Client)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.layout.LayoutImpl", qx.core.Object,
+function(vWidget)
+{
+ qx.core.Object.call(this);
+
+ this._widget = vWidget;
+});
+
+
+
+
+/*!
+ Returns the associated widget
+*/
+qx.Proto.getWidget = function() {
+ return this._widget;
+}
+
+
+/*!
+ Global Structure:
+ [01] COMPUTE BOX DIMENSIONS FOR AN INDIVIDUAL CHILD
+ [02] COMPUTE NEEDED DIMENSIONS FOR AN INDIVIDUAL CHILD
+ [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
+ [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
+ [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
+ [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
+ [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
+ [08] CHILDREN ADD/REMOVE/MOVE HANDLING
+ [09] FLUSH LAYOUT QUEUES OF CHILDREN
+ [10] LAYOUT CHILD
+ [11] DISPOSER
+*/
+
+
+/*
+---------------------------------------------------------------------------
+ [01] COMPUTE BOX DIMENSIONS FOR AN INDIVIDUAL CHILD
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Compute and return the box width of the given child
+*/
+qx.Proto.computeChildBoxWidth = function(vChild) {
+ return vChild.getWidthValue() || vChild._computeBoxWidthFallback();
+}
+
+/*!
+ Compute and return the box height of the given child
+*/
+qx.Proto.computeChildBoxHeight = function(vChild) {
+ return vChild.getHeightValue() || vChild._computeBoxHeightFallback();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [02] COMPUTE NEEDED DIMENSIONS FOR AN INDIVIDUAL CHILD
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Compute and return the needed width of the given child
+*/
+qx.Proto.computeChildNeededWidth = function(vChild)
+{
+ // omit ultra long lines, these two variables only needed once
+ // here, but this enhance the readability of the code :)
+ var vMinBox = vChild._computedMinWidthTypePercent ? null : vChild.getMinWidthValue();
+ var vMaxBox = vChild._computedMaxWidthTypePercent ? null : vChild.getMaxWidthValue();
+
+ var vBox = (vChild._computedWidthTypePercent || vChild._computedWidthTypeFlex ? null : vChild.getWidthValue()) || vChild.getPreferredBoxWidth() || 0;
+
+ return qx.lang.Number.limit(vBox, vMinBox, vMaxBox) + vChild.getMarginLeft() + vChild.getMarginRight();
+}
+
+/*!
+ Compute and return the needed height of the given child
+*/
+qx.Proto.computeChildNeededHeight = function(vChild)
+{
+ // omit ultra long lines, these two variables only needed once
+ // here, but this enhance the readability of the code :)
+ var vMinBox = vChild._computedMinHeightTypePercent ? null : vChild.getMinHeightValue();
+ var vMaxBox = vChild._computedMaxHeightTypePercent ? null : vChild.getMaxHeightValue();
+
+ var vBox = (vChild._computedHeightTypePercent || vChild._computedHeightTypeFlex ? null : vChild.getHeightValue()) || vChild.getPreferredBoxHeight() || 0;
+
+ return qx.lang.Number.limit(vBox, vMinBox, vMaxBox) + vChild.getMarginTop() + vChild.getMarginBottom();
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Calculate the maximum needed width of all children
+*/
+qx.Proto.computeChildrenNeededWidth_max = function()
+{
+ for (var i=0, ch=this.getWidget().getVisibleChildren(), chl=ch.length, maxv=0; i 0;
+ for (vIterator=vFlexibleChildrenLength-1; vIterator>=0; vIterator--)
+ {
+ vCurrentChild = vFlexibleChildren[vIterator];
+
+ if (vUp)
+ {
+ vAdjust = (vCurrentChild.getMaxHeightValue() || Infinity) - vCurrentChild._computedHeightFlexValue;
+
+ if (vAdjust > 0)
+ {
+ vCurrentChild._allocationLoops = Math.floor(vAdjust / vCurrentChild._computedHeightParsed);
+ }
+ else
+ {
+ qx.lang.Array.removeAt(vFlexibleChildren, vIterator);
+
+ vCurrentChild._computedHeightFlexValue = Math.round(vCurrentChild._computedHeightFlexValue);
+ vUsedHeight += Math.round(vCurrentChild._computedHeightFlexValue + vAdjust);
+ }
+ }
+ else
+ {
+ vAdjust = qx.util.Validation.isValidNumber(vCurrentChild.getMinHeightValue()) ? vCurrentChild._computedHeightFlexValue - vCurrentChild.getMinHeightValue() : vCurrentChild._computedHeightFlexValue;
+
+ if (vAdjust > 0)
+ {
+ vCurrentChild._allocationLoops = Math.floor(vAdjust / vCurrentChild._computedHeightParsed);
+ }
+ else
+ {
+ qx.lang.Array.removeAt(vFlexibleChildren, vIterator);
+
+ vCurrentChild._computedHeightFlexValue = Math.round(vCurrentChild._computedHeightFlexValue);
+ vUsedHeight += Math.round(vCurrentChild._computedHeightFlexValue - vAdjust);
+ }
+ }
+ }
+
+ // *************************************************************
+ // 6. Try to reallocate the height between flexible children
+ // so that the requirements through min/max limits
+ // are satisfied.
+ // *************************************************************
+ while (vAllocationDiff != 0 && vFlexibleChildrenLength > 0)
+ {
+ vFlexibleChildrenLength = vFlexibleChildren.length;
+ vMinAllocationLoops = Infinity;
+ vFactorSum = 0;
+
+ // Find minimal loop amount
+ for (vIterator=0; vIterator=0; vIterator--)
+ {
+ vCurrentChild = vFlexibleChildren[vIterator];
+ vCurrentChild._computedHeightFlexValue += vCurrentAllocationSum / vFactorSum * vCurrentChild._computedHeightParsed;
+
+ if (vCurrentChild._allocationLoops == vMinAllocationLoops)
+ {
+ vCurrentChild._computedHeightFlexValue = Math.round(vCurrentChild._computedHeightFlexValue);
+
+ vUsedHeight += vCurrentChild._computedHeightFlexValue;
+ delete vCurrentChild._allocationLoops;
+ qx.lang.Array.removeAt(vFlexibleChildren, vIterator);
+ }
+ else
+ {
+ if (vAllocationDiff == 0)
+ {
+ vCurrentChild._computedHeightFlexValue = Math.round(vCurrentChild._computedHeightFlexValue);
+ vUsedHeight += vCurrentChild._computedHeightFlexValue;
+ delete vCurrentChild._allocationLoops;
+ }
+ else
+ {
+ vCurrentChild._allocationLoops -= vMinAllocationLoops;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // *************************************************************
+ // 7. Fix rounding errors
+ // *************************************************************
+ vCurrentChild._computedHeightFlexValue += vAvailHeight - vUsedHeight;
+}
+
+qx.Proto.invalidateChildrenFlexHeight = function() {
+ delete this._childrenFlexHeightComputed;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [03] COMPUTE NEEDED DIMENSIONS FOR ALL CHILDREN
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Compute and return the height needed by all children of this widget
+*/
+qx.Proto.computeChildrenNeededHeight = function()
+{
+ var w = this.getWidget();
+ return qx.renderer.layout.LayoutImpl.prototype.computeChildrenNeededHeight_sum.call(this) + ((w.getVisibleChildrenLength()-1) * w.getSpacing());
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [04] UPDATE LAYOUT WHEN A CHILD CHANGES ITS OUTER DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Things to do and layout when any of the childs changes its outer height.
+ Needed by layouts where the children depends on each-other, like flow- or box-layouts.
+*/
+qx.Proto.updateSelfOnChildOuterHeightChange = function(vChild)
+{
+ // if a childrens outer height changes we need to update our accumulated
+ // height of all childrens (used for middle or bottom alignments)
+ this.getWidget()._invalidateAccumulatedChildrenOuterHeight();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [05] UPDATE CHILD ON INNER DIMENSION CHANGES OF LAYOUT
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Actions that should be done if the inner width of the widget was changed.
+ Normally this includes update to percent values and ranges.
+*/
+qx.Proto.updateChildOnInnerWidthChange = function(vChild)
+{
+ // use variables here to be sure to call both methods.
+ var vUpdatePercent = vChild._recomputePercentX();
+ var vUpdateStretch = vChild._recomputeStretchingX();
+
+ // priority to childs internal alignment
+ if ((vChild.getHorizontalAlign() || this.getWidget().getHorizontalChildrenAlign()) == "center") {
+ vChild.addToLayoutChanges("locationX");
+ }
+
+ // inform the caller if there were any notable changes occured
+ return vUpdatePercent || vUpdateStretch;
+}
+
+/*!
+ Actions that should be done if the inner height of the widget was changed.
+ Normally this includes update to percent values and ranges.
+*/
+qx.Proto.updateChildOnInnerHeightChange = function(vChild)
+{
+ if (this.getWidget().getVerticalChildrenAlign() == "middle") {
+ vChild.addToLayoutChanges("locationY");
+ }
+
+ // use variables here to be sure to call both methods.
+ var vUpdatePercent = vChild._recomputePercentY();
+ var vUpdateFlex = vChild._recomputeFlexY();
+
+ // inform the caller if there were any notable changes occured
+ return vUpdatePercent || vUpdateFlex;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [06] UPDATE LAYOUT ON JOB QUEUE FLUSH
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Invalidate and recompute things because of job in queue (before the rest of job handling will be executed).
+*/
+qx.Proto.updateSelfOnJobQueueFlush = function(vJobQueue)
+{
+ if (vJobQueue.addChild || vJobQueue.removeChild) {
+ this.getWidget()._invalidateAccumulatedChildrenOuterHeight();
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [07] UPDATE CHILDREN ON JOB QUEUE FLUSH
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Updates children on special jobs
+*/
+qx.Proto.updateChildrenOnJobQueueFlush = function(vQueue)
+{
+ var vStretchX=false, vStretchY=false;
+ var vWidget = this.getWidget();
+
+ // switching the orientation need updates for stretching on both axis
+ if (vQueue.orientation) {
+ vStretchX = vStretchY = true;
+ }
+
+ // different updates depending from the current orientation (or the new one)
+ if (vQueue.spacing || vQueue.orientation || vQueue.reverseChildrenOrder || vQueue.verticalChildrenAlign) {
+ vWidget._addChildrenToLayoutQueue("locationY");
+ }
+
+ if (vQueue.horizontalChildrenAlign) {
+ vWidget._addChildrenToLayoutQueue("locationX");
+ }
+
+ if (vQueue.stretchChildrenOrthogonalAxis) {
+ vStretchX = true;
+ }
+
+ // if stretching should be reworked reset the previous one and add
+ // a layout job to update the width respectively height.
+ if (vStretchX)
+ {
+ vWidget._recomputeChildrenStretchingX();
+ vWidget._addChildrenToLayoutQueue("width");
+ }
+
+ if (vStretchY)
+ {
+ vWidget._recomputeChildrenStretchingY();
+ vWidget._addChildrenToLayoutQueue("height");
+ }
+
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [08] CHILDREN ADD/REMOVE/MOVE HANDLING
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This method combines calls of methods which should be done if a widget should be removed from the current layout.
+ Needed by layouts where the children depends on each-other, like flow- or box-layouts.
+*/
+qx.Proto.updateChildrenOnRemoveChild = function(vChild, vIndex)
+{
+ var w=this.getWidget(), ch=w.getVisibleChildren(), chl=ch.length, chc, i=-1;
+
+ // Fix index to be at the first flex child
+ if (this.getEnableFlexSupport())
+ {
+ for (var i=0; i=0 && !vChildrenQueue[ch[i].toHashCode()]; i--) {}
+
+ // layout all children before this last child
+ for (var j=0; j<=i; j++) {
+ w._layoutChild(chc=ch[j]);
+ }
+
+ break;
+
+ case "middle":
+ case "middle-reversed":
+ // re-layout all children
+ i = -1;
+ while(chc=ch[++i]) {
+ w._layoutChild(chc);
+ }
+
+ break;
+
+ default:
+ // layout all childs from the first child
+ // with an own layout request to the end
+ i = -1;
+ var changed=false;
+ while(chc=ch[++i])
+ {
+ if (changed || vChildrenQueue[chc.toHashCode()])
+ {
+ w._layoutChild(chc);
+ changed = true;
+ }
+ }
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ [10] LAYOUT CHILD
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This is called from qx.ui.core.Widget and it's task is to apply the layout
+ (excluding border and padding) to the child.
+*/
+qx.Proto.layoutChild = function(vChild, vJobs)
+{
+ this.layoutChild_sizeX(vChild, vJobs);
+ this.layoutChild_sizeY(vChild, vJobs);
+
+ this.layoutChild_sizeLimitX(vChild, vJobs);
+ this.layoutChild_sizeLimitY(vChild, vJobs);
+
+ this.layoutChild_locationX(vChild, vJobs);
+ this.layoutChild_locationY(vChild, vJobs);
+
+ this.layoutChild_marginX(vChild, vJobs);
+ this.layoutChild_marginY(vChild, vJobs);
+}
+
+if (qx.sys.Client.getInstance().isMshtml() || qx.sys.Client.getInstance().isOpera() || qx.sys.Client.getInstance().isWebkit())
+{
+ qx.Proto.layoutChild_sizeX = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.width || vJobs.minWidth || vJobs.maxWidth)
+ {
+ if ((vChild._isWidthEssential() && (!vChild._computedWidthTypeNull || !vChild._computedMinWidthTypeNull || !vChild._computedMaxWidthTypeNull)) || (vChild.getAllowStretchX() && this.getWidget().getStretchChildrenOrthogonalAxis()))
+ {
+ vChild._applyRuntimeWidth(vChild.getBoxWidth());
+ }
+ else
+ {
+ vChild._resetRuntimeWidth();
+ }
+ }
+ }
+
+ qx.Proto.layoutChild_sizeY = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.height || vJobs.minHeight || vJobs.maxHeight)
+ {
+ if (vChild._isHeightEssential() && (!vChild._computedHeightTypeNull || !vChild._computedMinHeightTypeNull || !vChild._computedMaxHeightTypeNull))
+ {
+ vChild._applyRuntimeHeight(vChild.getBoxHeight());
+ }
+ else
+ {
+ vChild._resetRuntimeHeight();
+ }
+ }
+ }
+}
+else
+{
+ qx.Proto.layoutChild_sizeX = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.width)
+ {
+ if (vChild._isWidthEssential() && !vChild._computedWidthTypeNull)
+ {
+ vChild._applyRuntimeWidth(vChild.getWidthValue());
+ }
+ else
+ {
+ vChild._resetRuntimeWidth();
+ }
+ }
+ }
+
+ qx.Proto.layoutChild_sizeY = function(vChild, vJobs)
+ {
+ if (vJobs.initial || vJobs.height)
+ {
+ if (vChild._isHeightEssential() && !vChild._computedHeightTypeNull)
+ {
+ vChild._applyRuntimeHeight(vChild.getHeightValue());
+ }
+ else
+ {
+ vChild._resetRuntimeHeight();
+ }
+ }
+ }
+}
+
+qx.Proto.layoutChild_locationY = function(vChild, vJobs)
+{
+ var vWidget = this.getWidget();
+
+ // handle first child
+ if (vWidget.getFirstVisibleChild() == vChild)
+ {
+ switch(vWidget.getLayoutMode())
+ {
+ case "bottom":
+ case "top-reversed":
+ var vPos = vWidget.getPaddingBottom() + vWidget.getAccumulatedChildrenOuterHeight() - vChild.getOuterHeight();
+ break;
+
+ case "middle":
+ case "middle-reversed":
+ var vPos = vWidget.getPaddingTop() + Math.round((vWidget.getInnerHeight() - vWidget.getAccumulatedChildrenOuterHeight()) / 2);
+ break;
+
+ default:
+ var vPos = vWidget.getPaddingTop();
+ }
+ }
+
+ // handle any following child
+ else
+ {
+ var vPrev = vChild.getPreviousVisibleSibling();
+
+ switch(vWidget.getLayoutMode())
+ {
+ case "bottom":
+ case "top-reversed":
+ var vPos = vPrev._cachedLocationVertical - vChild.getOuterHeight() - vWidget.getSpacing();
+ break;
+
+ default:
+ var vPos = vPrev._cachedLocationVertical + vPrev.getOuterHeight() + vWidget.getSpacing();
+ }
+ }
+
+ // store for next sibling
+ vChild._cachedLocationVertical = vPos;
+
+ // apply styles
+ switch(this.getWidget().getLayoutMode())
+ {
+ case "bottom":
+ case "bottom-reversed":
+ case "middle-reversed":
+ // add relative positions (like 'position:relative' in css)
+ vPos += !vChild._computedBottomTypeNull ? vChild.getBottomValue() : !vChild._computedTopTypeNull ? -(vChild.getTopValue()) : 0;
+
+ vChild._resetRuntimeTop();
+ vChild._applyRuntimeBottom(vPos);
+ break;
+
+ default:
+ // add relative positions (like 'position:relative' in css)
+ vPos += !vChild._computedTopTypeNull ? vChild.getTopValue() : !vChild._computedBottomTypeNull ? -(vChild.getBottomValue()) : 0;
+
+ vChild._resetRuntimeBottom();
+ vChild._applyRuntimeTop(vPos);
+ }
+}
+
+qx.Proto.layoutChild_locationX = function(vChild, vJobs)
+{
+ var vWidget = this.getWidget();
+
+ // special stretching support
+ if (qx.sys.Client.getInstance().isGecko() && vChild.getAllowStretchX() && vWidget.getStretchChildrenOrthogonalAxis() && vChild._computedWidthTypeNull)
+ {
+ vChild._applyRuntimeLeft(vWidget.getPaddingLeft() || 0);
+ vChild._applyRuntimeRight(vWidget.getPaddingRight() || 0);
+
+ return;
+ }
+
+ // priority to childs internal alignment
+ var vAlign = vChild.getHorizontalAlign() || vWidget.getHorizontalChildrenAlign();
+
+ // handle center alignment
+ var vPos = vAlign == "center" ? Math.round((vWidget.getInnerWidth() - vChild.getOuterWidth()) / 2) : 0;
+
+ // the right alignment use the real 'right' styleproperty to
+ // use the best available method in modern browsers
+ if (vAlign == "right")
+ {
+ // add parent padding
+ vPos += vWidget.getPaddingRight();
+
+ // relative positions (like 'position:relative' in css)
+ if (!vChild._computedRightTypeNull) {
+ vPos += vChild.getRightValue();
+ }
+ else if (!vChild._computedLeftTypeNull) {
+ vPos -= vChild.getLeftValue();
+ }
+
+ // apply styles
+ vChild._resetRuntimeLeft();
+ vChild._applyRuntimeRight(vPos);
+ }
+ else
+ {
+ // add parent padding
+ vPos += vWidget.getPaddingLeft();
+
+ // relative positions (like 'position:relative' in css)
+ if (!vChild._computedLeftTypeNull) {
+ vPos += vChild.getLeftValue();
+ }
+ else if (!vChild._computedRightTypeNull) {
+ vPos -= vChild.getRightValue();
+ }
+
+ // apply styles
+ vChild._resetRuntimeRight();
+ vChild._applyRuntimeLeft(vPos);
+ }
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/AppearanceTheme.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/AppearanceTheme.js
new file mode 100644
index 0000000000..57cb643fb7
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/AppearanceTheme.js
@@ -0,0 +1,164 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.theme.AppearanceTheme", qx.core.Object,
+function(vTitle)
+{
+ qx.core.Object.call(this);
+
+ this.setTitle(vTitle);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "title", type : "string", allowNull : false, defaultValue : "" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DATA
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._appearances = {};
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CORE METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.registerAppearance = function(vId, vData) {
+ this._appearances[vId] = vData;
+}
+
+qx.Proto.getAppearance = function(vId) {
+ return this._appearances[vId];
+}
+
+qx.Proto.setupAppearance = function(vAppearance)
+{
+ if (!vAppearance._setupDone)
+ {
+ if (vAppearance.setup) {
+ vAppearance.setup(this);
+ }
+
+ vAppearance._setupDone = true;
+ }
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ WIDGET METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.initialFrom = function(vId)
+{
+ var vAppearance = this.getAppearance(vId);
+ if (vAppearance)
+ {
+ this.setupAppearance(vAppearance);
+
+ try
+ {
+ return vAppearance.initial ? vAppearance.initial(this) : {}
+ }
+ catch(ex)
+ {
+ this.error("Couldn't apply initial appearance", ex);
+ }
+ }
+ else
+ {
+ return this.error("Missing appearance: " + vId);
+ }
+}
+
+qx.Proto.stateFrom = function(vId, vStates)
+{
+ var vAppearance = this.getAppearance(vId);
+ if (vAppearance)
+ {
+ this.setupAppearance(vAppearance);
+
+ try
+ {
+ return vAppearance.state ? vAppearance.state(this, vStates) : {}
+ }
+ catch(ex)
+ {
+ this.error("Couldn't apply state appearance", ex);
+ }
+ }
+ else
+ {
+ return this.error("Missing appearance: " + vId);
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this._appearances = null;
+
+ return qx.core.Object.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/ColorTheme.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/ColorTheme.js
new file mode 100644
index 0000000000..2e72dc624a
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/ColorTheme.js
@@ -0,0 +1,132 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#after(qx.manager.object.ColorManager)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.theme.ColorTheme", qx.core.Object,
+function(vTitle)
+{
+ qx.core.Object.call(this);
+
+ this._compiledColors = {};
+ this.setTitle(vTitle);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "title", type : "string", allowNull : false, defaultValue : "" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DATA
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._needsCompilation = true;
+qx.Proto._colors = {};
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PUBLIC METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getValueByName = function(vName) {
+ return this._colors[vName] || "";
+}
+
+qx.Proto.getStyleByName = function(vName) {
+ return this._compiledColors[vName] || "";
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PRIVATE METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.compile = function()
+{
+ if (!this._needsCompilation) {
+ return;
+ }
+
+ for (var vName in qx.renderer.color.Color.themedNames) {
+ this._compileValue(vName);
+ }
+
+ this._needsCompilation = false;
+}
+
+qx.Proto._compileValue = function(vName)
+{
+ var v = this._colors[vName];
+ this._compiledColors[vName] = v ? qx.renderer.color.Color.rgb2style.apply(this, this._colors[vName]) : vName;
+}
+
+qx.Proto._register = function() {
+ return qx.manager.object.ColorManager.getInstance().registerTheme(this);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ delete this._colors;
+ delete this._compiledColors;
+
+ qx.core.Object.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/IconTheme.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/IconTheme.js
new file mode 100644
index 0000000000..1402ce76c0
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/IconTheme.js
@@ -0,0 +1,34 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#after(qx.manager.object.ImageManager)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.theme.IconTheme", qx.core.Object,
+function(vTitle)
+{
+ qx.core.Object.call(this);
+
+ this.setTitle(vTitle);
+});
+
+qx.OO.addProperty({ name : "title", type : "string", allowNull : false, defaultValue : "" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/WidgetTheme.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/WidgetTheme.js
new file mode 100644
index 0000000000..54d318f2f0
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/renderer/theme/WidgetTheme.js
@@ -0,0 +1,34 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#after(qx.manager.object.ImageManager)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.renderer.theme.WidgetTheme", qx.core.Object,
+function(vTitle)
+{
+ qx.core.Object.call(this);
+
+ this.setTitle(vTitle);
+});
+
+qx.OO.addProperty({ name : "title", type : "string", allowNull : false, defaultValue : "" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/sys/Client.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/sys/Client.js
new file mode 100644
index 0000000000..a32c0de8e5
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/sys/Client.js
@@ -0,0 +1,394 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(core)
+
+************************************************************************ */
+
+/*!
+ Basic client detection implementation
+
+ Version shemes following wikipedia: major.minor[.revision[.build]]
+ http://en.wikipedia.org/wiki/Software_version
+*/
+qx.OO.defineClass("qx.sys.Client", Object,
+function()
+{
+ var vRunsLocally = window.location.protocol === "file:";
+
+ var vBrowserUserAgent = navigator.userAgent;
+ var vBrowserVendor = navigator.vendor;
+ var vBrowserProduct = navigator.product;
+ var vBrowserPlatform = navigator.platform;
+ var vBrowserModeHta = false;
+ var vBrowser;
+
+ var vEngine = null;
+ var vEngineVersion = null;
+ var vEngineVersionMajor = 0;
+ var vEngineVersionMinor = 0;
+ var vEngineVersionRevision = 0;
+ var vEngineVersionBuild = 0;
+
+ var vEngineEmulation = null;
+ var vVersionHelper;
+
+ if (window.opera && /Opera[\s\/]([0-9\.]*)/.test(vBrowserUserAgent))
+ {
+ vEngine = "opera";
+ vEngineVersion = RegExp.$1;
+
+ // Fix Opera version to match wikipedia style
+ vEngineVersion = vEngineVersion.substring(0, 3) + "." + vEngineVersion.substring(3);
+
+ vEngineEmulation = vBrowserUserAgent.indexOf("MSIE") !== -1 ? "mshtml" : vBrowserUserAgent.indexOf("Mozilla") !== -1 ? "gecko" : null;
+ }
+ else if (typeof vBrowserVendor==="string" && vBrowserVendor==="KDE" && /KHTML\/([0-9-\.]*)/.test(vBrowserUserAgent))
+ {
+ vEngine = "khtml";
+ vBrowser = "konqueror";
+ vEngineVersion = RegExp.$1;
+ }
+ else if (vBrowserUserAgent.indexOf("AppleWebKit") != -1 && /AppleWebKit\/([0-9-\.]*)/.test(vBrowserUserAgent))
+ {
+ vEngine = "webkit";
+ vEngineVersion = RegExp.$1;
+
+ if(vBrowserUserAgent.indexOf("Safari") != -1) {
+ vBrowser = "safari";
+ } else if(vBrowserUserAgent.indexOf("Omni") != -1) {
+ vBrowser = "omniweb";
+ } else {
+ vBrowser = "other webkit";
+ }
+ }
+ else if (window.controllers && typeof vBrowserProduct==="string" && vBrowserProduct==="Gecko" && /rv\:([^\);]+)(\)|;)/.test(vBrowserUserAgent))
+ {
+ // http://www.mozilla.org/docs/dom/domref/dom_window_ref13.html
+ vEngine = "gecko";
+ vEngineVersion = RegExp.$1;
+
+ if(vBrowserUserAgent.indexOf("Firefox") != -1) {
+ vBrowser = "firefox";
+ } else if(vBrowserUserAgent.indexOf("Camino") != -1) {
+ vBrowser = "camino";
+ } else if(vBrowserUserAgent.indexOf("Galeon") != -1) {
+ vBrowser = "galeon";
+ } else {
+ vBrowser = "other gecko";
+ }
+ }
+ else if (/MSIE\s+([^\);]+)(\)|;)/.test(vBrowserUserAgent))
+ {
+ vEngine = "mshtml";
+ vEngineVersion = RegExp.$1;
+
+ vBrowserModeHta = !window.external;
+ }
+
+ if (vEngineVersion)
+ {
+ vVersionHelper = vEngineVersion.split(".");
+
+ vEngineVersionMajor = vVersionHelper[0] || 0;
+ vEngineVersionMinor = vVersionHelper[1] || 0;
+ vEngineVersionRevision = vVersionHelper[2] || 0;
+ vEngineVersionBuild = vVersionHelper[3] || 0;
+ }
+
+ var vEngineBoxSizingAttr = vEngine == "gecko" ? "-moz-box-sizing" : vEngine == "mshtml" ? null : "box-sizing";
+ var vEngineQuirksMode = document.compatMode !== "CSS1Compat";
+
+ var vDefaultLocale = "en";
+ var vBrowserLocale = (vEngine == "mshtml" ? navigator.userLanguage : navigator.language).toLowerCase();
+ var vBrowserLocaleVariant = null;
+
+ var vBrowserLocaleVariantIndex = vBrowserLocale.indexOf("-");
+ if (vBrowserLocaleVariantIndex != -1)
+ {
+ vBrowserLocaleVariant = vBrowserLocale.substr(vBrowserLocaleVariantIndex+1);
+ vBrowserLocale = vBrowserLocale.substr(0, vBrowserLocaleVariantIndex);
+ }
+
+ var vPlatform = "none";
+ var vPlatformWindows = false;
+ var vPlatformMacintosh = false;
+ var vPlatformUnix = false;
+ var vPlatformOther = false;
+
+ if (vBrowserPlatform.indexOf("Windows") != -1 || vBrowserPlatform.indexOf("Win32") != -1 || vBrowserPlatform.indexOf("Win64") != -1)
+ {
+ vPlatformWindows = true;
+ vPlatform = "win";
+ }
+ else if (vBrowserPlatform.indexOf("Macintosh") != -1 || vBrowserPlatform.indexOf("MacIntel") != -1)
+ {
+ vPlatformMacintosh = true;
+ vPlatform = "mac";
+ }
+ else if (vBrowserPlatform.indexOf("X11") != -1 || vBrowserPlatform.indexOf("Linux") != -1 || vBrowserPlatform.indexOf("BSD") != -1)
+ {
+ vPlatformUnix = true;
+ vPlatform = "unix";
+ }
+ else
+ {
+ vPlatformOther = true;
+ vPlatform = "other";
+ }
+
+ var vGfxVml = false;
+ var vGfxSvg = false;
+ var vGfxSvgBuiltin = false;
+ var vGfxSvgPlugin = false;
+
+ if (vEngine == "mshtml")
+ {
+ vGfxVml = true;
+
+ // TODO: Namespace for VML:
+ // document.write('');
+ // document.write(' ');
+ }
+
+ if (document.implementation && document.implementation.hasFeature)
+ {
+ if (document.implementation.hasFeature("org.w3c.dom.svg", "1.0"))
+ {
+ vGfxSvg = vGfxSvgBuiltin = true;
+ }
+ }
+
+ this._runsLocally = vRunsLocally;
+
+ this._engineName = vEngine;
+ this._engineNameMshtml = vEngine === "mshtml";
+ this._engineNameGecko = vEngine === "gecko";
+ this._engineNameOpera = vEngine === "opera";
+ this._engineNameKhtml = vEngine === "khtml";
+ this._engineNameWebkit = vEngine === "webkit";
+
+ this._engineVersion = parseFloat(vEngineVersion);
+ this._engineVersionMajor = parseInt(vEngineVersionMajor);
+ this._engineVersionMinor = parseInt(vEngineVersionMinor);
+ this._engineVersionRevision = parseInt(vEngineVersionRevision);
+ this._engineVersionBuild = parseInt(vEngineVersionBuild);
+
+ this._engineQuirksMode = vEngineQuirksMode;
+ this._engineBoxSizingAttribute = vEngineBoxSizingAttr;
+ this._engineEmulation = vEngineEmulation;
+
+ this._defaultLocale = vDefaultLocale;
+
+ this._browserPlatform = vPlatform;
+ this._browserPlatformWindows = vPlatformWindows;
+ this._browserPlatformMacintosh = vPlatformMacintosh;
+ this._browserPlatformUnix = vPlatformUnix;
+ this._browserPlatformOther = vPlatformOther;
+ this._browserModeHta = vBrowserModeHta;
+ this._browserLocale = vBrowserLocale;
+ this._browserLocaleVariant = vBrowserLocaleVariant;
+
+ this._gfxVml = vGfxVml;
+ this._gfxSvg = vGfxSvg;
+ this._gfxSvgBuiltin = vGfxSvgBuiltin;
+ this._gfxSvgPlugin = vGfxSvgPlugin;
+
+ this._supportsTextContent = (document.documentElement.textContent !== undefined);
+ this._supportsInnerText = (document.documentElement.innerText !== undefined);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getRunsLocally = function() {
+ return this._runsLocally;
+}
+
+qx.Proto.getEngine = function() {
+ return this._engineName;
+}
+
+qx.Proto.getVersion = function() {
+ return this._engineVersion;
+}
+
+qx.Proto.getMajor = function() {
+ return this._engineVersionMajor;
+}
+
+qx.Proto.getMinor = function() {
+ return this._engineVersionMinor;
+}
+
+qx.Proto.getRevision = function() {
+ return this._engineVersionRevision;
+}
+
+qx.Proto.getBuild = function() {
+ return this._engineVersionBuild;
+}
+
+qx.Proto.getEmulation = function() {
+ return this._engineEmulation;
+}
+
+qx.Proto.isMshtml = function() {
+ return this._engineNameMshtml;
+}
+
+qx.Proto.isGecko = function() {
+ return this._engineNameGecko;
+}
+
+qx.Proto.isOpera = function() {
+ return this._engineNameOpera;
+}
+
+qx.Proto.isKhtml = function() {
+ return this._engineNameKhtml;
+}
+
+qx.Proto.isWebkit = function() {
+ return this._engineNameWebkit;
+}
+
+qx.Proto.isSafari2 = function() {
+ return this._engineNameWebkit && (this._engineVersion < 420);
+}
+
+qx.Proto.isInQuirksMode = function() {
+ return this._engineQuirksMode;
+}
+
+qx.Proto.getLocale = function() {
+ return this._browserLocale;
+}
+
+qx.Proto.getLocaleVariant = function() {
+ return this._browserLocaleVariant;
+}
+
+qx.Proto.getDefaultLocale = function() {
+ return this._defaultLocale;
+}
+
+qx.Proto.usesDefaultLocale = function() {
+ return this._browserLocale === this._defaultLocale;
+}
+
+
+
+/**
+ * Returns the CSS attribute name for box-sizing if supported.
+ *
+ * @return {string} the attribute name.
+ */
+qx.Proto.getEngineBoxSizingAttribute = function() {
+ return this._engineBoxSizingAttribute;
+}
+
+
+qx.Proto.getPlatform = function() {
+ return this._browserPlatform;
+}
+
+/**
+ * Returns whether the client platform is a Windows machine.
+ *
+ * @return {boolean} whether the client platform is a Windows.
+ */
+qx.Proto.runsOnWindows = function() {
+ return this._browserPlatformWindows;
+}
+
+/**
+ * Returns whether the client platform is a Macintosh machine.
+ *
+ * @return {boolean} whether the client platform is a Macintosh.
+ */
+qx.Proto.runsOnMacintosh = function() {
+ return this._browserPlatformMacintosh;
+}
+
+/**
+ * Returns whether the client platform is a X11 powered machine.
+ *
+ * @return {boolean} whether the client platform is a X11 powered machine.
+ */
+qx.Proto.runsOnUnix = function() {
+ return this._browserPlatformUnix;
+}
+
+qx.Proto.supportsVml = function() {
+ return this._gfxVml;
+}
+
+qx.Proto.supportsSvg = function() {
+ return this._gfxSvg;
+}
+
+qx.Proto.usesSvgBuiltin = function() {
+ return this._gfxSvgBuiltin;
+}
+
+qx.Proto.usesSvgPlugin = function() {
+ return this._gfxSvgPlugin;
+}
+
+
+/**
+ * Returns whether the client supports the W3C property textContent of DOM element nodes.
+ *
+ * @return {boolean} whether the client supports textContent.
+ */
+qx.Proto.supportsTextContent = function() {
+ return this._supportsTextContent;
+}
+
+
+/**
+ * Returns whether the client supports the W3C property innerText of DOM element nodes.
+ *
+ * @return {boolean} whether the client supports innerText.
+ */
+qx.Proto.supportsInnerText = function() {
+ return this._supportsInnerText;
+}
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/appearance/Classic.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/appearance/Classic.js
new file mode 100644
index 0000000000..c45c98db5d
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/appearance/Classic.js
@@ -0,0 +1,2219 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+ * Til Schneider (til132)
+
+ ************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#module(theme_appearance)
+#optional(qx.renderer.color.Color)
+#optional(qx.renderer.color.ColorObject)
+#optional(qx.renderer.border.Border)
+#optional(qx.renderer.border.BorderObject)
+#optional(qx.renderer.font.Font)
+#optional(qx.renderer.font.FontObject)
+
+ ************************************************************************ */
+
+qx.OO.defineClass("qx.theme.appearance.Classic", qx.renderer.theme.AppearanceTheme,
+function(vTitle) {
+ qx.renderer.theme.AppearanceTheme.call(this, vTitle || "qooxdoo default appearance");
+});
+
+
+
+
+qx.Proto._appearances = qx.lang.Object.carefullyMergeWith( {
+ /*
+ ---------------------------------------------------------------------------
+ CORE
+ ---------------------------------------------------------------------------
+ */
+
+ "image" : {
+ initial : function(vTheme) {
+ return {
+ allowStretchX : false,
+ allowStretchY : false
+ }
+ }
+ },
+
+ "client-document" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.ColorObject("threedface");
+ this.color = new qx.renderer.color.ColorObject("windowtext");
+ },
+
+ initial : function(vTheme) {
+ return {
+ backgroundColor : this.bgcolor,
+ color : this.color,
+ hideFocus : true,
+ enableElementFocus : false
+ }
+ }
+ },
+
+ "blocker" : {
+ initial : function(vTheme) {
+ // You could also use: "static/image/dotted_white.gif" for example as backgroundImage here
+ // (Visible) background tiles could be dramatically slow down mshtml!
+ // A background image or color is always needed for mshtml to block the events successfully.
+ return {
+ cursor : "default",
+ backgroundImage : "static/image/blank.gif"
+ }
+ }
+ },
+
+ "atom" : {
+ initial : function(vTheme) {
+ return {
+ cursor : "default",
+ spacing : 4,
+ width : "auto",
+ height : "auto",
+ horizontalChildrenAlign : "center",
+ verticalChildrenAlign : "middle",
+ stretchChildrenOrthogonalAxis : false,
+ allowStretchY : false,
+ allowStretchX : false
+ }
+ }
+ },
+
+ "label" : {
+ setup : function() {
+ this.color_disabled = new qx.renderer.color.ColorObject("graytext");
+ this.font = new qx.renderer.font.Font(11, '"Segoe UI", Corbel, Calibri, Tahoma, "Lucida Sans Unicode", sans-serif');
+ },
+
+ initial : function(vTheme) {
+ return {
+ font: this.font,
+ wrap : false
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ color : vStates.disabled ? this.color_disabled : null
+ }
+ }
+ },
+
+ "htmlcontainer" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("label");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("label", vStates);
+ }
+ },
+
+ "popup" : {
+ initial : function(vTheme) {
+ return {
+ width : "auto",
+ height : "auto"
+ }
+ }
+ },
+
+ "tool-tip" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.ColorObject("InfoBackground");
+ this.color = new qx.renderer.color.ColorObject("InfoText");
+ },
+
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("popup"), {
+ backgroundColor : this.bgcolor,
+ color : this.color,
+ border : qx.renderer.border.BorderPresets.getInstance().info,
+ paddingTop : 1,
+ paddingRight : 3,
+ paddingBottom : 2,
+ paddingLeft : 3
+ });
+ }
+ },
+
+ "iframe" : {
+ initial : function(vTheme) {
+ return {
+ border : qx.renderer.border.BorderPresets.getInstance().inset
+ }
+ }
+ },
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ BUTTON
+ ---------------------------------------------------------------------------
+ */
+
+ "button" : {
+ setup : function() {
+ this.bgcolor_default = new qx.renderer.color.ColorObject("buttonface");
+ this.bgcolor_over = new qx.renderer.color.Color("#87BCE5");
+ this.bgcolor_left = new qx.renderer.color.Color("#FFF0C9");
+
+ this.border_pressed = qx.renderer.border.BorderPresets.getInstance().inset;
+ this.border_default = qx.renderer.border.BorderPresets.getInstance().outset;
+ },
+
+ initial : function(vTheme) {
+ return vTheme.initialFrom("atom");
+ },
+
+ state : function(vTheme, vStates) {
+ var vReturn = {
+ backgroundColor : vStates.abandoned ? this.bgcolor_left : vStates.over ? this.bgcolor_over : this.bgcolor_default,
+ border : vStates.pressed || vStates.checked || vStates.abandoned ? this.border_pressed : this.border_default
+ }
+
+ if (vStates.pressed || vStates.abandoned) {
+ vReturn.paddingTop = 4;
+ vReturn.paddingRight = 3;
+ vReturn.paddingBottom = 2;
+ vReturn.paddingLeft = 5;
+ }
+ else {
+ vReturn.paddingTop = vReturn.paddingBottom = 3;
+ vReturn.paddingRight = vReturn.paddingLeft = 4;
+ }
+
+ return vReturn;
+ }
+ },
+
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ TOOLBAR
+ ---------------------------------------------------------------------------
+ */
+
+ "toolbar" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.ColorObject("threedface");
+ },
+
+ initial : function(vTheme) {
+ return {
+ border : qx.renderer.border.BorderPresets.getInstance().thinOutset,
+ backgroundColor : this.bgcolor,
+ height : "auto"
+ }
+ }
+ },
+
+ "toolbar-part" : {
+ initial : function(vTheme) {
+ return {
+ width : "auto"
+ }
+ }
+ },
+
+ "toolbar-part-handle" : {
+ initial : function(vTheme) {
+ return {
+ width : 10
+ }
+ }
+ },
+
+ "toolbar-part-handle-line" : {
+ initial : function(vTheme) {
+ return {
+ top : 2,
+ left : 3,
+ bottom : 2,
+ width : 4,
+ border : qx.renderer.border.BorderPresets.getInstance().thinOutset
+ }
+ }
+ },
+
+ "toolbar-separator" : {
+ initial : function(vTheme) {
+ return {
+ width : 8
+ }
+ }
+ },
+
+ "toolbar-separator-line" : {
+ setup : function() {
+ var b = this.border = new qx.renderer.border.BorderObject;
+
+ b.setLeftColor("threedshadow");
+ b.setRightColor("threedhighlight");
+
+ b.setLeftStyle("solid");
+ b.setRightStyle("solid");
+
+ b.setLeftWidth(1);
+ b.setRightWidth(1);
+ b.setTopWidth(0);
+ b.setBottomWidth(0);
+ },
+
+ initial : function(vTheme) {
+ return {
+ top : 2,
+ left: 2,
+ width : 2,
+ bottom : 2,
+ border : this.border
+ }
+ }
+ },
+
+ "toolbar-button" : {
+ setup : function() {
+ this.bgcolor_default = new qx.renderer.color.ColorObject("buttonface");
+ this.bgcolor_left = new qx.renderer.color.Color("#FFF0C9");
+
+ this.border_pressed = qx.renderer.border.BorderPresets.getInstance().thinInset;
+ this.border_over = qx.renderer.border.BorderPresets.getInstance().thinOutset;
+ this.border_default = qx.renderer.border.BorderPresets.getInstance().none;
+
+ this.checked_background = "static/image/dotted_white.gif";
+ },
+
+ initial : function(vTheme) {
+ return {
+ cursor : "default",
+ spacing : 4,
+ width : "auto",
+ verticalChildrenAlign : "middle"
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ var vReturn = {
+ backgroundColor : vStates.abandoned ? this.bgcolor_left : this.bgcolor_default,
+ backgroundImage : vStates.checked && !vStates.over ? this.checked_background : null
+ }
+
+ if (vStates.pressed || vStates.checked || vStates.abandoned) {
+ vReturn.border = this.border_pressed;
+
+ vReturn.paddingTop = 3;
+ vReturn.paddingRight = 2;
+ vReturn.paddingBottom = 1;
+ vReturn.paddingLeft = 4;
+ } else if (vStates.over) {
+ vReturn.border = this.border_over;
+
+ vReturn.paddingTop = vReturn.paddingBottom = 2;
+ vReturn.paddingLeft = vReturn.paddingRight = 3;
+ } else {
+ vReturn.border = this.border_default;
+
+ vReturn.paddingTop = vReturn.paddingBottom = 3;
+ vReturn.paddingLeft = vReturn.paddingRight = 4;
+ }
+
+ return vReturn;
+ }
+ },
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ BAR VIEW
+ ---------------------------------------------------------------------------
+ */
+
+ "bar-view" : {
+ setup : function() {
+ this.background = new qx.renderer.color.ColorObject("#FAFBFE");
+ },
+
+ initial : function(vTheme) {
+ return {
+ backgroundColor : this.background,
+ border : qx.renderer.border.BorderPresets.getInstance().shadow
+ }
+ }
+ },
+
+ "bar-view-pane" : {
+ state : function(vTheme, vStates) {
+ if (vStates.barHorizontal) {
+ return {
+ width : null,
+ height : "1*"
+ }
+ }
+ else {
+ return {
+ width : "1*",
+ height : null
+ }
+ }
+ }
+ },
+
+ "bar-view-page" : {
+ initial : function(vTheme) {
+ return {
+ left : 10,
+ right : 10,
+ top : 10,
+ bottom : 10
+ }
+ }
+ },
+
+ "bar-view-bar" : {
+ setup : function() {
+ this.background_color = new qx.renderer.color.ColorObject("#E1EEFF");
+
+ this.border_color = new qx.renderer.color.ColorObject("threedshadow");
+
+ this.border_top = new qx.renderer.border.BorderObject;
+ this.border_top.setBottom(1, "solid", this.border_color);
+
+ this.border_bottom = new qx.renderer.border.BorderObject;
+ this.border_bottom.setTop(1, "solid", this.border_color);
+
+ this.border_left = new qx.renderer.border.BorderObject;
+ this.border_left.setRight(1, "solid", this.border_color);
+
+ this.border_right = new qx.renderer.border.BorderObject;
+ this.border_right.setLeft(1, "solid", this.border_color);
+ },
+
+ initial : function(vTheme) {
+ return {
+ backgroundColor : this.background_color
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ if (vStates.barTop) {
+ return {
+ paddingTop : 1,
+ paddingRight : 0,
+ paddingBottom : 1,
+ paddingLeft : 0,
+
+ border : this.border_top,
+ height : "auto",
+ width : null,
+ orientation : "horizontal"
+ };
+ }
+ else if (vStates.barBottom) {
+ return {
+ paddingTop : 1,
+ paddingRight : 0,
+ paddingBottom : 1,
+ paddingLeft : 0,
+
+ border : this.border_bottom,
+ height : "auto",
+ width : null,
+ orientation : "horizontal"
+ };
+ }
+ else if (vStates.barLeft) {
+ return {
+ paddingTop : 0,
+ paddingRight : 1,
+ paddingBottom : 0,
+ paddingLeft : 1,
+
+ border : this.border_left,
+ height : null,
+ width : "auto",
+ orientation : "vertical"
+ };
+ }
+ else if (vStates.barRight) {
+ return {
+ paddingTop : 0,
+ paddingRight : 1,
+ paddingBottom : 0,
+ paddingLeft : 1,
+
+ border : this.border_right,
+ height : null,
+ width : "auto",
+ orientation : "vertical"
+ };
+ }
+ }
+ },
+
+ "bar-view-button" : {
+ setup : function() {
+ this.background_color_normal = null;
+ this.background_color_checked = new qx.renderer.color.ColorObject("#FAFBFE");
+
+ this.border_color = new qx.renderer.color.ColorObject("threedshadow");
+ this.border_color_checked = new qx.renderer.color.ColorObject("#FEC83C");
+
+ this.border_top_checked = new qx.renderer.border.Border(1, "solid", this.border_color);
+ this.border_top_checked.setBottom(3, "solid", this.border_color_checked);
+
+ this.border_bottom_checked = new qx.renderer.border.Border(1, "solid", this.border_color);
+ this.border_bottom_checked.setTop(3, "solid", this.border_color_checked);
+
+ this.border_left_checked = new qx.renderer.border.Border(1, "solid", this.border_color);
+ this.border_left_checked.setRight(3, "solid", this.border_color_checked);
+
+ this.border_right_checked = new qx.renderer.border.Border(1, "solid", this.border_color);
+ this.border_right_checked.setLeft(3, "solid", this.border_color_checked);
+ },
+
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("atom"), {
+ iconPosition : "top"
+ });
+ },
+
+ state : function(vTheme, vStates) {
+ var vReturn = {
+ backgroundColor : vStates.checked ? this.background_color_checked : this.background_color_normal,
+ allowStretchX : true,
+ allowStretchY : true
+ }
+
+ if (vStates.checked || vStates.over) {
+ if (vStates.barTop) {
+ vReturn.border = this.border_top_checked;
+ vReturn.paddingTop = 3;
+ vReturn.paddingRight = 6;
+ vReturn.paddingBottom = 1;
+ vReturn.paddingLeft = 6;
+ }
+ else if (vStates.barBottom) {
+ vReturn.border = this.border_bottom_checked;
+ vReturn.paddingTop = 1;
+ vReturn.paddingRight = 6;
+ vReturn.paddingBottom = 3;
+ vReturn.paddingLeft = 6;
+ }
+ else if (vStates.barLeft) {
+ vReturn.border = this.border_left_checked;
+ vReturn.paddingTop = 3;
+ vReturn.paddingRight = 4;
+ vReturn.paddingBottom = 3;
+ vReturn.paddingLeft = 6;
+ }
+ else if (vStates.barRight) {
+ vReturn.border = this.border_right_checked;
+ vReturn.paddingTop = 3;
+ vReturn.paddingRight = 6;
+ vReturn.paddingBottom = 3;
+ vReturn.paddingLeft = 4;
+ }
+ }
+ else {
+ vReturn.border = qx.renderer.border.BorderPresets.getInstance().none;
+ vReturn.paddingTop = vReturn.paddingBottom = 4;
+ vReturn.paddingRight = vReturn.paddingLeft = 7;
+ }
+
+ if (vStates.barTop || vStates.barBottom) {
+ vReturn.marginTop = vReturn.marginBottom = 0;
+ vReturn.marginRight = vReturn.marginLeft = 1;
+ vReturn.width = "auto";
+ vReturn.height = null;
+ }
+ else if (vStates.barLeft || vStates.barRight) {
+ vReturn.marginTop = vReturn.marginBottom = 1;
+ vReturn.marginRight = vReturn.marginLeft = 0;
+ vReturn.height = "auto";
+ vReturn.width = null;
+ }
+
+ return vReturn;
+ }
+ },
+
+
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ WINDOW
+ ---------------------------------------------------------------------------
+ */
+
+ "window" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.ColorObject("threedface");
+ this.color = new qx.renderer.color.ColorObject("windowtext");
+ },
+
+ initial : function(vTheme) {
+ return {
+ backgroundColor : this.bgcolor,
+ color : this.color,
+ paddingTop : 1,
+ paddingRight : 1,
+ paddingBottom : 1,
+ paddingLeft : 1
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ border : vStates.maximized ? qx.renderer.border.BorderPresets.getInstance().none : qx.renderer.border.BorderPresets.getInstance().outset
+ }
+ }
+ },
+
+ "window-captionbar" : {
+ setup : function() {
+ this.bgcolor_active = new qx.renderer.color.ColorObject("activecaption");
+ this.color_active = new qx.renderer.color.ColorObject("captiontext");
+ this.bgcolor_inactive = new qx.renderer.color.ColorObject("inactivecaption");
+ this.color_inactive = new qx.renderer.color.ColorObject("inactivecaptiontext");
+ },
+
+ initial : function(vTheme) {
+ return {
+ paddingTop : 1,
+ paddingRight : 2,
+ paddingBottom : 2,
+ paddingLeft : 2,
+ verticalChildrenAlign : "middle",
+ height : "auto",
+ overflow : "hidden"
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ backgroundColor : vStates.active ? this.bgcolor_active : this.bgcolor_inactive,
+ color : vStates.active ? this.color_active : this.color_inactive
+ }
+ }
+ },
+
+ "window-resize-frame" : {
+ initial : function(vTheme) {
+ return {
+ border : qx.renderer.border.BorderPresets.getInstance().shadow
+ }
+ }
+ },
+
+ "window-captionbar-icon" : {
+ initial : function(vTheme) {
+ return {
+ marginRight : 2
+ }
+ }
+ },
+
+ "window-captionbar-title" : {
+ setup : function() {
+ this.font = new qx.renderer.font.Font(11, '"Segoe UI", Corbel, Calibri, Tahoma, "Lucida Sans Unicode", sans-serif');
+ this.font.setBold(true);
+ },
+
+ initial : function(vTheme) {
+ return {
+ cursor : "default",
+ font : this.font,
+ marginRight : 2,
+ wrap : false
+ }
+ }
+ },
+
+ "window-captionbar-button" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("button");
+ },
+
+ state : function(vTheme, vStates) {
+ var vReturn = vTheme.stateFrom("button", vStates);
+
+ if (vStates.pressed || vStates.abandoned) {
+ vReturn.paddingTop = 2;
+ vReturn.paddingRight = 1;
+ vReturn.paddingBottom = 0;
+ vReturn.paddingLeft = 3;
+ }
+ else {
+ vReturn.paddingTop = vReturn.paddingBottom = 1;
+ vReturn.paddingRight = vReturn.paddingLeft = 2;
+ }
+
+ return vReturn;
+ }
+ },
+
+ "window-captionbar-minimize-button" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("window-captionbar-button");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("window-captionbar-button", vStates);
+ }
+ },
+
+ "window-captionbar-restore-button" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("window-captionbar-button");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("window-captionbar-button", vStates);
+ }
+ },
+
+ "window-captionbar-maximize-button" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("window-captionbar-button");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("window-captionbar-button", vStates);
+ }
+ },
+
+ "window-captionbar-close-button" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("window-captionbar-button"), {
+ marginLeft : 2
+ });
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("window-captionbar-button", vStates);
+ }
+ },
+
+ "window-statusbar" : {
+ initial : function(vTheme) {
+ return {
+ border : qx.renderer.border.BorderPresets.getInstance().thinInset,
+ height : "auto"
+ }
+ }
+ },
+
+ "window-statusbar-text" : {
+ initial : function(vTheme) {
+ return {
+ paddingTop : 1,
+ paddingRight : 4,
+ paddingBottom : 1,
+ paddingLeft : 4,
+ cursor : "default"
+ }
+ }
+ },
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ RESIZER
+ ---------------------------------------------------------------------------
+ */
+
+ "resizer": {
+ initial: function(vTheme) {
+ return {
+ border : qx.renderer.border.BorderPresets.getInstance().outset
+ }
+ }
+ },
+
+ "resizer-frame" : {
+ initial : function(vTheme) {
+ return {
+ border : qx.renderer.border.BorderPresets.getInstance().shadow
+ }
+ }
+ },
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ MENU
+ ---------------------------------------------------------------------------
+ */
+
+ "menu" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.ColorObject("menu");
+ },
+
+ initial : function(vTheme) {
+ return {
+ width : "auto",
+ height : "auto",
+ backgroundColor : this.bgcolor,
+ border : qx.renderer.border.BorderPresets.getInstance().outset,
+ paddingTop : 1,
+ paddingRight : 1,
+ paddingBottom : 1,
+ paddingLeft : 1
+ }
+ }
+ },
+
+ "menu-layout" : {
+ initial : function(vTheme) {
+ return {
+ top : 0,
+ right : 0,
+ bottom : 0,
+ left : 0
+ }
+ }
+ },
+
+ "menu-button" : {
+ setup : function() {
+ this.BGCOLOR_OVER = new qx.renderer.color.ColorObject("highlight");
+ this.BGCOLOR_OUT = null;
+
+ this.COLOR_OVER = new qx.renderer.color.ColorObject("highlighttext");
+ this.COLOR_OUT = null;
+ },
+
+ initial : function(vTheme) {
+ return {
+ minWidth : "auto",
+ height : "auto",
+ spacing : 2,
+ paddingTop : 2,
+ paddingRight : 4,
+ paddingBottom : 2,
+ paddingLeft : 4,
+ cursor : "default",
+ verticalChildrenAlign : "middle",
+ allowStretchX : true
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ backgroundColor : vStates.over ? this.BGCOLOR_OVER : this.BGCOLOR_OUT,
+ color : vStates.over ? this.COLOR_OVER : this.COLOR_OUT
+ }
+ }
+ },
+
+ "menu-check-box" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("menu-button");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("menu-button", vStates);
+ }
+ },
+
+ "menu-radio-button" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("menu-button");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("menu-button", vStates);
+ }
+ },
+
+ "menu-separator" : {
+ initial : function(vTheme) {
+ return {
+ height : "auto",
+ marginTop : 3,
+ marginBottom : 2,
+ paddingLeft : 3,
+ paddingRight : 3
+ }
+ }
+ },
+
+ "menu-separator-line" : {
+ initial : function(vTheme) {
+ return {
+ right : 0,
+ left : 0,
+ height : "auto",
+ border : qx.renderer.border.BorderPresets.getInstance().verticalDivider
+ }
+ }
+ },
+
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ LIST
+ ---------------------------------------------------------------------------
+ */
+
+ "list" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.Color("white");
+ },
+
+ initial : function(vTheme) {
+ return {
+ overflow : "hidden",
+ border : qx.renderer.border.BorderPresets.getInstance().thinInset,
+ backgroundColor : this.bgcolor
+ }
+ }
+ },
+
+ "list-item" : {
+ setup : function() {
+ this.bgcolor_selected = new qx.renderer.color.ColorObject("highlight");
+ this.color_selected = new qx.renderer.color.ColorObject("highlighttext");
+ },
+
+ initial : function(vTheme) {
+ return {
+ cursor : "default",
+ height : "auto",
+ horizontalChildrenAlign : "left",
+ verticalChildrenAlign : "middle",
+ spacing : 4,
+ paddingTop : 3,
+ paddingRight : 5,
+ paddingBottom : 3,
+ paddingLeft : 5,
+ minWidth : "auto"
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ backgroundColor : vStates.selected ? this.bgcolor_selected : null,
+ color : vStates.selected ? this.color_selected : null
+ }
+ }
+ },
+
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ FIELDS
+ ---------------------------------------------------------------------------
+ */
+
+ "text-field" : {
+ setup : function() {
+ this.font = new qx.renderer.font.Font(11, '"Segoe UI", Corbel, Calibri, Tahoma, "Lucida Sans Unicode", sans-serif');
+ },
+
+ initial : function(vTheme) {
+ return {
+ hideFocus : true,
+ border : qx.renderer.border.BorderPresets.getInstance().inset,
+ paddingTop : 1,
+ paddingRight : 3,
+ paddingBottom : 1,
+ paddingLeft : 3,
+ allowStretchY : false,
+ allowStretchX : true,
+ font : this.font,
+ width : "auto",
+ height : "auto"
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("label", vStates);
+ }
+ },
+
+ "text-area" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("text-field"), {
+ overflow : "auto",
+
+ // gecko automatically defines a marginTop/marginBottom of 1px. We need to reset these values.
+ marginTop : 0,
+ marginBottom : 0
+ });
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("text-field", vStates);
+ }
+ },
+
+
+
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ COMBOBOX
+ ---------------------------------------------------------------------------
+ */
+
+ "combo-box" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.Color("white");
+ },
+
+ initial : function(vTheme) {
+ return {
+ minWidth : 40,
+ width : 120,
+ height : "auto",
+ border : qx.renderer.border.BorderPresets.getInstance().inset,
+ backgroundColor : this.bgcolor,
+ allowStretchY : false
+ }
+ }
+ },
+
+ "combo-box-ex" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.Color("white");
+ },
+
+ initial : function(vTheme) {
+ return {
+ width : "auto",
+ height : "auto",
+ border : qx.renderer.border.BorderPresets.getInstance().inset,
+ backgroundColor : this.bgcolor,
+ allowStretchY : false
+ }
+ }
+ },
+
+ "combo-box-list" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("list"), {
+ top : 0,
+ right : 0,
+ bottom : 0,
+ left : 0,
+ border : null,
+ overflow : "scrollY"
+ });
+ }
+ },
+
+ "combo-box-ex-list" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("list"), {
+ statusBarVisible: false,
+ columnVisibilityButtonVisible: false,
+ height: 'auto',
+ maxHeight: 150,
+ top : 0,
+ left : 0,
+ border : null
+ });
+ }
+ },
+
+ "combo-box-popup" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("list"), {
+ height : "auto",
+ maxHeight : 150,
+ border : qx.renderer.border.BorderPresets.getInstance().shadow
+ });
+ }
+ },
+
+ "combo-box-ex-popup" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("list"), {
+ width: "auto",
+ height : "auto",
+ border : qx.renderer.border.BorderPresets.getInstance().shadow
+ });
+ }
+ },
+
+ "combo-box-text-field" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.Color("transparent");
+ },
+
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("text-field"), {
+ border : qx.renderer.border.BorderPresets.getInstance().none,
+ width : "1*",
+ backgroundColor : this.bgcolor
+ });
+ }
+ },
+
+ "combo-box-ex-text-field" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.Color("transparent");
+ },
+
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("text-field"), {
+ border : qx.renderer.border.BorderPresets.getInstance().none,
+ minWidth : 30,
+ width : 100,
+ backgroundColor : this.bgcolor
+ });
+ }
+ },
+
+ // Used both for ComboBox and ComboBoxEx
+ "combo-box-button" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("button"), {
+ height : null,
+ allowStretchY : true
+ });
+ },
+
+ state : function(vTheme, vStates) {
+ return qx.lang.Object.mergeWith(vTheme.stateFrom("button", vStates), {
+ paddingTop : 0,
+ paddingRight : 3,
+ paddingBottom : 0,
+ paddingLeft : 2
+ });
+ }
+ },
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ TREE
+ ---------------------------------------------------------------------------
+ */
+
+ "tree-element" : {
+ initial : function(vTheme) {
+ return {
+ height : 16,
+ verticalChildrenAlign : "middle"
+ }
+ }
+ },
+
+ "tree-element-icon" : {
+ initial : function(vTheme) {
+ return {
+ width : 16,
+ height : 16
+ }
+ }
+ },
+
+ "tree-element-label" : {
+ setup : function() {
+ this.bgcolor_selected = new qx.renderer.color.ColorObject("highlight");
+ this.color_selected = new qx.renderer.color.ColorObject("highlighttext");
+ },
+
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("label"), {
+ cursor : "default",
+ marginLeft : 3,
+ height : 15,
+ paddingTop : 2,
+ paddingRight : 2,
+ paddingBottom : 2,
+ paddingLeft : 2,
+ allowStretchY : false
+ });
+ },
+
+ state : function(vTheme, vStates) {
+ return qx.lang.Object.mergeWith(vTheme.stateFrom("label", vStates), {
+ backgroundColor : vStates.selected ? this.bgcolor_selected : null,
+ color : vStates.selected ? this.color_selected : null
+ });
+ }
+ },
+
+ "tree-folder" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("tree-element");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("tree-element", vStates);
+ }
+ },
+
+ "tree-folder-icon" : {
+ initial : function(vTheme) {
+ return {
+ width : 16,
+ height : 16
+ }
+ }
+ },
+
+ "tree-folder-label" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("tree-element-label");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("tree-element-label", vStates);
+ }
+ },
+
+ "tree" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("tree-folder");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("tree-folder", vStates);
+ }
+ },
+
+ "tree-icon" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("tree-folder-icon");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("tree-folder-icon", vStates);
+ }
+ },
+
+ "tree-label" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("tree-folder-label");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("tree-folder-label", vStates);
+ }
+ },
+
+ "tree-container" : {
+ initial : function(vTheme) {
+ return {
+ verticalChildrenAlign : "top"
+ }
+ }
+ },
+
+ "tree-folder-container" : {
+ initial : function(vTheme) {
+ return {
+ height : "auto",
+ verticalChildrenAlign : "top"
+ }
+ }
+ },
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ LISTVIEW
+ ---------------------------------------------------------------------------
+ */
+
+ "list-view" : {
+ initial : function(vTheme) {
+ return {
+ cursor : "default",
+ overflow: "hidden"
+ }
+ }
+ },
+
+ "list-view-pane" : {
+ initial : function(vTheme) {
+ return {
+ width : "1*",
+ horizontalSpacing : 1,
+ overflow : "hidden"
+ }
+ }
+ },
+
+ "list-view-header" : {
+ setup : function() {
+ this.border = new qx.renderer.border.Border;
+ this.border.setBottom(1, "solid", "#e2e2e2");
+
+ this.bgcolor = new qx.renderer.color.Color("#f2f2f2");
+ },
+
+ initial : function(vTheme) {
+ return {
+ height : "auto",
+ overflow: "hidden",
+ border : this.border,
+ backgroundColor : this.bgcolor
+ }
+ }
+ },
+
+ "list-view-header-cell" : {
+ setup : function() {
+ this.border_hover = new qx.renderer.border.Border;
+ this.border_hover.setBottom(2, "solid", "#F9B119");
+
+ this.bgcolor_hover = new qx.renderer.color.Color("white");
+ },
+
+ initial : function(vTheme) {
+ return {
+ overflow : "hidden",
+ paddingTop : 2,
+ paddingRight : 6,
+ paddingBottom : 2,
+ paddingLeft : 6,
+ spacing : 4
+ };
+ },
+
+ state : function(vTheme, vStates) {
+ if (vStates.over) {
+ return {
+ backgroundColor : this.bgcolor_hover,
+ paddingBottom : 0,
+ border : this.border_hover
+ };
+ }
+ else {
+ return {
+ backgroundColor : null,
+ paddingBottom : 2,
+ border : null
+ };
+ }
+ }
+ },
+
+ "list-view-header-separator" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.Color("#D6D5D9");
+ },
+
+ initial : function(vTheme) {
+ return {
+ backgroundColor : this.bgcolor,
+ width : 1,
+ marginTop : 1,
+ marginBottom : 1
+ };
+ }
+ },
+
+ "list-view-content-cell" : {
+ setup : function() {
+ this.bgcolor_selected = new qx.renderer.color.ColorObject("highlight");
+ this.color_selected = new qx.renderer.color.ColorObject("highlighttext");
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ backgroundColor : vStates.selected ? this.bgcolor_selected : null,
+ color : vStates.selected ? this.color_selected : null
+ };
+ }
+ },
+
+ "list-view-content-cell-image" : {
+ initial : function(vTheme) {
+ return {
+ paddingLeft : 6,
+ paddingRight : 6
+ };
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("list-view-content-cell", vStates);
+ }
+ },
+
+ "list-view-content-cell-text" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("htmlcontainer"), {
+ overflow: "hidden",
+ paddingLeft : 6,
+ paddingRight : 6
+ });
+ },
+
+ state : function(vTheme, vStates) {
+ return qx.lang.Object.mergeWith(vTheme.stateFrom("htmlcontainer", vStates), vTheme.stateFrom("list-view-content-cell", vStates));
+ }
+ },
+
+ "list-view-content-cell-html" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("list-view-content-cell-text");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("list-view-content-cell-text", vStates);
+ }
+ },
+
+ "list-view-content-cell-icon-html" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("list-view-content-cell-text");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("list-view-content-cell-text", vStates);
+ }
+ },
+
+ "list-view-content-cell-link" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("list-view-content-cell-text");
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("list-view-content-cell-text", vStates);
+ }
+ },
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ TABVIEW
+ ---------------------------------------------------------------------------
+ */
+
+ "tab-view" : {
+ initial : function(vTheme) {
+ return {
+ spacing : -1
+ };
+ }
+ },
+
+ "tab-view-bar" : {
+ initial : function(vTheme) {
+ return {
+ height : "auto"
+ };
+ }
+ },
+
+ "tab-view-pane" : {
+ setup : function() {
+ this.border = new qx.renderer.border.Border(1, "solid", "#91A5BD");
+ this.bgcolor = new qx.renderer.color.ColorObject("#FAFBFE");
+ },
+
+ initial : function(vTheme) {
+ return {
+ height : "1*",
+ backgroundColor : this.bgcolor,
+ border : this.border,
+ paddingTop : 10,
+ paddingRight : 10,
+ paddingBottom : 10,
+ paddingLeft : 10
+ };
+ }
+ },
+
+ "tab-view-page" : {
+ initial : function(vTheme) {
+ return {
+ top : 0,
+ right : 0,
+ bottom : 0,
+ left : 0
+ };
+ }
+ },
+
+ "tab-view-button" : {
+ setup : function() {
+ this.bgcolor_normal = new qx.renderer.color.ColorObject("#E1EEFF");
+ this.bgcolor_checked = new qx.renderer.color.ColorObject("#FAFBFE");
+
+ this.border_top_normal = new qx.renderer.border.Border(1, "solid", "#91A5BD");
+ this.border_top_normal.setBottomWidth(0);
+
+ this.border_top_checked = new qx.renderer.border.Border(1, "solid", "#91A5BD");
+ this.border_top_checked.setBottomWidth(0);
+ this.border_top_checked.setTop(3, "solid", "#FEC83C");
+
+ this.border_bottom_normal = new qx.renderer.border.Border(1, "solid", "#91A5BD");
+ this.border_bottom_normal.setTopWidth(0);
+
+ this.border_bottom_checked = new qx.renderer.border.Border(1, "solid", "#91A5BD");
+ this.border_bottom_checked.setTopWidth(0);
+ this.border_bottom_checked.setBottom(3, "solid", "#FEC83C");
+ },
+
+ initial : function(vTheme) {
+ return vTheme.initialFrom("atom");
+ },
+
+ state : function(vTheme, vStates) {
+ var vReturn;
+
+ if (vStates.checked) {
+ vReturn = {
+ backgroundColor : this.bgcolor_checked,
+ zIndex : 1,
+ paddingTop : 2,
+ paddingBottom : 4,
+ paddingLeft : 7,
+ paddingRight : 8,
+ border : vStates.barTop ? this.border_top_checked : this.border_bottom_checked,
+ marginTop : 0,
+ marginBottom : 0,
+ marginRight : -1,
+ marginLeft : -2
+ }
+
+ if (vStates.alignLeft) {
+ if (vStates.firstChild) {
+ vReturn.paddingLeft = 6;
+ vReturn.paddingRight = 7;
+ vReturn.marginLeft = 0;
+ }
+ }
+ else {
+ if (vStates.lastChild) {
+ vReturn.paddingLeft = 8;
+ vReturn.paddingRight = 5;
+ vReturn.marginRight = 0;
+ }
+ }
+ }
+ else {
+ vReturn = {
+ backgroundColor : vStates.over ? this.bgcolor_checked : this.bgcolor_normal,
+ zIndex : 0,
+ paddingTop : 2,
+ paddingBottom : 2,
+ paddingLeft : 5,
+ paddingRight : 6,
+ marginRight : 1,
+ marginLeft : 0
+ }
+
+ if (vStates.alignLeft) {
+ if (vStates.firstChild) {
+ vReturn.paddingLeft = 6;
+ vReturn.paddingRight = 5;
+ }
+ }
+ else {
+ if (vStates.lastChild) {
+ vReturn.paddingLeft = 6;
+ vReturn.paddingRight = 5;
+ vReturn.marginRight = 0;
+ }
+ }
+
+ if (vStates.barTop) {
+ vReturn.border = this.border_top_normal;
+ vReturn.marginTop = 3;
+ vReturn.marginBottom = 1;
+ }
+ else {
+ vReturn.border = this.border_bottom_normal;
+ vReturn.marginTop = 1;
+ vReturn.marginBottom = 3;
+ }
+ }
+
+ return vReturn;
+ }
+ },
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ FIELDSET
+ ---------------------------------------------------------------------------
+ */
+
+ "field-set" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.ColorObject("threedface");
+ },
+
+ initial : function(vTheme) {
+ return {
+ backgroundColor : this.bgcolor
+ }
+ }
+ },
+
+ "field-set-legend" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.ColorObject("threedface");
+ },
+
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("atom"), {
+ top : 1,
+ left : 10,
+ backgroundColor : this.bgcolor,
+ paddingRight : 3,
+ paddingLeft : 4,
+ marginRight: 10
+ });
+ }
+ },
+
+ "field-set-frame" : {
+ initial : function(vTheme) {
+ return {
+ top : 8,
+ left : 2,
+ right : 2,
+ bottom : 2,
+ paddingTop : 12,
+ paddingRight : 9,
+ paddingBottom : 12,
+ paddingLeft : 9,
+ border : qx.renderer.border.BorderPresets.getInstance().groove
+ }
+ }
+ },
+
+ "check-box-field-set-legend" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.ColorObject("threedface");
+ },
+
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("atom"), {
+ top : 1,
+ left : 10,
+ backgroundColor : this.bgcolor,
+ paddingRight : 3
+ });
+ }
+ },
+
+ "radio-button-field-set-legend" : {
+ initial : function(vTheme) {
+ return vTheme.initialFrom("check-box-field-set-legend");
+ }
+ },
+
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ SPINNER
+ ---------------------------------------------------------------------------
+ */
+
+ "spinner" : {
+ setup : function() {
+ this.bgcolor = new qx.renderer.color.Color("white");
+ },
+
+ initial : function(vTheme) {
+ return {
+ width : 60,
+ height : 22,
+ border : qx.renderer.border.BorderPresets.getInstance().inset,
+ backgroundColor : this.bgcolor
+ }
+ }
+ },
+
+ "spinner-field" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("text-field"), {
+ width : "1*",
+ border : qx.renderer.border.BorderPresets.getInstance().none
+ });
+ },
+
+ state : function(vTheme, vStates) {
+ return vTheme.stateFrom("text-field", vStates);
+ }
+ },
+
+ "spinner-button-up" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("image"), {
+ height: "1*",
+ width: 16,
+ backgroundColor: new qx.renderer.color.ColorObject("threedface")
+ });
+ },
+
+ state : function(vTheme, vStates) {
+ return qx.lang.Object.mergeWith(vTheme.stateFrom("button", vStates), {
+ paddingTop : 0,
+ paddingRight : 0,
+ paddingBottom: 0,
+ paddingLeft : 3
+ });
+ }
+ },
+
+ "spinner-button-down" : {
+ initial : function(vTheme) {
+ return qx.lang.Object.mergeWith(vTheme.initialFrom("image"), {
+ height: "1*",
+ width: 16,
+ backgroundColor: new qx.renderer.color.ColorObject("threedface")
+ });
+ },
+
+ state : function(vTheme, vStates) {
+ return qx.lang.Object.mergeWith(vTheme.stateFrom("button", vStates), {
+ paddingTop : 1,
+ paddingRight : 0,
+ paddingBottom: 0,
+ paddingLeft : 3
+ });
+ }
+ },
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ COLORSELECTOR
+ ---------------------------------------------------------------------------
+ */
+
+ "colorselector" : {
+ setup : function() {
+ this.border = qx.renderer.border.BorderPresets.getInstance().outset;
+ },
+
+ initial : function(vTheme) {
+ return {
+ border : this.border,
+ width: "auto",
+ height: "auto"
+ }
+ },
+
+ state : function(vTheme, vStates) {
+
+ }
+ },
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ DATECHOOSER
+ ---------------------------------------------------------------------------
+ */
+
+ "datechooser-toolbar-button" : {
+ setup : function() {
+ this.bgcolor_default = new qx.renderer.color.ColorObject("buttonface");
+ this.bgcolor_left = new qx.renderer.color.Color("#FFF0C9");
+
+ this.border_pressed = qx.renderer.border.BorderPresets.getInstance().thinInset;
+ this.border_over = qx.renderer.border.BorderPresets.getInstance().thinOutset;
+ this.border_default = null;
+
+ this.checked_background = "static/image/dotted_white.gif";
+ },
+
+ initial : function(vTheme) {
+ return {
+ cursor : "default",
+ spacing : 4,
+ width : "auto",
+ verticalChildrenAlign : "middle"
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ var vReturn = {
+ backgroundColor : vStates.abandoned ? this.bgcolor_left : this.bgcolor_default,
+ backgroundImage : (vStates.checked && !vStates.over) ? this.checked_background : null
+ }
+
+ if (vStates.pressed || vStates.checked || vStates.abandoned) {
+ vReturn.border = this.border_pressed;
+ } else if (vStates.over) {
+ vReturn.border = this.border_over;
+ } else {
+ vReturn.border = this.border_default;
+ }
+
+ if (vStates.pressed || vStates.checked || vStates.abandoned) {
+ vReturn.paddingTop = 2;
+ vReturn.paddingRight = 0;
+ vReturn.paddingBottom = 0;
+ vReturn.paddingLeft = 2;
+ } else if (vStates.over) {
+ vReturn.paddingTop = vReturn.paddingBottom = 1;
+ vReturn.paddingLeft = vReturn.paddingRight = 1;
+ } else {
+ vReturn.paddingTop = vReturn.paddingBottom = 2;
+ vReturn.paddingLeft = vReturn.paddingRight = 2;
+ }
+
+ return vReturn;
+ }
+ },
+
+
+ "datechooser-monthyear" : {
+ setup : function() {
+ this.font = new qx.renderer.font.Font(13, '"Segoe UI", Corbel, Calibri, Tahoma, "Lucida Sans Unicode", sans-serif');
+ },
+
+ initial : function(vTheme) {
+ return {
+ font : this.font,
+ textAlign: "center",
+ verticalAlign: "middle"
+ }
+ }
+ },
+
+
+ "datechooser-datepane" : {
+ setup : function() {
+ this.border = new qx.renderer.border.Border(1, "solid", "gray");
+ this.bgcolor = new qx.renderer.color.ColorObject("window");
+ },
+
+ initial : function(vTheme) {
+ return {
+ border : this.border,
+ backgroundColor : this.bgcolor
+ }
+ }
+ },
+
+
+ "datechooser-weekday" : {
+ setup : function() {
+ this.border = new qx.renderer.border.Border;
+ this.border.set({ bottomColor:"gray", bottomStyle :"solid", bottomWidth:1 });
+ this.color = new qx.renderer.color.ColorObject("window");
+ this.bgcolor = new qx.renderer.color.ColorObject("#6285BA");
+ this.font = new qx.renderer.font.Font(11, '"Segoe UI", Corbel, Calibri, Tahoma, "Lucida Sans Unicode", sans-serif');
+ this.font.setBold(true);
+ },
+
+ initial : function(vTheme) {
+ return {
+ border : this.border,
+ font : this.font,
+ textAlign : "center"
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ color : vStates.weekend ? this.bgcolor : this.color,
+ backgroundColor : vStates.weekend ? this.color : this.bgcolor
+ }
+ }
+
+ },
+
+
+ "datechooser-day" : {
+ setup : function() {
+ this.font = new qx.renderer.font.Font(11, '"Segoe UI", Corbel, Calibri, Tahoma, "Lucida Sans Unicode", sans-serif');
+
+ this.selectedColor = new qx.renderer.color.ColorObject("highlightText");
+ this.selectedBgColor = new qx.renderer.color.ColorObject("highlight");
+ this.color = new qx.renderer.color.ColorObject("windowText");
+ this.otherMonthColor = new qx.renderer.color.ColorObject("grayText");
+
+ this.transparentBorder = new qx.renderer.border.Border(1, "none");
+ },
+
+ initial : function(vTheme) {
+ return {
+ cursor : "default",
+ border : this.border,
+ color : this.color,
+ font : this.font,
+ textAlign : "center",
+ verticalAlign: "middle",
+ selectable: false
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ border : vStates.today ? qx.renderer.border.BorderPresets.getInstance().black : this.transparentBorder,
+ color : vStates.selected ? this.selectedColor :
+ (vStates.otherMonth ? this.otherMonthColor : this.color),
+ backgroundColor : vStates.selected ? this.selectedBgColor : null
+ }
+ }
+ },
+
+ "datechooser-week" : {
+ setup : function() {
+ this.border = new qx.renderer.border.Border;
+ this.border.set({ rightColor:"gray", rightStyle :"solid", rightWidth:1 });
+ this.headerBorder = new qx.renderer.border.Border;
+ this.headerBorder.set({ rightColor:"gray", rightStyle :"solid", rightWidth:1,
+ bottomColor:"gray", bottomStyle :"solid", bottomWidth:1 });
+ this.color = new qx.renderer.color.ColorObject("#6285BA");
+ this.font = new qx.renderer.font.Font(11, '"Segoe UI", Corbel, Calibri, Tahoma, "Lucida Sans Unicode", sans-serif');
+ },
+
+ initial : function(vTheme) {
+ return {
+ border : this.border,
+ font : this.font,
+ color: this.color,
+ paddingLeft : 2
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ border : vStates.header ? this.headerBorder : this.border
+ }
+ }
+ },
+
+
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ TABLE
+ ---------------------------------------------------------------------------
+ */
+
+ "table-focus-statusbar" : {
+ setup : function() {
+ this.font = new qx.renderer.font.Font(11, '"Segoe UI", Corbel, Calibri, Tahoma, "Lucida Sans Unicode", sans-serif');
+ this.border = new qx.renderer.border.Border;
+ this.border.set({ topColor:"threedshadow", topStyle :"solid", topWidth:1 });
+ },
+
+ initial : function(vTheme) {
+ return {
+ font: this.font,
+ border: this.border,
+ paddingLeft: 2,
+ paddingRight: 2
+ }
+ }
+ },
+
+
+ "table-focus-indicator" : {
+ setup : function() {
+ this.border = new qx.renderer.border.Border(3, "solid", "#b3d9ff");
+ this.blurBorder = new qx.renderer.border.Border(3, "solid", "#c5c8ca");
+ this.editingBorder = new qx.renderer.border.Border(2, "solid", "#b3d9ff");
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ border : vStates.editing ? this.editingBorder : (vStates.tableHasFocus ? this.border : this.blurBorder)
+ }
+ }
+ },
+
+
+ "table-editor-textfield" : {
+ setup : function() {
+ this.font = new qx.renderer.font.Font(11, '"Segoe UI", Corbel, Calibri, Tahoma, "Lucida Sans Unicode", sans-serif');
+ },
+
+ initial : function(vTheme) {
+ return {
+ font: this.font,
+ border: qx.renderer.border.BorderPresets.getInstance().none,
+ paddingLeft: 2,
+ paddingRight: 2,
+ paddingTop: 0,
+ paddingBottom: 0
+ }
+ }
+ },
+
+ "table-header-cell" : {
+ setup : function() {
+ this.border = new qx.renderer.border.Border;
+ this.border.set({ rightColor:"#d6d2c2", rightStyle :"solid", rightWidth:1,
+ bottomColor:"#d6d2c2", bottomStyle :"solid", bottomWidth:2 });
+
+ this.mouseOverBorder = new qx.renderer.border.Border;
+ this.mouseOverBorder.set({ rightColor:"#d6d2c2", rightStyle :"solid", rightWidth:1,
+ bottomColor:"#F9B119", bottomStyle :"solid", bottomWidth:2 });
+
+ this.mouseOverBackground = new qx.renderer.color.ColorObject("white");
+ this.background = new qx.renderer.color.ColorObject("#ebeadb");
+ },
+
+ initial : function(vTheme) {
+ return {
+ cursor : "default",
+ border : this.border,
+ paddingLeft : 2,
+ paddingRight : 2,
+ spacing:2,
+ overflow:"hidden",
+ selectable: false,
+ backgroundColor:this.background,
+ iconPosition:"right",
+ verticalChildrenAlign:"middle"
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ backgroundColor : vStates.mouseover ? this.mouseOverBackground : this.background,
+ border : vStates.mouseover ? this.mouseOverBorder : this.border
+ }
+ }
+ },
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ SPLITPANE
+ ---------------------------------------------------------------------------
+ */
+
+ "splitpane" :
+ {
+ initial : function(vTheme)
+ {
+ return {
+ overflow : "hidden"
+ }
+ }
+ },
+
+ "splitpane-glasspane" :
+ {
+ setup : function() {
+ this.background = new qx.renderer.color.ColorObject("threedshadow");
+ },
+
+ initial : function(vTheme)
+ {
+ return {
+ zIndex : 1e7,
+ backgroundColor : this.background
+ }
+ },
+
+ state : function(vTheme, vStates) {
+ return {
+ opacity : vStates.visible ? 0.2 : 0
+ }
+ }
+ },
+
+ "splitpane-splitter" :
+ {
+ initial : function(vTheme) {
+ return {
+ backgroundColor : "threedface"
+ }
+ },
+
+ state : function(vTheme, vStates)
+ {
+ return {
+ cursor : vStates.horizontal ? "col-resize" : "row-resize"
+ };
+ }
+ },
+
+ "splitpane-slider" :
+ {
+ initial : function(vTheme)
+ {
+ return {
+ opacity: 0.5,
+ zIndex : 1e8
+ }
+ },
+
+ state : function(vTheme, vStates)
+ {
+ return {
+ backgroundColor: vStates.dragging ? "threeddarkshadow" : "threedface"
+ }
+ }
+ },
+
+ "splitpane-knob" :
+ {
+ state : function(vTheme, vStates)
+ {
+ var vReturn = {
+ opacity: vStates.dragging ? 0.5 : 1.0
+ }
+
+ if (vStates.horizontal)
+ {
+ vReturn.top = "33%";
+ vReturn.left = null;
+ vReturn.marginLeft = -6;
+ vReturn.marginTop = 0;
+ vReturn.cursor = "col-resize";
+ }
+ else if (vStates.vertical)
+ {
+ vReturn.top = null;
+ vReturn.left = "33%";
+ vReturn.marginTop = -6;
+ vReturn.marginLeft = 0;
+ vReturn.cursor = "row-resize";
+ }
+
+ return vReturn;
+ }
+ }
+
+
+
+
+ /*
+ ---------------------------------------------------------------------------
+ END
+ ---------------------------------------------------------------------------
+ */
+}, qx.Super.prototype._appearances);
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTER TO MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.manager.object.AppearanceManager.getInstance().registerAppearanceTheme(qx.Class);
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/System.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/System.js
new file mode 100644
index 0000000000..54d3d996a3
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/System.js
@@ -0,0 +1,54 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(theme_color)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.theme.color.System", qx.renderer.theme.ColorTheme,
+function() {
+ qx.renderer.theme.ColorTheme.call(this, "Operating System Default");
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTER TO MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.manager.object.ColorManager.getInstance().registerColorTheme(qx.Class);
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsClassic.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsClassic.js
new file mode 100644
index 0000000000..1a5d32914b
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsClassic.js
@@ -0,0 +1,98 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(theme_color)
+
+************************************************************************ */
+
+
+qx.OO.defineClass("qx.theme.color.WindowsClassic", qx.renderer.theme.ColorTheme,
+function() {
+ qx.renderer.theme.ColorTheme.call(this, "Windows Classic");
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFINE COLORS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._colors = qx.lang.Object.carefullyMergeWith({
+ activeborder : [ 212,208,200 ],
+ activecaption : [ 10,36,106 ],
+ appworkspace : [ 128,128,128 ],
+ background : [ 58,110,165 ],
+ buttonface : [ 212,208,200 ],
+ buttonhighlight : [ 255,255,255 ],
+ buttonshadow : [ 128,128,128 ],
+ buttontext : [ 0,0,0 ],
+ captiontext : [ 255,255,255 ],
+ graytext : [ 128,128,128 ],
+ highlight : [ 10,36,106 ],
+ highlighttext : [ 255,255,255 ],
+ inactiveborder : [ 212,208,200 ],
+ inactivecaption : [ 128,128,128 ],
+ inactivecaptiontext : [ 212,208,200 ],
+ infobackground : [ 255,255,225 ],
+ infotext : [ 0,0,0 ],
+ menu : [ 212,208,200 ],
+ menutext : [ 0,0,0 ],
+ scrollbar : [ 212,208,200 ],
+ threeddarkshadow : [ 64,64,64 ],
+ threedface : [ 212,208,200 ],
+ threedhighlight : [ 255,255,255 ],
+ threedlightshadow : [ 212,208,200 ],
+ threedshadow : [ 128,128,128 ],
+ window : [ 255,255,255 ],
+ windowframe : [ 0,0,0 ],
+ windowtext : [ 0,0,0 ]
+}, qx.Super.prototype._colors);
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTER TO MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.manager.object.ColorManager.getInstance().registerColorTheme(qx.Class);
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsLunaBlue.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsLunaBlue.js
new file mode 100644
index 0000000000..a7737e8422
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsLunaBlue.js
@@ -0,0 +1,96 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(theme_color)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.theme.color.WindowsLunaBlue", qx.renderer.theme.ColorTheme,
+function() {
+ qx.renderer.theme.ColorTheme.call(this, "Windows Luna Blue");
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFINE COLORS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._colors = qx.lang.Object.carefullyMergeWith({
+ activeborder : [ 212,208,200 ],
+ activecaption : [ 0,84,227 ],
+ appworkspace : [ 128,128,128 ],
+ background : [ 0,78,152 ],
+ buttonface : [ 236,233,216 ],
+ buttonhighlight : [ 255,255,255 ],
+ buttonshadow : [ 172,168,153 ],
+ buttontext : [ 0,0,0 ],
+ captiontext : [ 255,255,255 ],
+ graytext : [ 172,168,153 ],
+ highlight : [ 49,106,197 ],
+ highlighttext : [ 255,255,255 ],
+ inactiveborder : [ 212,208,200 ],
+ inactivecaption : [ 122,150,223 ],
+ inactivecaptiontext : [ 216,228,248 ],
+ infobackground : [ 255,255,225 ],
+ infotext : [ 0,0,0 ],
+ menu : [ 255,255,255 ],
+ menutext : [ 0,0,0 ],
+ scrollbar : [ 212,208,200 ],
+ threeddarkshadow : [ 113,111,100 ],
+ threedface : [ 236,233,216 ],
+ threedhighlight : [ 255,255,255 ],
+ threedlightshadow : [ 241,239,226 ],
+ threedshadow : [ 172,168,153 ],
+ window : [ 255,255,255 ],
+ windowframe : [ 0,0,0 ],
+ windowtext : [ 0,0,0 ]
+}, qx.Super.prototype._colors);
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTER TO MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.manager.object.ColorManager.getInstance().registerColorTheme(qx.Class);
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsLunaGreen.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsLunaGreen.js
new file mode 100644
index 0000000000..b6af5d25f1
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsLunaGreen.js
@@ -0,0 +1,94 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(theme_color)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.theme.color.WindowsLunaGreen", qx.renderer.theme.ColorTheme,
+function() {
+ qx.renderer.theme.ColorTheme.call(this, "Windows Luna Green");
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFINE COLORS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._colors = qx.lang.Object.carefullyMergeWith({
+ activeborder : [ 212,208,200 ],
+ activecaption : [ 139,161,105 ],
+ appworkspace : [ 128,128,128 ],
+ background : [ 157,172,189 ],
+ buttonface : [ 236,233,216 ],
+ buttonhighlight : [ 255,255,255 ],
+ buttonshadow : [ 172,168,153 ],
+ buttontext : [ 0,0,0 ],
+ captiontext : [ 255,255,255 ],
+ graytext : [ 172,168,153 ],
+ highlight : [ 147,160,112 ],
+ highlighttext : [ 255,255,255 ],
+ inactiveborder : [ 212,208,200 ],
+ inactivecaption : [ 212,214,186 ],
+ inactivecaptiontext : [ 255,255,255 ],
+ infobackground : [ 255,255,225 ],
+ infotext : [ 0,0,0 ],
+ menu : [ 255,255,255 ],
+ menutext : [ 0,0,0 ],
+ scrollbar : [ 212,208,200 ],
+ threeddarkshadow : [ 113,111,100 ],
+ threedface : [ 236,233,216 ],
+ threedhighlight : [ 255,255,255 ],
+ threedlightshadow : [ 241,239,226 ],
+ threedshadow : [ 172,168,153 ],
+ window : [ 255,255,255 ],
+ windowframe : [ 0,0,0 ],
+ windowtext : [ 0,0,0 ]
+}, qx.Super.prototype._colors);
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTER TO MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.manager.object.ColorManager.getInstance().registerColorTheme(qx.Class);
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsLunaSilver.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsLunaSilver.js
new file mode 100644
index 0000000000..3ccb52fd9f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsLunaSilver.js
@@ -0,0 +1,94 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(theme_color)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.theme.color.WindowsLunaSilver", qx.renderer.theme.ColorTheme,
+function() {
+ qx.renderer.theme.ColorTheme.call(this, "Windows Luna Silver");
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFINE COLORS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._colors = qx.lang.Object.carefullyMergeWith({
+ activeborder : [ 212,208,200 ],
+ activecaption : [ 192,192,192 ],
+ appworkspace : [ 128,128,128 ],
+ background : [ 88,87,104 ],
+ buttonface : [ 224,223,227 ],
+ buttonhighlight : [ 255,255,255 ],
+ buttonshadow : [ 157,157,161 ],
+ buttontext : [ 0,0,0 ],
+ captiontext : [ 14,16,16 ],
+ graytext : [ 172,168,153 ],
+ highlight : [ 178,180,191 ],
+ highlighttext : [ 0,0,0 ],
+ inactiveborder : [ 212,208,200 ],
+ inactivecaption : [ 255,255,255 ],
+ inactivecaptiontext : [ 162,161,161 ],
+ infobackground : [ 255,255,225 ],
+ infotext : [ 0,0,0 ],
+ menu : [ 255,255,255 ],
+ menutext : [ 0,0,0 ],
+ scrollbar : [ 212,208,200 ],
+ threeddarkshadow : [ 113,111,100 ],
+ threedface : [ 224,223,227 ],
+ threedhighlight : [ 255,255,255 ],
+ threedlightshadow : [ 241,239,226 ],
+ threedshadow : [ 157,157,161 ],
+ window : [ 255,255,255 ],
+ windowframe : [ 0,0,0 ],
+ windowtext : [ 0,0,0 ]
+}, qx.Super.prototype._colors);
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTER TO MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.manager.object.ColorManager.getInstance().registerColorTheme(qx.Class);
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsRoyale.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsRoyale.js
new file mode 100644
index 0000000000..b268b221c2
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/color/WindowsRoyale.js
@@ -0,0 +1,95 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#module(theme_color)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.theme.color.WindowsRoyale", qx.renderer.theme.ColorTheme,
+function() {
+ qx.renderer.theme.ColorTheme.call(this, "Windows Royale");
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFINE COLORS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._colors = qx.lang.Object.carefullyMergeWith({
+ activeborder : [ 212,208,200 ],
+ activecaption : [ 51,94,168 ],
+ appworkspace : [ 128,128,128 ],
+ background : [ 0,0,64 ],
+ buttonface : [ 235,233,237 ],
+ buttonhighlight : [ 255,255,255 ],
+ buttonshadow : [ 167,166,170 ],
+ buttontext : [ 0,0,0 ],
+ captiontext : [ 255,255,255 ],
+ graytext : [ 167,166,170 ],
+ highlight : [ 51,94,168 ],
+ highlighttext : [ 255,255,255 ],
+ inactiveborder : [ 212,208,200 ],
+ inactivecaption : [ 111,161,217 ],
+ inactivecaptiontext : [ 255,255,255 ],
+ infobackground : [ 255,255,225 ],
+ infotext : [ 0,0,0 ],
+ menu : [ 255,255,255 ],
+ menutext : [ 0,0,0 ],
+ scrollbar : [ 212,208,200 ],
+ threeddarkshadow : [ 133,135,140 ],
+ threedface : [ 235,233,237 ],
+ threedhighlight : [ 255,255,255 ],
+ threedlightshadow : [ 220,223,228 ],
+ threedshadow : [ 167,166,170 ],
+ window : [ 255,255,255 ],
+ windowframe : [ 0,0,0 ],
+ windowtext : [ 0,0,0 ]
+}, qx.Super.prototype._colors);
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTER TO MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.manager.object.ColorManager.getInstance().registerColorTheme(qx.Class);
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/icon/CrystalSvg.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/icon/CrystalSvg.js
new file mode 100644
index 0000000000..52dd581b52
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/icon/CrystalSvg.js
@@ -0,0 +1,68 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#module(theme_icon)
+#resource(images:icon/crystalsvg)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.theme.icon.CrystalSvg", qx.renderer.theme.IconTheme,
+function() {
+ qx.renderer.theme.IconTheme.call(this, "Crystal SVG");
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFAULT SETTINGS
+---------------------------------------------------------------------------
+*/
+
+qx.Settings.setDefault("imageUri", qx.Settings.getValueOfClass("qx.manager.object.AliasManager", "resourceUri") + "/icon/crystalsvg");
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTER TO MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.manager.object.ImageManager.getInstance().registerIconTheme(qx.Class);
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/icon/Nuvola.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/icon/Nuvola.js
new file mode 100644
index 0000000000..da55824fee
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/icon/Nuvola.js
@@ -0,0 +1,66 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(theme_icon)
+#resource(images:icon/nuvola)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.theme.icon.Nuvola", qx.renderer.theme.IconTheme,
+function() {
+ qx.renderer.theme.IconTheme.call(this, "Nuvola");
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFAULT SETTINGS
+---------------------------------------------------------------------------
+*/
+
+qx.Settings.setDefault("imageUri", qx.Settings.getValueOfClass("qx.manager.object.AliasManager", "resourceUri") + "/icon/nuvola");
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTER TO MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.manager.object.ImageManager.getInstance().registerIconTheme(qx.Class);
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/widget/Windows.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/widget/Windows.js
new file mode 100644
index 0000000000..c94fd1d418
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/theme/widget/Windows.js
@@ -0,0 +1,68 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#module(theme_widget)
+#resource(images:widget/windows)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.theme.widget.Windows", qx.renderer.theme.WidgetTheme,
+function() {
+ qx.renderer.theme.WidgetTheme.call(this, "Windows");
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFAULT SETTINGS
+---------------------------------------------------------------------------
+*/
+
+qx.Settings.setDefault("imageUri", qx.Settings.getValueOfClass("qx.manager.object.AliasManager", "resourceUri") + "/widget/windows");
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REGISTER TO MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.manager.object.ImageManager.getInstance().registerWidgetTheme(qx.Class);
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/Range.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/Range.js
new file mode 100644
index 0000000000..848550b7ae
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/Range.js
@@ -0,0 +1,87 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+/**
+ * This manager is used by all objects which needs ranges like qx.ui.form.Spinner, ...
+ *
+ * @event change {qx.event.type.Event}
+ */
+qx.OO.defineClass("qx.type.Range", qx.core.Target,
+function() {
+ qx.core.Target.call(this);
+});
+
+/** current value of the Range object */
+qx.OO.addProperty({ name : "value", type : "number", defaultValue : 0 });
+
+/** minimal value of the Range object */
+qx.OO.addProperty({ name : "min", type : "number", defaultValue : 0 });
+
+/** maximal value of the Range object */
+qx.OO.addProperty({ name : "max", type : "number", defaultValue : 100 });
+
+/** Step size for increments/decrements of the value property */
+qx.OO.addProperty({ name : "step", type : "number", defaultValue : 1 });
+
+qx.Proto._checkValue = function(propValue) {
+ return Math.max(this.getMin(), Math.min(this.getMax(), Math.floor(propValue)));
+}
+
+qx.Proto._modifyValue = function(propValue, propOldValue, propData)
+{
+ if (this.hasEventListeners("change")) {
+ this.dispatchEvent(new qx.event.type.Event("change"), true);
+ }
+
+ return true;
+}
+
+qx.Proto._checkMax = function(propValue) {
+ return Math.floor(propValue);
+}
+
+qx.Proto._modifyMax = function(propValue, propOldValue, propData)
+{
+ this.setValue(Math.min(this.getValue(), propValue));
+
+ if (this.hasEventListeners("change")) {
+ this.dispatchEvent(new qx.event.type.Event("change"), true);
+ }
+
+ return true;
+}
+
+qx.Proto._checkMin = function(propValue) {
+ return Math.floor(propValue);
+}
+
+qx.Proto._modifyMin = function(propValue, propOldValue, propData)
+{
+ this.setValue(Math.max(this.getValue(), propValue));
+
+ if (this.hasEventListeners("change")) {
+ this.dispatchEvent(new qx.event.type.Event("change"), true);
+ }
+
+ return true;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/Selection.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/Selection.js
new file mode 100644
index 0000000000..61f0be7ef1
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/Selection.js
@@ -0,0 +1,120 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+
+************************************************************************ */
+
+/*!
+ Helper for qx.manager.selection.SelectionManager, contains data for selections
+*/
+qx.OO.defineClass("qx.type.Selection", qx.core.Object,
+function(vManager)
+{
+ qx.core.Object.call(this);
+
+ this._manager = vManager;
+ this.removeAll();
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ USER METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.add = function(oItem) {
+ this._storage[this.getItemHashCode(oItem)] = oItem;
+}
+
+qx.Proto.remove = function(oItem) {
+ delete this._storage[this.getItemHashCode(oItem)];
+}
+
+qx.Proto.removeAll = function() {
+ this._storage = {};
+}
+
+qx.Proto.contains = function(oItem) {
+ return this.getItemHashCode(oItem) in this._storage;
+}
+
+qx.Proto.toArray = function()
+{
+ var res = [];
+
+ for (var key in this._storage) {
+ res.push(this._storage[key]);
+ }
+
+ return res;
+}
+
+qx.Proto.getFirst = function()
+{
+ for (var key in this._storage) {
+ return this._storage[key];
+ }
+}
+
+qx.Proto.getChangeValue = function()
+{
+ var sb = [];
+
+ for (var hc in this._storage) {
+ sb.push(hc);
+ }
+
+ sb.sort();
+ return sb.join(";");
+}
+
+qx.Proto.getItemHashCode = function(oItem) {
+ return this._manager.getItemHashCode(oItem);
+}
+
+qx.Proto.isEmpty = function() {
+ return qx.lang.Object.isEmpty(this._storage);
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this._storage = null;
+ this._manager = null;
+
+ qx.core.Object.prototype.dispose.call(this);
+}
\ No newline at end of file
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/StringBuilder.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/StringBuilder.js
new file mode 100644
index 0000000000..c31102c8b1
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/StringBuilder.js
@@ -0,0 +1,146 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#require(qx.sys.Client)
+
+************************************************************************ */
+
+/**
+ * A string builder class
+ *
+ * += operator is faster in Firefox and Opera.
+ * Array push/join is faster in Internet Explorer
+ *
+ * Even with this wrapper, which costs some time, this is
+ * faster in Firefox than the alternative Array concat in
+ * all browsers (which is in relation to IE's performance issues
+ * only marginal). The IE performance loss caused by this
+ * wrapper is not relevant.
+ *
+ * So this class seems to be the best compromise to handle
+ * string concatination.
+ */
+qx.OO.defineClass("qx.type.StringBuilder", qx.core.Object,
+function()
+{
+ qx.core.Object.call(this);
+
+ this.init();
+ this.add.apply(this, arguments);
+});
+
+
+/**
+ * Resets the contents of the Stringbuilder
+ * equivalent to str = "";
+ */
+qx.Proto.clear = function() {}
+
+/**
+ * Returns the contents of the concatenated string
+ *
+ * @return (string) string content
+ */
+qx.Proto.get = function() {}
+
+/**
+ * Append a variable number of string arguments
+ *
+ * @param varargs (string) variable number os strings to be added
+ */
+qx.Proto.add = function(varargs) {}
+
+/**
+ * Initializes the contents of the Stringbuilder
+ * equivalent to str = "";
+ */
+qx.Proto.init = function() {}
+
+/** Destructor */
+qx.Proto.dispose = function() {}
+
+/**
+ * Returns the contents of the concatenated string
+ *
+ * @return (string) string content
+ */
+qx.Proto.toString = function() {}
+
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto.clear = function() {
+ this._array = [];
+ }
+
+ qx.Proto.get = function() {
+ return this._array.join("");
+ }
+
+ qx.Proto.add = function() {
+ this._array.push.apply(this._array, arguments);
+ }
+
+ qx.Proto.init = function() {
+ this._array = [];
+ }
+
+ qx.Proto.dispose = function()
+ {
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this._array = null;
+
+ qx.core.Object.prototype.dispose.call(this);
+ }
+}
+else
+{
+ qx.Proto.clear = function() {
+ this._string = "";
+ }
+
+ qx.Proto.get = function() {
+ return this._string;
+ }
+
+ qx.Proto.add = function() {
+ this._string += Array.prototype.join.call(arguments, "");
+ }
+
+ qx.Proto.init = function() {
+ this._string = "";
+ }
+
+ qx.Proto.dispose = function()
+ {
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this._string = null;
+
+ qx.core.Object.prototype.dispose.call(this);
+ }
+}
+
+qx.Proto.toString = qx.Proto.get;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/Version.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/Version.js
new file mode 100755
index 0000000000..e0ce4ec53a
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/type/Version.js
@@ -0,0 +1,118 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+/*!
+ This class contains a version string and can extract
+ major, minor and revision flags from this string. It can also
+ compare a incoming version object with the stored version string
+ and checks if this version is smaller or identical than the stored
+ one.
+
+ Flash detection and embed (http://blog.deconcept.com/flashobject) (non qooxdoo Version by Geoff Stearns)
+ Copyright 2005 Geoff Stearns. Released under the MIT License (http://www.opensource.org/licenses/mit-license.php).
+
+ Modified for qooxdoo by Sebastian Werner. Based on version 1.2.3. Relicensed under LGPL in assent of Geoff Stearns.
+*/
+
+qx.OO.defineClass("qx.type.Version", qx.core.Object,
+function(arrVersion)
+{
+ qx.core.Object.call(this);
+
+ if (typeof arrVersion === "string") {
+ arrVersion = arrVersion.split(".");
+ }
+
+ this._major = parseInt(arrVersion[0]) || 0;
+ this._minor = parseInt(arrVersion[1]) || 0;
+ this._rev = parseInt(arrVersion[2]) || 0;
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DATA FIELDS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._major = 0;
+qx.Proto._minor = 0;
+qx.Proto._rev = 0;
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ USER VERSION ACCESS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.versionIsValid = function(fv)
+{
+ if (this.getMajor() < fv.getMajor()) return false;
+ if (this.getMajor() > fv.getMajor()) return true;
+
+ if (this.getMinor() < fv.getMinor()) return false;
+ if (this.getMinor() > fv.getMinor()) return true;
+
+ if (this.getRev() < fv.getRev()) return false;
+
+ return true;
+}
+
+qx.Proto.getMajor = function() {
+ return this._major;
+}
+
+qx.Proto.getMinor = function() {
+ return this._minor;
+}
+
+qx.Proto.getRev = function() {
+ return this._rev;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this._major = this._minor = this._rev = null;
+
+ qx.core.Object.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Atom.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Atom.js
new file mode 100644
index 0000000000..5a1c0ae97f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Atom.js
@@ -0,0 +1,397 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+#optional(qx.ui.embed.Flash)
+
+************************************************************************ */
+
+/*!
+ A multi-prupose widget used by many more complex widgets.
+
+ The intended purpose of qx.ui.basic.Atom is to easily align the common icon-text combination in different ways.
+ This is useful for all types of buttons, menuentires, tooltips, ...
+*/
+qx.OO.defineClass("qx.ui.basic.Atom", qx.ui.layout.BoxLayout,
+function(vLabel, vIcon, vIconWidth, vIconHeight, vFlash)
+{
+ qx.ui.layout.BoxLayout.call(this);
+
+ if (this.getOrientation() == null) {
+ this.setOrientation("horizontal");
+ }
+
+ // Prohibit selection
+ this.setSelectable(false);
+
+ // Disable flex support
+ this.getLayoutImpl().setEnableFlexSupport(false);
+
+ // Apply constructor arguments
+ if (qx.util.Validation.isValidString(vLabel)) {
+ this.setLabel(vLabel);
+ } else {
+ this.setLabel("");
+ }
+
+ // Simple flash wrapper
+ if (qx.OO.isAvailable("qx.ui.embed.Flash") && qx.util.Validation.isValidString(vFlash) && qx.util.Validation.isValidNumber(vIconWidth) && qx.util.Validation.isValidNumber(vIconHeight) && qx.ui.embed.Flash.getPlayerVersion().getMajor() > 0)
+ {
+ this._flashMode = true;
+
+ this.setIcon(vFlash);
+
+ // flash needs explicit dimensions!
+ this.setIconWidth(vIconWidth);
+ this.setIconHeight(vIconHeight);
+ }
+ else if (qx.util.Validation.isValidString(vIcon))
+ {
+ this.setIcon(vIcon);
+
+ if (qx.util.Validation.isValidNumber(vIconWidth)) {
+ this.setIconWidth(vIconWidth);
+ }
+
+ if (qx.util.Validation.isValidNumber(vIconHeight)) {
+ this.setIconHeight(vIconHeight);
+ }
+ }
+});
+
+qx.ui.basic.Atom.SHOW_LABEL = "label";
+qx.ui.basic.Atom.SHOW_ICON = "icon";
+qx.ui.basic.Atom.SHOW_BOTH = "both";
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ The label/caption/text of the qx.ui.basic.Atom instance
+*/
+qx.OO.addProperty({ name : "label", type : "string" });
+
+/*!
+ Any URI String supported by qx.ui.basic.Image to display a icon
+*/
+qx.OO.addProperty({ name : "icon", type : "string" });
+
+/**
+ * Any URI String supported by qx.ui.basic.Image to display a disabled icon.
+ *
+ * If not set the normal icon is shown transparently.
+ */
+qx.OO.addProperty({ name : "disabledIcon", type : "string" });
+
+/*!
+ Configure the visibility of the sub elements/widgets.
+ Possible values: both, text, icon, none
+*/
+qx.OO.addProperty({ name : "show", type : "string", defaultValue : "both", possibleValues : [ "both", "label", "icon", "none", null ] });
+
+/*!
+ The position of the icon in relation to the text.
+ Only useful/needed if text and icon is configured and 'show' is configured as 'both' (default)
+*/
+qx.OO.addProperty({ name : "iconPosition", type : "string", defaultValue : "left", possibleValues : [ "top", "right", "bottom", "left" ] });
+
+/*!
+ The width of the icon.
+ If configured, this makes qx.ui.basic.Atom a little bit faster as it does not need to wait until the image loading is finished.
+*/
+qx.OO.addProperty({ name : "iconWidth", type : "number" });
+
+/*!
+ The height of the icon
+ If configured, this makes qx.ui.basic.Atom a little bit faster as it does not need to wait until the image loading is finished.
+*/
+qx.OO.addProperty({ name : "iconHeight", type : "number" });
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "atom" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ SUB WIDGETS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._flashMode = false;
+
+qx.Proto._labelObject = null;
+qx.Proto._iconObject = null;
+
+qx.Proto._createLabel = function()
+{
+ var l = this._labelObject = new qx.ui.basic.Label(this.getLabel());
+
+ l.setAnonymous(true);
+ l.setEnabled(this.getEnabled());
+ l.setSelectable(false);
+
+ this.addAt(l, this._iconObject ? 1 : 0);
+}
+
+qx.Proto._createIcon = function()
+{
+ if (this._flashMode && qx.OO.isAvailable("qx.ui.embed.Flash"))
+ {
+ var i = this._iconObject = new qx.ui.embed.Flash(this.getIcon());
+ }
+ else
+ {
+ var i = this._iconObject = new qx.ui.basic.Image();
+ }
+
+ i.setAnonymous(true);
+
+ this._updateIcon();
+
+ this.addAt(i, 0);
+}
+
+qx.Proto._updateIcon = function() {
+ // NOTE: We have to check whether the properties "icon" and "disabledIcon"
+ // exist, because some child classes remove them.
+ if (this._iconObject && this.getIcon && this.getDisabledIcon) {
+ var disabledIcon = this.getDisabledIcon();
+ if (disabledIcon) {
+ if (this.getEnabled()) {
+ this._iconObject.setSource(this.getIcon());
+ } else {
+ this._iconObject.setSource(disabledIcon);
+ }
+ this._iconObject.setEnabled(true);
+ } else {
+ this._iconObject.setSource(this.getIcon());
+ this._iconObject.setEnabled(this.getEnabled());
+ }
+ }
+}
+
+qx.Proto.getLabelObject = function() {
+ return this._labelObject;
+}
+
+qx.Proto.getIconObject = function() {
+ return this._iconObject;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyEnabled = function(propValue, propOldValue, propData)
+{
+ this._updateIcon();
+
+ if (this._labelObject) {
+ this._labelObject.setEnabled(propValue);
+ }
+
+ return qx.ui.layout.BoxLayout.prototype._modifyEnabled.call(this, propValue, propOldValue, propData);
+}
+
+qx.Proto._modifyIconPosition = function(propValue, propOldValue, propData)
+{
+ switch(propValue)
+ {
+ case "top":
+ case "bottom":
+ this.setOrientation("vertical");
+ this.setReverseChildrenOrder(propValue == "bottom");
+ break;
+
+ default:
+ this.setOrientation("horizontal");
+ this.setReverseChildrenOrder(propValue == "right");
+ break;
+ }
+
+ return true;
+}
+
+qx.Proto._modifyShow = function(propValue, propOldValue, propData)
+{
+ this._handleIcon();
+ this._handleLabel();
+
+ return true;
+}
+
+qx.Proto._modifyLabel = function(propValue, propOldValue, propData)
+{
+ if (this._labelObject) {
+ this._labelObject.setHtml(propValue);
+ }
+
+ this._handleLabel();
+
+ return true;
+}
+
+qx.Proto._modifyIcon = function(propValue, propOldValue, propData)
+{
+ this._updateIcon();
+ this._handleIcon();
+
+ return true;
+}
+
+qx.Proto._modifyDisabledIcon = function(propValue, propOldValue, propData)
+{
+ this._updateIcon();
+ this._handleIcon();
+
+ return true;
+}
+
+qx.Proto._modifyIconWidth = function(propValue, propOldValue, propData)
+{
+ this._iconObject.setWidth(propValue);
+ return true;
+}
+
+qx.Proto._modifyIconHeight = function(propValue, propOldValue, propData)
+{
+ this._iconObject.setHeight(propValue);
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._iconIsVisible = false;
+qx.Proto._labelIsVisible = false;
+
+qx.Proto._handleLabel = function()
+{
+ switch(this.getShow())
+ {
+ case qx.ui.basic.Atom.SHOW_LABEL:
+ case qx.ui.basic.Atom.SHOW_BOTH:
+ this._labelIsVisible = qx.util.Validation.isValidString(this.getLabel());
+ break;
+
+ default:
+ this._labelIsVisible = false;
+ }
+
+ if (this._labelIsVisible)
+ {
+ this._labelObject ? this._labelObject.setDisplay(true) : this._createLabel();
+ }
+ else if (this._labelObject)
+ {
+ this._labelObject.setDisplay(false);
+ }
+}
+
+qx.Proto._handleIcon = function()
+{
+ switch(this.getShow())
+ {
+ case qx.ui.basic.Atom.SHOW_ICON:
+ case qx.ui.basic.Atom.SHOW_BOTH:
+ this._iconIsVisible = qx.util.Validation.isValidString(this.getIcon());
+ break;
+
+ default:
+ this._iconIsVisible = false;
+ }
+
+ if (this._iconIsVisible)
+ {
+ this._iconObject ? this._iconObject.setDisplay(true) : this._createIcon();
+ }
+ else if (this._iconObject)
+ {
+ this._iconObject.setDisplay(false);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CLONE
+---------------------------------------------------------------------------
+*/
+
+// Omit recursive cloning
+qx.Proto._cloneRecursive = qx.util.Return.returnTrue;
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._iconObject)
+ {
+ this._iconObject.dispose();
+ this._iconObject = null;
+ }
+
+ if (this._labelObject)
+ {
+ this._labelObject.dispose();
+ this._labelObject = null;
+ }
+
+ return qx.ui.layout.BoxLayout.prototype.dispose.call(this);
+}
\ No newline at end of file
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/HorizontalSpacer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/HorizontalSpacer.js
new file mode 100644
index 0000000000..9db8f12064
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/HorizontalSpacer.js
@@ -0,0 +1,31 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.basic.HorizontalSpacer", qx.ui.basic.Terminator,
+function()
+{
+ qx.ui.basic.Terminator.call(this);
+
+ this.setWidth("1*");
+});
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Image.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Image.js
new file mode 100644
index 0000000000..0cc25a9d5c
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Image.js
@@ -0,0 +1,611 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+#resource(core:static/image)
+
+************************************************************************ */
+
+/**
+ * This widget is for all images in qooxdoo projects.
+ *
+ * @event error {qx.event.type.Event}
+ */
+qx.OO.defineClass("qx.ui.basic.Image", qx.ui.basic.Terminator,
+function(vSource, vWidth, vHeight)
+{
+ qx.ui.basic.Terminator.call(this);
+
+ // Reset Alt and Title
+ this.setHtmlProperty("alt", "");
+ this.setHtmlProperty("title", "");
+
+ // Apply constructor arguments
+ this.setSource(qx.util.Validation.isValid(vSource) ? vSource : "static/image/blank.gif");
+
+ // Dimensions
+ this.setWidth(qx.util.Validation.isValid(vWidth) ? vWidth : "auto");
+ this.setHeight(qx.util.Validation.isValid(vHeight) ? vHeight : "auto");
+
+ // Prohibit selection
+ this.setSelectable(false);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ The source uri of the image.
+*/
+qx.OO.addProperty({ name : "source", type : "string" });
+
+/*!
+ The assigned preloader instance of the image.
+*/
+qx.OO.addProperty({ name : "preloader", type : "object" });
+
+/*!
+ The loading status.
+
+ True if the image is loaded correctly. False if no image is loaded
+ or the one that should be loaded is currently loading or not available.
+*/
+qx.OO.addProperty({ name : "loaded", type : "boolean", defaultValue : false });
+
+/*!
+ Should the image be maxified in it's own container?
+*/
+qx.OO.addProperty({ name : "resizeToInner", type : "boolean", defaultValue : false });
+
+/*!
+ Appearance of the widget
+*/
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "image" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT MAPPERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onload = function() {
+ this.setLoaded(true);
+}
+
+qx.Proto._onerror = function()
+{
+ this.debug("Could not load: " + this.getSource());
+
+ this.setLoaded(false);
+
+ if (this.hasEventListeners("error")) {
+ this.dispatchEvent(new qx.event.type.Event("error"), true);
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPLAYBLE HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._beforeAppear = function()
+{
+ var vSource = this.getSource();
+
+ if (qx.util.Validation.isValidString(vSource)) {
+ qx.manager.object.ImageManager.getInstance()._sources[vSource]++;
+ }
+
+ return qx.ui.basic.Terminator.prototype._beforeAppear.call(this);
+}
+
+qx.Proto._beforeDisappear = function()
+{
+ var vSource = this.getSource();
+
+ if (qx.util.Validation.isValidString(vSource))
+ {
+ if (qx.manager.object.ImageManager.getInstance()._sources[vSource] <= 1)
+ {
+ delete qx.manager.object.ImageManager.getInstance()._sources[vSource];
+ }
+ else
+ {
+ qx.manager.object.ImageManager.getInstance()._sources[vSource]--;
+ }
+ }
+
+ return qx.ui.basic.Terminator.prototype._beforeDisappear.call(this);
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifySource = function(propValue, propOldValue, propData)
+{
+ if (propValue && typeof qx.manager.object.ImageManager.getInstance()._sources[propValue] === "undefined") {
+ qx.manager.object.ImageManager.getInstance()._sources[propValue] = 0;
+ }
+
+ if (propOldValue)
+ {
+ if (qx.manager.object.ImageManager.getInstance()._sources[propOldValue] <= 1)
+ {
+ delete qx.manager.object.ImageManager.getInstance()._sources[propOldValue];
+ }
+ else
+ {
+ qx.manager.object.ImageManager.getInstance()._sources[propOldValue]--;
+ }
+ }
+
+ if (this.isCreated())
+ {
+ if (propValue)
+ {
+ this.setPreloader(qx.manager.object.ImagePreloaderManager.getInstance().create(qx.manager.object.AliasManager.getInstance().resolvePath(propValue)));
+ }
+ else if (propOldValue)
+ {
+ this._resetContent();
+ this.setPreloader(null);
+ }
+ }
+
+ return true;
+}
+
+qx.Proto._modifyPreloader = function(propValue, propOldValue, propData)
+{
+ if (propOldValue)
+ {
+ // remove event connection
+ propOldValue.removeEventListener("load", this._onload, this);
+ propOldValue.removeEventListener("error", this._onerror, this);
+ }
+
+ if (propValue)
+ {
+ // Register to image manager
+ qx.manager.object.ImageManager.getInstance().add(this);
+
+ // Omit here, otherwise the later setLoaded(true)
+ // will not be executed (prevent recursion)
+
+ // Changed: Use forceLoaded instead of setLoaded => should be faster
+ this.forceLoaded(false);
+
+ if (propValue.isErroneous())
+ {
+ this._onerror();
+ }
+ else if (propValue.isLoaded())
+ {
+ this.setLoaded(true);
+ }
+ else
+ {
+ propValue.addEventListener("load", this._onload, this);
+ propValue.addEventListener("error", this._onerror, this);
+ }
+ }
+ else
+ {
+ // Remove from image manager
+ qx.manager.object.ImageManager.getInstance().remove(this);
+
+ this.setLoaded(false);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyLoaded = function(propValue, propOldValue, propData)
+{
+ if (propValue && this.isCreated())
+ {
+ this._applyContent();
+ }
+ else if (!propValue)
+ {
+ this._invalidatePreferredInnerWidth();
+ this._invalidatePreferredInnerHeight();
+ }
+
+ return true;
+}
+
+qx.Proto._modifyElement = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ if (!this._image)
+ {
+ try
+ {
+ // Create Image-Node
+ // Webkit has problems with "new Image". Maybe related to "new Function" with
+ // is also not working correctly.
+ if (qx.sys.Client.getInstance().isWebkit())
+ {
+ this._image = document.createElement("img");
+ }
+ else
+ {
+ this._image = new Image;
+ }
+
+ // Possible alternative for MSHTML for PNG images
+ // But it seems not to be faster
+ // this._image = document.createElement("div");
+
+ // this costs much performance, move setup to blank gif to error handling
+ // is this SSL save?
+ // this._image.src = qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif");
+
+ this._image.style.border = "0 none";
+ this._image.style.verticalAlign = "top";
+ }
+ catch(ex)
+ {
+ this.error("Failed while creating image #1", ex);
+ }
+
+ if (!qx.sys.Client.getInstance().isMshtml()) {
+ this._applyEnabled();
+ }
+ }
+
+ propValue.appendChild(this._image);
+ }
+
+ // call widget implmentation
+ qx.ui.basic.Terminator.prototype._modifyElement.call(this, propValue, propOldValue, propData);
+
+ if (propValue)
+ {
+ try
+ {
+ // initialisize preloader
+ var vSource = this.getSource();
+ if (qx.util.Validation.isValidString(vSource)) {
+ this.setPreloader(qx.manager.object.ImagePreloaderManager.getInstance().create(qx.manager.object.AliasManager.getInstance().resolvePath(vSource)));
+ }
+ }
+ catch(ex)
+ {
+ this.error("Failed while creating image #2", ex);
+ }
+ }
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CLIENT OPTIMIZED MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._postApply = function()
+{
+ if (!this.getLoaded()) {
+ this._updateContent(qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif"));
+ return;
+ }
+
+ this._postApplyDimensions();
+ this._updateContent();
+}
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._modifyEnabled = function(propValue, propOldValue, propData)
+ {
+ if (this._image) {
+ this._applyEnabled();
+ }
+
+ return qx.ui.basic.Terminator.prototype._modifyEnabled.call(this, propValue, propOldValue, propData);
+ }
+
+ qx.Proto._updateContent = function(vSource)
+ {
+ var i = this._image;
+ var pl = this.getPreloader();
+
+ if (pl.getIsPng() && this.getEnabled())
+ {
+ i.src = qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif");
+ i.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + (vSource || pl.getSource()) + "',sizingMethod='scale')";
+ }
+ else
+ {
+ i.src = vSource || pl.getSource();
+ i.style.filter = this.getEnabled() ? "" : "Gray() Alpha(Opacity=30)";
+ }
+ }
+
+ qx.Proto._resetContent = function()
+ {
+ var i = this._image;
+
+ i.src = qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif");
+ i.style.filter = "";
+ }
+
+ qx.Proto._applyEnabled = qx.Proto._postApply;
+}
+else
+{
+ qx.Proto._updateContent = function(vSource) {
+ this._image.src = vSource || this.getPreloader().getSource();
+ }
+
+ qx.Proto._resetContent = function() {
+ this._image.src = qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif");
+ }
+
+ qx.Proto._applyEnabled = function()
+ {
+ if (this._image)
+ {
+ var o = this.getEnabled() ? "" : 0.3;
+ var s = this._image.style;
+
+ s.opacity = s.KhtmlOpacity = s.MozOpacity = o;
+ }
+ }
+
+ qx.Proto._modifyEnabled = function(propValue, propOldValue, propData)
+ {
+ if (this._image) {
+ this._applyEnabled();
+ }
+
+ return qx.ui.basic.Terminator.prototype._modifyEnabled.call(this, propValue, propOldValue, propData);
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PREFERRED DIMENSIONS: INNER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computePreferredInnerWidth = function()
+{
+ if (this.getLoaded())
+ {
+ return this.getPreloader().getWidth();
+ }
+ else if (qx.util.Validation.isValidString(this.getSource()))
+ {
+ var vPreloader = qx.manager.object.ImagePreloaderManager.getInstance().get(qx.manager.object.AliasManager.getInstance().resolvePath(this.getSource()));
+
+ if (vPreloader && vPreloader.isLoaded()) {
+ return vPreloader.getWidth();
+ }
+ }
+
+ return 0;
+}
+
+qx.Proto._computePreferredInnerHeight = function()
+{
+ if (this.getLoaded())
+ {
+ return this.getPreloader().getHeight();
+ }
+ else if (qx.util.Validation.isValidString(this.getSource()))
+ {
+ var vPreloader = qx.manager.object.ImagePreloaderManager.getInstance().get(qx.manager.object.AliasManager.getInstance().resolvePath(this.getSource()));
+
+ if (vPreloader && vPreloader.isLoaded()) {
+ return vPreloader.getHeight();
+ }
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPLY
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyContent = function()
+{
+ qx.ui.basic.Terminator.prototype._applyContent.call(this);
+
+ // Images load asyncron, so we need to force flushing here
+ // to get an up-to-date view when an image is loaded.
+ qx.ui.core.Widget.flushGlobalQueues();
+}
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._postApplyDimensions = function()
+ {
+ try
+ {
+ var vImageStyle = this._image.style;
+
+ if (this.getResizeToInner())
+ {
+ vImageStyle.pixelWidth = this.getInnerWidth();
+ vImageStyle.pixelHeight = this.getInnerHeight();
+ }
+ else
+ {
+ vImageStyle.pixelWidth = this.getPreferredInnerWidth();
+ vImageStyle.pixelHeight = this.getPreferredInnerHeight();
+ }
+ }
+ catch(ex)
+ {
+ this.error("postApplyDimensions failed", ex);
+ }
+ }
+}
+else
+{
+ qx.Proto._postApplyDimensions = function()
+ {
+ try
+ {
+ var vImageNode = this._image;
+
+ if (this.getResizeToInner())
+ {
+ vImageNode.width = this.getInnerWidth();
+ vImageNode.height = this.getInnerHeight();
+ }
+ else
+ {
+ vImageNode.width = this.getPreferredInnerWidth();
+ vImageNode.height = this.getPreferredInnerHeight();
+ }
+ }
+ catch(ex)
+ {
+ this.error("postApplyDimensions failed", ex);
+ }
+ }
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHANGES IN DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._changeInnerWidth = function(vNew, vOld)
+ {
+ if (this.getResizeToInner()) {
+ this._image.style.pixelWidth = vNew;
+ }
+ }
+
+ qx.Proto._changeInnerHeight = function(vNew, vOld)
+ {
+ if (this.getResizeToInner()) {
+ this._image.style.pixelHeight = vNew;
+ }
+ }
+}
+else
+{
+ qx.Proto._changeInnerWidth = function(vNew, vOld)
+ {
+ if (this.getResizeToInner()) {
+ this._image.width = vNew;
+ }
+ }
+
+ qx.Proto._changeInnerHeight = function(vNew, vOld)
+ {
+ if (this.getResizeToInner()) {
+ this._image.height = vNew;
+ }
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ var vPreloader = this.getPreloader();
+ if (vPreloader)
+ {
+ // remove event connection
+ vPreloader.removeEventListener("load", this._onload, this);
+ vPreloader.removeEventListener("error", this._onerror, this);
+
+ this.forcePreloader(null);
+ }
+
+ if (this._image)
+ {
+ // Remove leaking filter attribute before leaving page
+ this._image.style.filter = "";
+ this._image = null;
+ }
+
+ qx.manager.object.ImageManager.getInstance().remove(this);
+
+ return qx.ui.basic.Terminator.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Inline.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Inline.js
new file mode 100644
index 0000000000..f6c59cf486
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Inline.js
@@ -0,0 +1,37 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.basic.Inline", qx.ui.layout.CanvasLayout,
+function(vId)
+{
+ qx.ui.layout.CanvasLayout.call(this);
+
+ this.setStyleProperty("position", "relative");
+
+ if (qx.util.Validation.isValidString(vId)) {
+ this.setInlineNodeId(vId);
+ }
+});
+
+qx.OO.addProperty({ name : "inlineNodeId", type : "string" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Label.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Label.js
new file mode 100644
index 0000000000..a284649d98
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Label.js
@@ -0,0 +1,546 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+#require(qx.renderer.font.FontCache)
+#after(qx.renderer.font.FontObject)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.basic.Label", qx.ui.basic.Terminator,
+function(vHtml, vMnemonic)
+{
+ qx.ui.basic.Terminator.call(this);
+
+ // Apply constructor arguments
+ if (qx.util.Validation.isValidString(vHtml)) {
+ this.setHtml(vHtml);
+ }
+
+ if (qx.util.Validation.isValidString(vMnemonic)) {
+ this.setMnemonic(vMnemonic);
+ }
+
+ // Prohibit stretching through layout handler
+ this.setAllowStretchX(false);
+ this.setAllowStretchY(false);
+
+ // Auto Sized
+ this.auto();
+});
+
+qx.Class._measureNodes = {};
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "label" });
+
+/*!
+ Any text string which can contain HTML, too
+*/
+qx.OO.addProperty({ name : "html", type : "string" });
+
+/*!
+ The alignment of the text.
+*/
+qx.OO.addProperty({ name : "textAlign", type : "string", defaultValue : "left", possibleValues : [ "left", "center", "right", "justify" ] });
+
+/*!
+ The styles which should be copied
+*/
+qx.OO.addProperty({ name : "fontPropertiesProfile", type : "string", defaultValue : "default", possibleValues : [ "none", "default", "extended", "multiline", "extendedmultiline", "all" ] });
+
+/*!
+ A single character which will be underlined inside the text.
+*/
+qx.OO.addProperty({ name : "mnemonic", type : "string" });
+
+/*!
+ The font property describes how to paint the font on the widget.
+*/
+qx.OO.addProperty({ name : "font", type : "object", instance : "qx.renderer.font.Font", convert : qx.renderer.font.FontCache, allowMultipleArguments : true });
+
+/*!
+ Wrap the text?
+*/
+qx.OO.addProperty({ name : "wrap", type : "boolean", defaultValue : true });
+
+
+
+
+
+
+
+
+
+/* ************************************************************************
+ Class data, properties and methods
+************************************************************************ */
+
+/*
+---------------------------------------------------------------------------
+ DATA
+---------------------------------------------------------------------------
+*/
+
+qx.ui.basic.Label.SYMBOL_ELLIPSIS = String.fromCharCode(8230);
+qx.ui.basic.Label.SUPPORT_NATIVE_ELLIPSIS = qx.sys.Client.getInstance().isMshtml();
+
+// these are the properties what will be copied to the measuring frame.
+qx.ui.basic.Label._fontProperties =
+{
+ "none" : [],
+
+ "default" : ["fontFamily", "fontSize", "fontStyle", "fontWeight", "textDecoration"],
+ "extended" : ["fontFamily", "fontSize", "fontStyle", "fontWeight", "letterSpacing", "textDecoration", "textTransform", "whiteSpace", "wordSpacing"],
+
+ "multiline" : ["fontFamily", "fontSize", "fontStyle", "fontWeight", "textDecoration", "lineHeight", "wordWrap"],
+ "extendedmultiline" : ["fontFamily", "fontSize", "fontStyle", "fontWeight", "letterSpacing", "textDecoration", "textTransform", "whiteSpace", "wordSpacing", "lineHeight", "wordBreak", "wordWrap", "quotes"],
+
+ "all" : ["fontFamily", "fontSize", "fontStyle", "fontVariant", "fontWeight", "letterSpacing", "lineBreak", "lineHeight", "quotes", "textDecoration", "textIndent", "textShadow", "textTransform", "textUnderlinePosition", "whiteSpace", "wordBreak", "wordSpacing", "wordWrap"]
+}
+
+qx.ui.basic.Label.htmlToText = function(s) {
+ return String(s).replace(/\s+|<([^>])+>|&|<|>|"| |[0-9]+;|[0-9a-fA-F];]/gi, qx.ui.basic.Label._htmlToText);
+}
+
+qx.ui.basic.Label._htmlToText = function(s)
+{
+ switch(s)
+ {
+ case "&":
+ return "&";
+
+ case "<":
+ return "<";
+
+ case ">":
+ return ">";
+
+ case """:
+ return '"';
+
+ case " ":
+ return String.fromCharCode(160);
+
+ default:
+ if (s.substring(0, 3) == "") {
+ return String.fromCharCode(parseInt("0x" + s.substring(3, s.length - 1)));
+ }
+ else if (s.substring(0, 2) == "") {
+ return String.fromCharCode(s.substring(2, s.length - 1));
+ }
+ else if (/\s+/.test(s)) {
+ return " ";
+ }
+ else if (/^ |\n|\u00A0/g, qx.ui.basic.Label._textToHtml);
+}
+
+qx.ui.basic.Label._textToHtml = function(s)
+{
+ switch(s)
+ {
+ case "&":
+ return "&";
+
+ case "<":
+ return "<";
+
+ case ">":
+ return ">";
+
+ case "\n":
+ return " ";
+
+ default:
+ return " ";
+ }
+}
+
+qx.ui.basic.Label.createMeasureNode = function(vId)
+{
+ var vNode = qx.ui.basic.Label._measureNodes[vId];
+
+ if (!vNode)
+ {
+ vNode = document.createElement("div");
+ var vStyle = vNode.style;
+
+ vStyle.width = vStyle.height = "auto";
+ vStyle.visibility = "hidden";
+ vStyle.position = "absolute";
+ vStyle.zIndex = "-1";
+
+ document.body.appendChild(vNode);
+
+ qx.ui.basic.Label._measureNodes[vId] = vNode;
+ }
+
+ return vNode;
+}
+
+
+
+
+
+
+
+
+/* ************************************************************************
+ Instance data, properties and methods
+************************************************************************ */
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._htmlMode = false;
+qx.Proto._hasMnemonic = false;
+qx.Proto._mnemonicHtml = "";
+qx.Proto._mnemonicTest = null;
+
+qx.Proto._modifyHtml = function(propValue, propOldValue, propData)
+{
+ this._htmlMode = qx.util.Validation.isValidString(propValue) && propValue.match(/<.*>/) ? true : false;
+
+ if (this._isCreated) {
+ this._applyContent();
+ }
+
+ return true;
+}
+
+qx.Proto._modifyTextAlign = function(propValue, propOldValue, propData)
+{
+ this.setStyleProperty("textAlign", propValue);
+ return true;
+}
+
+qx.Proto._modifyMnemonic = function(propValue, propOldValue, propData)
+{
+ this._hasMnemonic = qx.util.Validation.isValidString(propValue) && propValue.length == 1;
+
+ this._mnemonicHtml = this._hasMnemonic ? "(" + propValue + " )" : "";
+ this._mnemonicTest = this._hasMnemonic ? new RegExp("^(((<([^>]|" + propValue + ")+>)|(&([^;]|" + propValue + ")+;)|[^&" + propValue + "])*)(" + propValue + ")", "i") : null;
+
+ return true;
+}
+
+qx.Proto._modifyFont = function(propValue, propOldValue, propData)
+{
+ this._invalidatePreferredInnerDimensions();
+
+ if (propValue) {
+ propValue._applyWidget(this);
+ } else if (propOldValue) {
+ propOldValue._resetWidget(this);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyWrap = function(propValue, propOldValue, propData)
+{
+ this.setStyleProperty("whiteSpace", propValue ? "normal" : "nowrap");
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HELPER FOR PREFERRED DIMENSION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computeObjectNeededDimensions = function()
+{
+ // copy styles
+ var vNode = this._copyStyles();
+
+ // prepare html
+ var vHtml = this.getHtml();
+
+ // test for mnemonic and fix content
+ if (this._hasMnemonic && !this._mnemonicTest.test(vHtml)) {
+ vHtml += this._mnemonicHtml;
+ }
+
+ // apply html
+ vNode.innerHTML = vHtml;
+
+ // store values
+ this._cachedPreferredInnerWidth = vNode.scrollWidth;
+ this._cachedPreferredInnerHeight = vNode.scrollHeight;
+}
+
+qx.Proto._copyStyles = function()
+{
+ var vProps = this.getFontPropertiesProfile();
+ var vNode = qx.ui.basic.Label.createMeasureNode(vProps);
+ var vUseProperties=qx.ui.basic.Label._fontProperties[vProps];
+ var vUsePropertiesLength=vUseProperties.length-1;
+ var vProperty=vUseProperties[vUsePropertiesLength--];
+
+ var vStyle = vNode.style;
+ var vTemp;
+
+ if (!vProperty) {
+ return vNode;
+ }
+
+ do {
+ vStyle[vProperty] = qx.util.Validation.isValid(vTemp = this.getStyleProperty([vProperty])) ? vTemp : "";
+ } while(vProperty=vUseProperties[vUsePropertiesLength--]);
+
+ return vNode;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PREFERRED DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computePreferredInnerWidth = function()
+{
+ this._computeObjectNeededDimensions();
+ return this._cachedPreferredInnerWidth;
+}
+
+qx.Proto._computePreferredInnerHeight = function()
+{
+ this._computeObjectNeededDimensions();
+ return this._cachedPreferredInnerHeight;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LAYOUT APPLY
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._postApply = function()
+{
+ var vHtml = this.getHtml();
+ var vElement = this._getTargetNode();
+ var vMnemonicMode = 0;
+
+ if (qx.util.Validation.isInvalidString(vHtml)) {
+ vElement.innerHTML = "";
+ return;
+ }
+
+ if (this._hasMnemonic) {
+ vMnemonicMode = this._mnemonicTest.test(vHtml) ? 1 : 2;
+ }
+
+ // works only with text, don't use when wrap is enabled
+ if (!this._htmlMode && !this.getWrap())
+ {
+ switch(this._computedWidthType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ case qx.ui.core.Widget.TYPE_PERCENT:
+
+ //carstenl: enabled truncation code for flex sizing, too. Appears to work except for the
+ // truncation code (gecko version), which I have disabled (see below).
+ case qx.ui.core.Widget.TYPE_FLEX:
+ var vNeeded = this.getPreferredInnerWidth();
+ var vInner = this.getInnerWidth();
+
+ if (vInner < vNeeded)
+ {
+ vElement.style.overflow = "hidden";
+
+ if (qx.ui.basic.Label.SUPPORT_NATIVE_ELLIPSIS)
+ {
+ vElement.style.textOverflow = "ellipsis";
+ vHtml += this._mnemonicHtml;
+ }
+ else
+ {
+ var vMeasureNode = this._copyStyles();
+
+ var vSplitString = vHtml.split(" ");
+ var vSplitLength = vSplitString.length;
+
+ var vWordIterator = 0;
+ var vCharaterIterator = 0;
+
+ var vPost = qx.ui.basic.Label.SYMBOL_ELLIPSIS;
+
+ var vUseInnerText = true;
+ if (vMnemonicMode == 2)
+ {
+ var vPost = this._mnemonicHtml + vPost;
+ vUseInnerText = false;
+ }
+
+ // Measure Words (if more than one)
+ if (vSplitLength > 1)
+ {
+ var vSplitTemp = [];
+
+ for (vWordIterator=0; vWordIterator vInner)
+ /* carstenl: The following code (truncate the text to fit in the available
+ * space, append ellipsis to indicate truncation) did not reliably
+ * work in my tests. Problem was that sometimes the measurer returned
+ * insanely high values for short texts, like "I..." requiring 738 px.
+ *
+ * I don't have time to examine this code in detail. Since all of my
+ * tests used flex width and the truncation code never was intended
+ * for this, I am disabling truncation if flex is active.
+ */
+ && (this._computedWidthType != qx.ui.core.Widget.TYPE_FLEX)){
+ break;
+ }
+ }
+
+ // Remove last word which does not fit
+ vSplitTemp.pop();
+
+ // Building new temportary array
+ vSplitTemp = [ vSplitTemp.join(" ") ];
+
+ // Extracting remaining string
+ vCharaterString = vHtml.replace(vSplitTemp[0], "");
+ }
+ else
+ {
+ var vSplitTemp = [];
+ vCharaterString = vHtml;
+ }
+
+ var vCharaterLength = vCharaterString.length;
+
+ // Measure Chars
+ for (var vCharaterIterator=0; vCharaterIterator vInner) {
+ break;
+ }
+ }
+
+ // Remove last char which does not fit
+ vSplitTemp.pop();
+
+ // Add mnemonic and ellipsis symbol
+ vSplitTemp.push(vPost);
+
+ // Building Final HTML String
+ vHtml = vSplitTemp.join("");
+ }
+
+ break;
+ }
+ else
+ {
+ vHtml += this._mnemonicHtml;
+ }
+
+ // no break here
+
+ default:
+ vElement.style.overflow = "";
+
+ if (qx.ui.basic.Label.SUPPORT_NATIVE_ELLIPSIS) {
+ vElement.style.textOverflow = "";
+ }
+ }
+ }
+
+ if (vMnemonicMode == 1)
+ {
+ // re-test: needed to make ellipsis handling correct
+ this._mnemonicTest.test(vHtml);
+ vHtml = RegExp.$1 + "" + RegExp.$7 + " " + RegExp.rightContext;
+ }
+
+ return this._postApplyHtml(vElement, vHtml, vMnemonicMode);
+}
+
+
+qx.Proto._postApplyHtml = function(vElement, vHtml, vMnemonicMode)
+{
+ if (this._htmlMode || vMnemonicMode > 0)
+ {
+ vElement.innerHTML = vHtml;
+ }
+ else
+ {
+ try {
+ qx.dom.Element.setTextContent(vElement, vHtml);
+ } catch(ex) {
+ vElement.innerHTML = vHtml;
+ }
+ }
+}
\ No newline at end of file
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Terminator.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Terminator.js
new file mode 100644
index 0000000000..2b77bb883c
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Terminator.js
@@ -0,0 +1,187 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+
+************************************************************************ */
+
+/*!
+ This widget is the last widget of the current child chain.
+*/
+qx.OO.defineClass("qx.ui.basic.Terminator", qx.ui.core.Widget,
+function() {
+ qx.ui.core.Widget.call(this);
+});
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPLY PADDING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyPaddingX = function(vParent, vChanges, vStyle)
+{
+ if (vChanges.paddingLeft) {
+ this._applyRuntimePaddingLeft(this.getPaddingLeft());
+ }
+
+ if (vChanges.paddingRight) {
+ this._applyRuntimePaddingRight(this.getPaddingRight());
+ }
+}
+
+qx.Proto._applyPaddingY = function(vParent, vChanges, vStyle)
+{
+ if (vChanges.paddingTop) {
+ this._applyRuntimePaddingTop(this.getPaddingTop());
+ }
+
+ if (vChanges.paddingBottom) {
+ this._applyRuntimePaddingBottom(this.getPaddingBottom());
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPLY CONTENT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyContent = function()
+{
+ // Small optimization: Only add innerPreferred jobs
+ // if we don't have a static width
+ if (this._computedWidthTypePixel) {
+ this._cachedPreferredInnerWidth = null;
+ } else {
+ this._invalidatePreferredInnerWidth();
+ }
+
+ // Small optimization: Only add innerPreferred jobs
+ // if we don't have a static height
+ if (this._computedHeightTypePixel) {
+ this._cachedPreferredInnerHeight = null;
+ } else {
+ this._invalidatePreferredInnerHeight();
+ }
+
+ // add load job
+ if (this._initialLayoutDone) {
+ this.addToJobQueue("load");
+ }
+}
+
+qx.Proto._layoutPost = function(vChanges) {
+ if (vChanges.initial || vChanges.load || vChanges.width || vChanges.height) {
+ this._postApply();
+ }
+}
+
+qx.Proto._postApply = qx.util.Return.returnTrue;
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ BOX DIMENSION HELPERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computeBoxWidthFallback = qx.Proto.getPreferredBoxWidth;
+qx.Proto._computeBoxHeightFallback = qx.Proto.getPreferredBoxHeight;
+
+qx.Proto._computePreferredInnerWidth = qx.util.Return.returnZero;
+qx.Proto._computePreferredInnerHeight = qx.util.Return.returnZero;
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ METHODS TO GIVE THE LAYOUTERS INFORMATIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._isWidthEssential = function()
+{
+ if (!this._computedLeftTypeNull && !this._computedRightTypeNull) {
+ return true;
+ }
+
+ if (!this._computedWidthTypeNull && !this._computedWidthTypeAuto) {
+ return true;
+ }
+
+ if (!this._computedMinWidthTypeNull && !this._computedMinWidthTypeAuto) {
+ return true;
+ }
+
+ if (!this._computedMaxWidthTypeNull && !this._computedMaxWidthTypeAuto) {
+ return true;
+ }
+
+ if (this._borderElement) {
+ return true;
+ }
+
+ return false;
+}
+
+qx.Proto._isHeightEssential = function()
+{
+ if (!this._computedTopTypeNull && !this._computedBottomTypeNull) {
+ return true;
+ }
+
+ if (!this._computedHeightTypeNull && !this._computedHeightTypeAuto) {
+ return true;
+ }
+
+ if (!this._computedMinHeightTypeNull && !this._computedMinHeightTypeAuto) {
+ return true;
+ }
+
+ if (!this._computedMaxHeightTypeNull && !this._computedMaxHeightTypeAuto) {
+ return true;
+ }
+
+ if (this._borderElement) {
+ return true;
+ }
+
+ return false;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/VerticalSpacer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/VerticalSpacer.js
new file mode 100644
index 0000000000..6887c9d3fd
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/VerticalSpacer.js
@@ -0,0 +1,31 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.basic.VerticalSpacer", qx.ui.basic.Terminator,
+function()
+{
+ qx.ui.basic.Terminator.call(this);
+
+ this.setHeight("1*");
+});
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/ColorPopup.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/ColorPopup.js
new file mode 100644
index 0000000000..523a98df8f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/ColorPopup.js
@@ -0,0 +1,387 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+
+************************************************************************ */
+
+/*!
+ A color popup
+*/
+qx.OO.defineClass("qx.ui.component.ColorPopup", qx.ui.popup.Popup,
+function(tables)
+{
+ qx.ui.popup.Popup.call(this);
+
+ this.setPadding(4);
+ this.auto();
+ this.setBorder(qx.renderer.border.BorderPresets.getInstance().outset);
+ this.setBackgroundColor("threedface");
+
+ this._tables = tables;
+
+ this._createLayout();
+ this._createAutoBtn();
+ this._createBoxes();
+ this._createPreview();
+ this._createSelectorBtn();
+
+ this.addEventListener("beforeAppear", this._onBeforeAppear);
+});
+
+qx.OO.addProperty({ name : "value", type : "object", instance : "qx.renderer.color.Color" });
+
+qx.OO.addProperty({ name : "red", type : "number", defaultValue : 0 });
+qx.OO.addProperty({ name : "green", type : "number", defaultValue : 0 });
+qx.OO.addProperty({ name : "blue", type : "number", defaultValue : 0 });
+
+qx.Proto._minZIndex = 1e5;
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CREATOR SUBS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._createLayout = function()
+{
+ this._layout = new qx.ui.layout.VerticalBoxLayout;
+ this._layout.setLocation(0, 0);
+ this._layout.auto();
+ this._layout.setSpacing(2);
+
+ this.add(this._layout);
+}
+
+qx.Proto._createAutoBtn = function()
+{
+ this._automaticBtn = new qx.ui.form.Button("Automatic");
+ this._automaticBtn.setWidth(null);
+ this._automaticBtn.setAllowStretchX(true);
+ this._automaticBtn.addEventListener("execute", this._onAutomaticBtnExecute, this);
+
+ this._layout.add(this._automaticBtn);
+}
+
+qx.Proto._recentTableId = "recent";
+qx.Proto._fieldWidth = 14;
+qx.Proto._fieldHeight = 14;
+qx.Proto._fieldNumber = 12;
+
+qx.Proto._createBoxes = function()
+{
+ this._boxes = {};
+
+ var tables = this._tables;
+ var table, box, boxLayout, field;
+
+ for (var tableId in tables)
+ {
+ table = tables[tableId];
+
+ box = new qx.ui.groupbox.GroupBox(table.label);
+ box.setHeight("auto");
+
+ this._boxes[tableId] = box;
+ this._layout.add(box);
+
+ boxLayout = new qx.ui.layout.HorizontalBoxLayout;
+ boxLayout.setLocation(0, 0);
+ boxLayout.setSpacing(1);
+ boxLayout.auto();
+ box.add(boxLayout);
+
+ for (var i=0; inull
+ * the current day (today) is shown.
+ *
+ * @event select {qx.event.type.DataEvent} Fired when a date was selected. The
+ * event holds the new selected date in its data property.
+ */
+qx.OO.defineClass("qx.ui.component.DateChooser", qx.ui.layout.BoxLayout,
+function(date) {
+ qx.ui.layout.BoxLayout.call(this);
+
+ this.setOrientation("vertical");
+
+ // Create the navigation bar
+ var navBar = new qx.ui.layout.BoxLayout;
+ navBar.set({ width:null, height:"auto", spacing:1 });
+
+ var lastYearBt = new qx.ui.toolbar.Button(null, "widget/datechooser/lastYear.png");
+ var lastMonthBt = new qx.ui.toolbar.Button(null, "widget/datechooser/lastMonth.png");
+ var monthYearLabel = new qx.ui.basic.Label;
+ var nextMonthBt = new qx.ui.toolbar.Button(null, "widget/datechooser/nextMonth.png");
+ var nextYearBt = new qx.ui.toolbar.Button(null, "widget/datechooser/nextYear.png");
+
+ lastYearBt.set({ show:'icon', toolTip:new qx.ui.popup.ToolTip("Last year"), spacing:0 });
+ lastMonthBt.set({ show:'icon', toolTip:new qx.ui.popup.ToolTip("Last month") });
+ nextMonthBt.set({ show:'icon', toolTip:new qx.ui.popup.ToolTip("Next month") });
+ nextYearBt.set({ show:'icon', toolTip:new qx.ui.popup.ToolTip("Next year") });
+
+ lastYearBt.setAppearance("datechooser-toolbar-button");
+ lastMonthBt.setAppearance("datechooser-toolbar-button");
+ nextMonthBt.setAppearance("datechooser-toolbar-button");
+ nextYearBt.setAppearance("datechooser-toolbar-button");
+
+ lastYearBt.addEventListener("click", this._onNavButtonClicked, this);
+ lastMonthBt.addEventListener("click", this._onNavButtonClicked, this);
+ nextMonthBt.addEventListener("click", this._onNavButtonClicked, this);
+ nextYearBt.addEventListener("click", this._onNavButtonClicked, this);
+
+ this._lastYearBt = lastYearBt;
+ this._lastMonthBt = lastMonthBt;
+ this._nextMonthBt = nextMonthBt;
+ this._nextYearBt = nextYearBt;
+
+ monthYearLabel.setAppearance("datechooser-monthyear");
+ monthYearLabel.set({ width:"1*" });
+
+ navBar.add(lastYearBt, lastMonthBt, monthYearLabel, nextMonthBt, nextYearBt);
+ this._monthYearLabel = monthYearLabel;
+ navBar.setHtmlAttribute("id", "navBar");
+
+ // Calculate the cell width and height
+ var testLabel = new qx.ui.basic.Label;
+ var testParent = new qx.ui.layout.CanvasLayout;
+ testParent.add(testLabel);
+ testLabel.setHtml("Xx");
+ testLabel.set({ paddingLeft : 5, paddingRight : 5 });
+ testLabel.setAppearance("datechooser-weekday");
+ var cellWidth = testLabel.getBoxWidth();
+ var cellHeight = testLabel.getBoxHeight();
+ testLabel.dispose();
+ testParent.dispose();
+
+ // Create the date pane
+ var datePane = new qx.ui.layout.GridLayout;
+ datePane.setAppearance("datechooser-datepane");
+ datePane.set({ width:"100%", height:"auto" });
+ datePane.setColumnCount(8);
+ datePane.setRowCount(7);
+ for (var i = 0; i < datePane.getColumnCount(); i++) {
+ datePane.setColumnWidth(i, cellWidth);
+ }
+ for (var i = 0; i < datePane.getRowCount(); i++) {
+ datePane.setRowHeight(i, cellHeight);
+ }
+
+ // Create the weekdays
+ // Add an empty label as spacer for the week numbers
+ var label = new qx.ui.basic.Label;
+ label.setAppearance("datechooser-week");
+ label.set({ width:"100%", height:"100%" });
+ label.addState("header");
+ datePane.add(label, 0, 0);
+
+ this._weekdayLabelArr = [];
+ for (var i = 0; i < 7; i++) {
+ var label = new qx.ui.basic.Label;
+ label.setAppearance("datechooser-weekday");
+ label.set({ width:"100%", height:"100%" });
+ datePane.add(label, i + 1, 0);
+ this._weekdayLabelArr.push(label);
+ }
+
+ // Add the days
+ this._dayLabelArr = [];
+ this._weekLabelArr = [];
+ for (var y = 0; y < 6; y++) {
+ // Add the week label
+ var label = new qx.ui.basic.Label;
+ label.setAppearance("datechooser-week");
+ label.set({ width:"100%", height:"100%" });
+ datePane.add(label, 0, y + 1);
+ this._weekLabelArr.push(label);
+
+ // Add the day labels
+ for (var x = 0; x < 7; x++) {
+ var label = new qx.ui.basic.Label;
+ label.setAppearance("datechooser-day");
+ label.set({ width:"100%", height:"100%" });
+ label.addEventListener("mousedown", this._onDayClicked, this);
+ label.addEventListener("dblclick", this._onDayDblClicked, this);
+ datePane.add(label, x + 1, y + 1);
+ this._dayLabelArr.push(label);
+ }
+ }
+
+ // Make focusable
+ this.setTabIndex(1);
+ this.addEventListener("keypress", this._onkeypress);
+
+ // Show the right date
+ var shownDate = (date != null) ? date : new Date();
+ this.showMonth(shownDate.getMonth(), shownDate.getFullYear());
+
+ // Add the main widgets
+ this.add(navBar);
+ this.add(datePane);
+
+});
+
+
+// ***** Properties *****
+
+/** The start of the week. 0 = sunday, 1 = monday, and so on. */
+qx.OO.addProperty({ name:"startOfWeek", type:"number", defaultValue:1 });
+/** The currently shown month. 0 = january, 1 = february, and so on. */
+qx.OO.addProperty({ name:"shownMonth", type:"number", defaultValue:null });
+/** The currently shown year. */
+qx.OO.addProperty({ name:"shownYear", type:"number", defaultValue:null });
+/** {Date} The currently selected date. */
+qx.OO.addProperty({ name:"date", type:"object", defaultValue:null });
+
+
+// property checker
+qx.Proto._checkDate = function(propValue, propData) {
+ // Use a clone of the date internally since date instances may be changed
+ return (propValue == null) ? null : new Date(propValue.getTime());
+}
+
+
+// property modifier
+qx.Proto._modifyDate = function(propValue, propOldValue, propData) {
+ var DateChooser = qx.ui.component.DateChooser;
+
+ if ((propValue != null) && (this.getShownMonth() != propValue.getMonth()
+ || this.getShownYear() != propValue.getFullYear()))
+ {
+ // The new date is in another month -> Show that month
+ this.showMonth(propValue.getMonth(), propValue.getFullYear());
+ } else {
+ // The new date is in the current month -> Just change the states
+ var newDay = (propValue == null) ? -1 : propValue.getDate();
+ for (var i = 0; i < 6 * 7; i++) {
+ var dayLabel = this._dayLabelArr[i];
+
+ if (dayLabel.hasState("otherMonth")) {
+ if (dayLabel.hasState("selected")) {
+ dayLabel.removeState("selected");
+ }
+ } else {
+ var day = parseInt(dayLabel.getHtml());
+ if (day == newDay) {
+ dayLabel.addState("selected");
+ } else if (dayLabel.hasState("selected")) {
+ dayLabel.removeState("selected");
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Event handler. Called when a navigation button has been clicked.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onNavButtonClicked = function(evt) {
+ var year = this.getShownYear();
+ var month = this.getShownMonth();
+
+ switch(evt.getCurrentTarget()) {
+ case this._lastYearBt:
+ year--;
+ break;
+ case this._lastMonthBt:
+ month--;
+ if (month < 0) {
+ month = 11;
+ year--;
+ }
+ break;
+ case this._nextMonthBt:
+ month++;
+ if (month >= 12) {
+ month = 0;
+ year++;
+ }
+ break;
+ case this._nextYearBt:
+ year++;
+ break;
+ }
+
+ this.showMonth(month, year);
+}
+
+
+/**
+ * Event handler. Called when a day has been clicked.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onDayClicked = function(evt) {
+ var time = evt.getCurrentTarget().dateTime;
+ this.setDate(new Date(time));
+}
+
+qx.Proto._onDayDblClicked = function() {
+ this.createDispatchDataEvent("select", this.getDate());
+}
+
+/**
+ * Event handler. Called when a key was pressed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onkeypress = function(evt) {
+ var dayIncrement = null;
+ var monthIncrement = null;
+ var yearIncrement = null;
+ if (evt.getModifiers() == 0) {
+ switch(evt.getKeyIdentifier()) {
+ case "Left":
+ dayIncrement = -1;
+ break;
+ case "Right":
+ dayIncrement = 1;
+ break;
+ case "Up":
+ dayIncrement = -7;
+ break;
+ case "Down":
+ dayIncrement = 7;
+ break;
+ case "PageUp":
+ monthIncrement = -1;
+ break;
+ case "PageDown":
+ monthIncrement = 1;
+ break;
+ case "Escape":
+ if (this.getDate() != null) {
+ this.setDate(null);
+ return true;
+ }
+ break;
+ case "Enter":
+ case "Space":
+ if (this.getDate() != null) {
+ this.createDispatchDataEvent("select", this.getDate());
+ }
+ return;
+ }
+ } else if (evt.getShiftKey()) {
+ switch(evt.getKeyIdentifier()) {
+ case "PageUp":
+ yearIncrement = -1;
+ break;
+ case "PageDown":
+ yearIncrement = 1;
+ break;
+ }
+ }
+
+ if (dayIncrement != null || monthIncrement != null || yearIncrement != null) {
+ var date = this.getDate();
+ if (date != null) {
+ date = new Date(date.getTime()); // TODO: Do cloning in getter
+ }
+ if (date == null) {
+ date = new Date();
+ } else {
+ if (dayIncrement != null) date.setDate(date.getDate() + dayIncrement);
+ if (monthIncrement != null) date.setMonth(date.getMonth() + monthIncrement);
+ if (yearIncrement != null) date.setFullYear(date.getFullYear() + yearIncrement);
+ }
+ this.setDate(date);
+ }
+}
+
+
+// ***** Methods *****
+
+
+/**
+ * Returns whether a certain day of week belongs to the week end.
+ *
+ * @param dayOfWeek {int} the day to check. (0 = sunday, 1 = monday, ...,
+ * 6 = saturday)
+ * @return {boolean} whether the day belongs to the week end.
+ */
+qx.Proto._isWeekend = function(dayOfWeek) {
+ return (dayOfWeek == 0) || (dayOfWeek == 6);
+}
+
+
+/**
+ * Shows a certain month.
+ *
+ * @param month {int ? null} the month to show (0 = january). If not set the month
+ * will remain the same.
+ * @param year {int ? null} the year to show. If not set the year will remain the
+ * same.
+ */
+qx.Proto.showMonth = function(month, year) {
+ if ((month != null && month != this.getShownMonth())
+ || (year != null && year != this.getShownYear()))
+ {
+ if (month != null) {
+ this.setShownMonth(month);
+ }
+ if (year != null) {
+ this.setShownYear(year);
+ }
+
+ this._updateDatePane();
+ }
+}
+
+
+/**
+ * Updates the date pane.
+ */
+qx.Proto._updateDatePane = function() {
+ var DateChooser = qx.ui.component.DateChooser;
+
+ var today = new Date();
+ var todayYear = today.getFullYear();
+ var todayMonth = today.getMonth();
+ var todayDayOfMonth = today.getDate();
+
+ var selDate = this.getDate();
+ var selYear = (selDate == null) ? -1 : selDate.getFullYear();
+ var selMonth = (selDate == null) ? -1 : selDate.getMonth();
+ var selDayOfMonth = (selDate == null) ? -1 : selDate.getDate();
+
+ var shownMonth = this.getShownMonth();
+ var shownYear = this.getShownYear();
+
+ var startOfWeek = this.getStartOfWeek();
+
+ // Create a help date that points to the first of the current month
+ var helpDate = new Date(this.getShownYear(), this.getShownMonth(), 1);
+
+ this._monthYearLabel.setHtml(DateChooser.MONTH_YEAR_FORMAT.format(helpDate));
+
+ // Show the day names
+ var firstDayOfWeek = helpDate.getDay();
+ var firstSundayInMonth = (1 + 7 - firstDayOfWeek) % 7;
+ for (var i = 0; i < 7; i++) {
+ var day = (i + startOfWeek) % 7;
+
+ var dayLabel = this._weekdayLabelArr[i];
+
+ helpDate.setDate(firstSundayInMonth + day);
+ dayLabel.setHtml(DateChooser.WEEKDAY_FORMAT.format(helpDate));
+
+ if (this._isWeekend(day)) {
+ dayLabel.addState("weekend");
+ } else {
+ dayLabel.removeState("weekend");
+ }
+ }
+
+ // Show the days
+ helpDate = new Date(shownYear, shownMonth, 1);
+ var nrDaysOfLastMonth = (7 + firstDayOfWeek - startOfWeek) % 7;
+ helpDate.setDate(helpDate.getDate() - nrDaysOfLastMonth);
+ for (var week = 0; week < 6; week++) {
+ this._weekLabelArr[week].setHtml(DateChooser.WEEK_FORMAT.format(helpDate));
+
+ for (var i = 0; i < 7; i++) {
+ var dayLabel = this._dayLabelArr[week * 7 + i];
+
+ var year = helpDate.getFullYear();
+ var month = helpDate.getMonth();
+ var dayOfMonth = helpDate.getDate();
+
+ var isSelectedDate = (selYear == year && selMonth == month && selDayOfMonth == dayOfMonth);
+ if (isSelectedDate) {
+ dayLabel.addState("selected");
+ } else {
+ dayLabel.removeState("selected");
+ }
+
+ if (month != shownMonth) {
+ dayLabel.addState("otherMonth");
+ } else {
+ dayLabel.removeState("otherMonth");
+ }
+
+ var isToday = (year == todayYear && month == todayMonth && dayOfMonth == todayDayOfMonth);
+ if (isToday) {
+ dayLabel.addState("today");
+ } else {
+ dayLabel.removeState("today");
+ }
+
+ dayLabel.setHtml("" + dayOfMonth);
+ dayLabel.dateTime = helpDate.getTime();
+
+ // Go to the next day
+ helpDate.setDate(helpDate.getDate() + 1);
+ }
+ }
+}
+
+
+/**
+ * {qx.util.format.DateFormat} The format for the date year
+ * label at the top center.
+ */
+qx.Class.MONTH_YEAR_FORMAT = new qx.util.format.DateFormat("MMMM yyyy");
+
+/**
+ * {qx.util.format.DateFormat} The format for the weekday
+ * labels (the headers of the date table).
+ */
+qx.Class.WEEKDAY_FORMAT = new qx.util.format.DateFormat("EE");
+
+/**
+ * {qx.util.format.DateFormat} The format for the week labels.
+ */
+qx.Class.WEEK_FORMAT = new qx.util.format.DateFormat("ww");
+
+
+// overridden
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ this._lastYearBt.removeEventListener("click", this._onNavButtonClicked, this);
+ this._lastMonthBt.removeEventListener("click", this._onNavButtonClicked, this);
+ this._nextMonthBt.removeEventListener("click", this._onNavButtonClicked, this);
+ this._nextYearBt.removeEventListener("click", this._onNavButtonClicked, this);
+
+ this._lastYearBt.dispose();
+ this._lastMonthBt.dispose();
+ this._nextMonthBt.dispose();
+ this._nextYearBt.dispose();
+
+ this._lastYearBt = null;
+ this._lastMonthBt = null;
+ this._nextMonthBt = null;
+ this._nextYearBt = null;
+
+ this._monthYearLabel.dispose();
+ this._monthYearLabel = null;
+
+ for (var i = 0; i < this._weekdayLabelArr.length; i++) {
+ this._weekdayLabelArr[i].dispose();
+ }
+ this._weekdayLabelArr = null;
+
+ for (var i = 0; i < this._dayLabelArr.length; i++) {
+ this._dayLabelArr[i].dispose();
+ this._dayLabelArr[i].removeEventListener("mousedown", this._onDayClicked, this);
+ this._dayLabelArr[i].removeEventListener("dblclick", this._onDayDblClicked, this);
+ }
+ this._dayLabelArr = null;
+
+ for (var i = 0; i < this._weekLabelArr.length; i++) {
+ this._weekLabelArr[i].dispose();
+ }
+ this._weekLabelArr = null;
+
+ this.removeEventListener("keypress", this._onkeypress);
+
+ return qx.ui.layout.BoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ClientDocument.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ClientDocument.js
new file mode 100644
index 0000000000..f65edcb32e
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ClientDocument.js
@@ -0,0 +1,450 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#require(qx.dom.StyleSheet)
+#require(qx.event.handler.EventHandler)
+#optional(qx.client.NativeWindow)
+#optional(qx.ui.window.Window)
+#optional(qx.manager.object.PopupManager)
+
+************************************************************************ */
+
+/**
+ * This is the basic widget of all qooxdoo applications.
+ *
+ * qx.ui.core.ClientDocument is the parent of all children inside your application. It
+ * also handles their resizing and focus navigation.
+ *
+ * @event windowblur {qx.event.type.Event} Fired when the window looses the
+ * focus. (Fired by {@link qx.event.handler.EventHandler})
+ * @event windowfocus {qx.event.type.Event} Fired when the window gets the
+ * focus. (Fired by {@link qx.event.handler.EventHandler})
+ * @event windowresize {qx.event.type.Event} Fired when the window has been
+ * resized. (Fired by {@link qx.event.handler.EventHandler})
+ */
+qx.OO.defineClass("qx.ui.core.ClientDocument", qx.ui.layout.CanvasLayout,
+function()
+{
+ this._window = window;
+ this._document = window.document;
+
+ // Init element
+ this.setElement(this._document.body);
+
+ // Needed hard-coded because otherwise the client document
+ // would not be added initially to the state queue
+ this.addToStateQueue();
+
+ qx.ui.layout.CanvasLayout.call(this);
+
+ // Don't use widget styles
+ this._styleProperties = {};
+
+ // Configure as focus root
+ this.activateFocusRoot();
+
+ // Cache current size
+ this._cachedInnerWidth = this._document.body.offsetWidth;
+ this._cachedInnerHeight = this._document.body.offsetHeight;
+
+ // Add Resize Handler
+ this.addEventListener("windowresize", this._onwindowresize);
+
+ // Dialog Support
+ this._modalWidgets = [];
+ this._modalNativeWindow = null;
+
+ // Register as focus root
+ qx.event.handler.EventHandler.getInstance().setFocusRoot(this);
+
+
+ // Init Resize Helper
+ /*
+ if (qx.sys.Client.getInstance().isGecko())
+ {
+ var o = this;
+ this._resizeHelper = window.setInterval(function() { o._onresizehelper() }, 100);
+ }
+ */
+});
+
+qx.OO.addProperty({ name : "globalCursor", type : "string" });
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "client-document" });
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFAULT SETTINGS
+---------------------------------------------------------------------------
+*/
+
+qx.Settings.setDefault("enableApplicationLayout", true);
+qx.Settings.setDefault("boxModelCorrection", true);
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ OVERWRITE WIDGET FUNCTIONS/PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyParent = qx.util.Return.returnTrue;
+qx.Proto._modifyVisible = qx.util.Return.returnTrue;
+
+qx.Proto._modifyElement = function(propValue, propOldValue, propData)
+{
+ this._isCreated = qx.util.Validation.isValidElement(propValue);
+
+ if (propOldValue)
+ {
+ propOldValue.qx_Widget = null;
+ }
+
+ if (propValue)
+ {
+ // add reference to widget instance
+ propValue.qx_Widget = this;
+
+ // link element and style reference
+ this._element = propValue;
+ this._style = propValue.style;
+ }
+ else
+ {
+ this._element = null;
+ this._style = null;
+ }
+
+ return true;
+}
+
+qx.Proto.getTopLevelWidget = qx.util.Return.returnThis;
+qx.Proto.getWindowElement = function() { return this._window; }
+qx.Proto.getDocumentElement = function() { return this._document; }
+
+qx.Proto.getParent = qx.Proto.getToolTip = qx.util.Return.returnNull;
+qx.Proto.isMaterialized = qx.Proto.isSeeable = qx.util.Return.returnTrue;
+
+qx.Proto._isDisplayable = true;
+qx.Proto._hasParent = false;
+qx.Proto._initialLayoutDone = true;
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ BLOCKER AND DIALOG SUPPORT
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Returns the blocker widget if already created; otherwise create it first
+ *
+ * @return {ClientDocumentBlocker} the blocker widget.
+ */
+qx.Proto._getBlocker = function()
+{
+ if (!this._blocker)
+ {
+ // Create blocker instance
+ this._blocker = new qx.ui.core.ClientDocumentBlocker;
+
+ // Add blocker events
+ this._blocker.addEventListener("mousedown", this.blockHelper, this);
+ this._blocker.addEventListener("mouseup", this.blockHelper, this);
+
+ // Add blocker to client document
+ this.add(this._blocker);
+ }
+
+ return this._blocker;
+};
+
+qx.Proto.blockHelper = function(e)
+{
+ if (this._modalNativeWindow)
+ {
+ try
+ {
+ this._modalNativeWindow._window.focus();
+ }
+ catch(ex)
+ {
+ this.debug("Window seems to be closed already! => Releasing Blocker: (" + e.getType() + ")", ex);
+ this.release(this._modalNativeWindow);
+ }
+ }
+}
+
+qx.Proto.block = function(vActiveChild)
+{
+ // this.debug("BLOCK: " + vActiveChild.toHashCode());
+
+ this._getBlocker().show();
+
+ if (qx.OO.isAvailable("qx.ui.window.Window") && vActiveChild instanceof qx.ui.window.Window)
+ {
+ this._modalWidgets.push(vActiveChild);
+
+ var vOrigIndex = vActiveChild.getZIndex();
+ this._getBlocker().setZIndex(vOrigIndex);
+ vActiveChild.setZIndex(vOrigIndex+1);
+ }
+ else if (qx.OO.isAvailable("qx.client.NativeWindow") && vActiveChild instanceof qx.client.NativeWindow)
+ {
+ this._modalNativeWindow = vActiveChild;
+ this._getBlocker().setZIndex(1e7);
+ }
+}
+
+qx.Proto.release = function(vActiveChild)
+{
+ // this.debug("RELEASE: " + vActiveChild.toHashCode());
+
+ if (vActiveChild)
+ {
+ if (qx.OO.isAvailable("qx.client.NativeWindow") && vActiveChild instanceof qx.client.NativeWindow)
+ {
+ this._modalNativeWindow = null;
+ }
+ else
+ {
+ qx.lang.Array.remove(this._modalWidgets, vActiveChild);
+ }
+ }
+
+ var l = this._modalWidgets.length;
+ if (l == 0)
+ {
+ this._getBlocker().hide();
+ }
+ else
+ {
+ var oldActiveChild = this._modalWidgets[l-1];
+
+ var o = oldActiveChild.getZIndex();
+ this._getBlocker().setZIndex(o);
+ oldActiveChild.setZIndex(o+1);
+ }
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CSS API
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.createStyleElement = function(vCssText) {
+ return qx.dom.StyleSheet.createElement(vCssText);
+}
+
+qx.Proto.addCssRule = function(vSheet, vSelector, vStyle) {
+ return qx.dom.StyleSheet.addRule(vSheet, vSelector, vStyle);
+}
+
+qx.Proto.removeCssRule = function(vSheet, vSelector) {
+ return qx.dom.StyleSheet.removeRule(vSheet, vSelector);
+}
+
+qx.Proto.removeAllCssRules = function(vSheet) {
+ return qx.dom.StyleSheet.removeAllRules(vSheet);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CSS FIX
+---------------------------------------------------------------------------
+*/
+if (qx.Settings.getValueOfClass("qx.ui.core.ClientDocument", "boxModelCorrection")) {
+ qx.dom.StyleSheet.createElement("html,body{margin:0;border:0;padding:0;}" +
+ " html{border:0 none;} *{" + qx.sys.Client.getInstance().getEngineBoxSizingAttribute() +
+ ":border-box;} img{" + qx.sys.Client.getInstance().getEngineBoxSizingAttribute() +
+ ":content-box;}");
+}
+if (qx.Settings.getValueOfClass("qx.ui.core.ClientDocument", "enableApplicationLayout")) {
+ qx.dom.StyleSheet.createElement("html,body{width:100%;height:100%;overflow:hidden;}");
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ GLOBAL CURSOR SUPPORT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyGlobalCursor = function(propValue, propOldValue, propData)
+{
+ if (!this._globalCursorStyleSheet) {
+ this._globalCursorStyleSheet = this.createStyleElement();
+ }
+
+ // Selector based remove does not work with the "*" selector in mshtml
+ // this.removeCssRule(this._globalCursorStyleSheet, "*");
+
+ this.removeAllCssRules(this._globalCursorStyleSheet);
+
+ if (propValue) {
+ this.addCssRule(this._globalCursorStyleSheet, "*", "cursor:" + propValue + " !important");
+ }
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ WINDOW RESIZE HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onwindowresize = function(e)
+{
+ // Hide popups, tooltips, ...
+ if (qx.OO.isAvailable("qx.manager.object.PopupManager")) {
+ qx.manager.object.PopupManager.getInstance().update();
+ }
+
+ // Update children
+ this._recomputeInnerWidth();
+ this._recomputeInnerHeight();
+
+ // Flush queues
+ qx.ui.core.Widget.flushGlobalQueues();
+}
+
+// This was an idea to allow mozilla more realtime document resize updates
+// but it seems so, that mozilla stops javascript execution while the user
+// resize windows. Bad.
+
+/*
+qx.Proto._onwindowresizehelper = function()
+{
+ // Test for changes
+ var t1 = this._recomputeInnerWidth();
+ var t2 = this._recomputeInnerHeight();
+
+ // Flush queues
+ if (t1 || t2) {
+ qx.ui.core.Widget.flushGlobalQueues();
+ }
+}
+*/
+
+qx.Proto._computeInnerWidth = function() {
+ return this._document.body.offsetWidth;
+}
+
+qx.Proto._computeInnerHeight = function() {
+ return this._document.body.offsetHeight;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ delete this._document;
+ delete this._modalWidgets;
+ delete this._modalNativeWindow;
+
+ // Remove Resize Handler
+ this.removeEventListener("windowresize", this._onwindowresize);
+
+ this._globalCursorStyleSheet = null;
+
+ if (this._blocker)
+ {
+ this._blocker.removeEventListener("mousedown", this.blockHelper, this);
+ this._blocker.removeEventListener("mouseup", this.blockHelper, this);
+
+ this._blocker.dispose();
+ this._blocker = null;
+ }
+
+ /*
+ if (this._resizeHelper)
+ {
+ window.clearInterval(this._resizeHelper);
+ this._resizeHelper = null;
+ }
+ */
+
+ return qx.ui.layout.CanvasLayout.prototype.dispose.call(this);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFER SINGLETON INSTANCE
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Singleton Instance Getter
+ */
+qx.Class.getInstance = qx.util.Return.returnInstance;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ClientDocumentBlocker.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ClientDocumentBlocker.js
new file mode 100644
index 0000000000..5acbb85e12
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ClientDocumentBlocker.js
@@ -0,0 +1,39 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+
+************************************************************************ */
+
+/*!
+ qx.ui.core.ClientDocumentBlocker blocks the inputs from the user.
+ This will be used internally to allow better modal dialogs for example.
+*/
+qx.OO.defineClass("qx.ui.core.ClientDocumentBlocker", qx.ui.basic.Terminator,
+function()
+{
+ qx.ui.basic.Terminator.call(this);
+
+ this.setEdge(0);
+ this.setZIndex(1e8);
+ this.setDisplay(false);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "blocker" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/Parent.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/Parent.js
new file mode 100644
index 0000000000..29e886170a
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/Parent.js
@@ -0,0 +1,1207 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#optional(qx.event.handler.FocusHandler)
+#optional(qx.manager.object.ToolTipManager)
+#optional(qx.manager.object.PopupManager)
+#optional(qx.dom.ElementFromPoint)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.core.Parent", qx.ui.core.Widget,
+function()
+{
+ if (this.classname == qx.ui.core.Parent.ABSTRACT_CLASS) {
+ throw new Error("Please omit the usage of qx.ui.core.Parent directly. Choose between any widget which inherits from qx.ui.core.Parent and so comes with a layout implementation!");
+ }
+
+ qx.ui.core.Widget.call(this);
+
+ // Contains all children
+ this._children = [];
+
+ // Create instanceof layout implementation
+ this._layoutImpl = this._createLayoutImpl();
+});
+
+qx.ui.core.Parent.ABSTRACT_CLASS = "qx.ui.core.Parent";
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Individual focus handler for all child elements.
+*/
+qx.OO.addProperty({ name : "focusHandler", type : "object", instance : "qx.event.handler.FocusHandler" });
+
+/*!
+ The current active child.
+*/
+qx.OO.addProperty({ name : "activeChild", type : "object", instance : "qx.ui.core.Widget" });
+
+/*!
+ The current focused child.
+*/
+qx.OO.addProperty({ name : "focusedChild", type : "object", instance : "qx.ui.core.Widget" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CACHED PRIVATE PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addCachedProperty({ name : "visibleChildren", defaultValue : null });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ FOCUS HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.isFocusRoot = function() {
+ return this.getFocusHandler() != null;
+}
+
+qx.Proto.getFocusRoot = function()
+{
+ if (this.isFocusRoot()) {
+ return this;
+ }
+
+ if(this._hasParent) {
+ return this.getParent().getFocusRoot();
+ }
+
+ return null;
+}
+
+qx.Proto.activateFocusRoot = function() {
+ this.setFocusHandler(new qx.event.handler.FocusHandler(this));
+}
+
+qx.Proto._onfocuskeyevent = function(e) {
+ this.getFocusHandler()._onkeyevent(this, e);
+}
+
+qx.Proto._modifyFocusHandler = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ // Add Key Handler
+ this.addEventListener("keydown", this._onfocuskeyevent);
+ this.addEventListener("keypress", this._onfocuskeyevent);
+
+ // Activate focus handling (but keep already configured tabIndex)
+ if (this.getTabIndex() < 1) {
+ this.setTabIndex(1);
+ }
+
+ // But hide the focus outline
+ this.setHideFocus(true);
+
+ // Make myself the default
+ this.setActiveChild(this);
+ }
+ else
+ {
+ // Remove Key Handler
+ this.removeEventListener("keydown", this._onfocuskeyevent);
+ this.removeEventListener("keypress", this._onfocuskeyevent);
+
+ // Deactivate focus handling
+ this.setTabIndex(-1);
+
+ // Don't hide focus outline
+ this.setHideFocus(false);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyFocusedChild = function(propValue, propOldValue, propData)
+{
+ // this.debug("FocusedChild: " + propValue);
+
+ var vFocusValid = qx.util.Validation.isValidObject(propValue);
+ var vBlurValid = qx.util.Validation.isValidObject(propOldValue);
+
+ if (qx.OO.isAvailable("qx.manager.object.PopupManager") && vFocusValid)
+ {
+ var vMgr = qx.manager.object.PopupManager.getInstance();
+ if (vMgr) {
+ vMgr.update(propValue);
+ }
+ }
+
+ if (vBlurValid)
+ {
+ // Dispatch FocusOut
+ if (propOldValue.hasEventListeners("focusout"))
+ {
+ var vEventObject = new qx.event.type.FocusEvent("focusout", propOldValue);
+
+ if (vFocusValid) {
+ vEventObject.setRelatedTarget(propValue);
+ }
+
+ propOldValue.dispatchEvent(vEventObject);
+ vEventObject.dispose();
+ }
+ }
+
+ if (vFocusValid)
+ {
+ if (propValue.hasEventListeners("focusin"))
+ {
+ // Dispatch FocusIn
+ var vEventObject = new qx.event.type.FocusEvent("focusin", propValue);
+
+ if (vBlurValid) {
+ vEventObject.setRelatedTarget(propOldValue);
+ }
+
+ propValue.dispatchEvent(vEventObject);
+ vEventObject.dispose();
+ }
+ }
+
+ if (vBlurValid)
+ {
+ if (this.getActiveChild() == propOldValue) {
+ this.setActiveChild(null);
+ }
+
+ propOldValue.setFocused(false);
+
+ // Dispatch Blur
+ var vEventObject = new qx.event.type.FocusEvent("blur", propOldValue);
+
+ if (vFocusValid) {
+ vEventObject.setRelatedTarget(propValue);
+ }
+
+ propOldValue.dispatchEvent(vEventObject);
+
+ if (qx.OO.isAvailable("qx.manager.object.ToolTipManager"))
+ {
+ var vMgr = qx.manager.object.ToolTipManager.getInstance();
+ if (vMgr) {
+ vMgr.handleBlur(vEventObject);
+ }
+ }
+
+ vEventObject.dispose();
+ }
+
+ if (vFocusValid)
+ {
+ this.setActiveChild(propValue);
+ propValue.setFocused(true);
+ qx.event.handler.EventHandler.getInstance().setFocusRoot(this);
+
+ // Dispatch Focus
+ var vEventObject = new qx.event.type.FocusEvent("focus", propValue);
+
+ if (vBlurValid) {
+ vEventObject.setRelatedTarget(propOldValue);
+ }
+
+ propValue.dispatchEvent(vEventObject);
+
+ if (qx.OO.isAvailable("qx.manager.object.ToolTipManager"))
+ {
+ var vMgr = qx.manager.object.ToolTipManager.getInstance();
+ if (vMgr) {
+ vMgr.handleFocus(vEventObject);
+ }
+ }
+
+ vEventObject.dispose();
+ }
+
+ // Flush Queues
+ // Do we really need this?
+ // qx.ui.core.Widget.flushGlobalQueues();
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LAYOUT IMPLEMENTATION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._layoutImpl = null;
+
+qx.Proto._createLayoutImpl = function() {
+ return null;
+}
+
+qx.Proto.getLayoutImpl = function() {
+ return this._layoutImpl;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN MANAGMENT: MANAGE ALL
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Return the array of all children
+*/
+qx.Proto.getChildren = function() {
+ return this._children;
+}
+
+/*!
+ Get children count
+*/
+qx.Proto.getChildrenLength = function() {
+ return this.getChildren().length;
+}
+
+/*!
+ Check if the widget has a children
+*/
+qx.Proto.hasChildren = function() {
+ return this.getChildrenLength() > 0;
+}
+
+/*!
+ Check if there are any childrens inside
+*/
+qx.Proto.isEmpty = function() {
+ return this.getChildrenLength() == 0;
+}
+
+/*!
+ Get the position of a children.
+*/
+qx.Proto.indexOf = function(vChild) {
+ return this.getChildren().indexOf(vChild);
+}
+
+/*!
+Check if the given qx.ui.core.Widget is a children.
+
+#param des[qx.ui.core.Widget]: The widget which should be checked.
+*/
+qx.Proto.contains = function(vWidget)
+{
+ switch(vWidget)
+ {
+ case null:
+ return false;
+
+ case this:
+ return true;
+
+ default:
+ // try the next parent of the widget (recursive until found)
+ return this.contains(vWidget.getParent());
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN MANAGMENT: MANAGE VISIBLE ONES
+
+ uses a cached private property
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Return the array of all visible children
+ (which are configured as visible=true)
+*/
+qx.Proto._computeVisibleChildren = function()
+{
+ var vVisible = [];
+ var vChildren = this.getChildren();
+ var vLength = vChildren.length;
+
+ for (var i=0; i 0;
+}
+
+/*!
+ Check if there are any visible childrens inside
+*/
+qx.Proto.isVisibleEmpty = function() {
+ return this.getVisibleChildrenLength() == 0;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN MANAGMENT: ADD
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Add/Append another widget. Allows to add multiple at
+ one, a parameter could be a widget.
+*/
+qx.Proto.add = function()
+{
+ var vWidget;
+
+ for (var i=0, l=arguments.length; i vTargetIndex) {
+ vTargetIndex++;
+ }
+
+ return this.addAt(vChild, Math.max(0, vTargetIndex-1));
+}
+
+/*!
+ Add a widget after another already inserted child
+*/
+qx.Proto.addAfter = function(vChild, vAfter)
+{
+ var vChildren = this.getChildren();
+ var vTargetIndex = vChildren.indexOf(vAfter);
+
+ if (vTargetIndex == -1) {
+ throw new Error("Child to add after: " + vAfter + " is not inside this parent.");
+ }
+
+ var vSourceIndex = vChildren.indexOf(vChild);
+
+ if (vSourceIndex != -1 && vSourceIndex < vTargetIndex) {
+ vTargetIndex--;
+ }
+
+ return this.addAt(vChild, Math.min(vChildren.length, vTargetIndex+1));
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN MANAGMENT: REMOVE
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Remove one or multiple childrens.
+*/
+qx.Proto.remove = function()
+{
+ var vWidget;
+
+ for (var i=0, l=arguments.length; i omitting!");
+ return;
+ }
+
+ // APPLY LAYOUT
+ var vChanges = vChild._layoutChanges;
+
+ // this.debug("Layouting " + vChild + ": " + qx.lang.Object.getKeysAsString(vChanges));
+
+ try
+ {
+ if (vChanges.borderX) {
+ this._applyBorderX(vChild, vChanges);
+ }
+
+ if (vChanges.borderY) {
+ this._applyBorderY(vChild, vChanges);
+ }
+ }
+ catch(ex)
+ {
+ this.error("Could not apply border to child " + vChild, ex);
+ }
+
+ try
+ {
+ if (vChanges.paddingLeft || vChanges.paddingRight) {
+ vChild._applyPaddingX(this, vChanges);
+ }
+
+ if (vChanges.paddingTop || vChanges.paddingBottom) {
+ vChild._applyPaddingY(this, vChanges);
+ }
+ }
+ catch(ex)
+ {
+ this.error("Could not apply padding to child " + vChild, ex);
+ }
+
+
+ // WRAP TO LAYOUT ENGINE
+ try
+ {
+ this.getLayoutImpl().layoutChild(vChild, vChanges);
+ }
+ catch(ex)
+ {
+ this.error("Could not layout child " + vChild + " through layout handler", ex);
+ }
+
+
+ // POST LAYOUT
+ try
+ {
+ vChild._layoutPost(vChanges);
+ }
+ catch(ex)
+ {
+ this.error("Could not post layout child " + vChild, ex);
+ }
+
+
+ // DISPLAY DOM NODE
+ try
+ {
+ // insert dom node (if initial flag enabled)
+ if (vChanges.initial)
+ {
+ vChild._initialLayoutDone = true;
+ qx.ui.core.Widget.addToGlobalDisplayQueue(vChild);
+ }
+ }
+ catch(ex)
+ {
+ this.error("Could not handle display updates from layout flush for child " + vChild, ex);
+ }
+
+
+ // CLEANUP
+ vChild._layoutChanges = {};
+
+ delete vChild._isInParentLayoutQueue;
+ delete this._childrenQueue[vChild.toHashCode()];
+}
+
+qx.Proto._layoutPost = qx.util.Return.returnTrue;
+
+/*!
+ Fix Operas Rendering Bugs
+*/
+if (qx.sys.Client.getInstance().isOpera())
+{
+ qx.Proto._layoutChildOrig = qx.Proto._layoutChild;
+
+ qx.Proto._layoutChild = function(vChild)
+ {
+ if (!vChild._initialLayoutDone || !vChild._layoutChanges.borderX || !vChild._layoutChanges.borderY) {
+ return this._layoutChildOrig(vChild);
+ }
+
+ var vStyle = vChild.getElement().style;
+
+ var vOldDisplay = vStyle.display;
+ vStyle.display = "none";
+ var vRet = this._layoutChildOrig(vChild);
+ vStyle.display = vOldDisplay;
+
+ return vRet;
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DIMENSION CACHE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computePreferredInnerWidth = function() {
+ return this.getLayoutImpl().computeChildrenNeededWidth();
+}
+
+qx.Proto._computePreferredInnerHeight = function() {
+ return this.getLayoutImpl().computeChildrenNeededHeight();
+}
+
+qx.Proto._changeInnerWidth = function(vNew, vOld)
+{
+ var vLayout = this.getLayoutImpl();
+
+ if (vLayout.invalidateChildrenFlexWidth) {
+ vLayout.invalidateChildrenFlexWidth();
+ }
+
+ this.forEachVisibleChild(function()
+ {
+ if (vLayout.updateChildOnInnerWidthChange(this) && this._recomputeBoxWidth())
+ {
+ this._recomputeOuterWidth();
+ this._recomputeInnerWidth();
+ }
+ });
+}
+
+qx.Proto._changeInnerHeight = function(vNew, vOld)
+{
+ var vLayout = this.getLayoutImpl();
+
+ if (vLayout.invalidateChildrenFlexHeight) {
+ vLayout.invalidateChildrenFlexHeight();
+ }
+
+ this.forEachVisibleChild(function()
+ {
+ if (vLayout.updateChildOnInnerHeightChange(this) && this._recomputeBoxHeight())
+ {
+ this._recomputeOuterHeight();
+ this._recomputeInnerHeight();
+ }
+ });
+}
+
+qx.Proto.getInnerWidthForChild = function(vChild) {
+ return this.getInnerWidth();
+}
+
+qx.Proto.getInnerHeightForChild = function(vChild) {
+ return this.getInnerHeight();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ WIDGET FROM POINT SUPPORT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getWidgetFromPointHelper = function(x, y)
+{
+ var ch = this.getChildren();
+
+ for (var chl=ch.length, i=0; i=0; i--)
+ {
+ this._children[i].dispose();
+ this._children[i] = null;
+ }
+
+ this._children = null;
+ }
+
+ delete this._cachedVisibleChildren;
+
+ // Remove Key Handler
+ if (this.getFocusHandler())
+ {
+ this.removeEventListener("keydown", this._onfocuskeyevent);
+ this.removeEventListener("keypress", this._onfocuskeyevent);
+
+ this.forceFocusHandler(null);
+ }
+
+ return qx.ui.core.Widget.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ScrollBar.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ScrollBar.js
new file mode 100644
index 0000000000..c4630fba87
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ScrollBar.js
@@ -0,0 +1,260 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+/**
+ * A scroll bar.
+ *
+ * @param horizontal {boolean ? false} whether the scroll bar should be
+ * horizontal. If false it will be vertical.
+ */
+qx.OO.defineClass("qx.ui.core.ScrollBar", qx.ui.layout.BoxLayout,
+function(horizontal) {
+ qx.ui.layout.BoxLayout.call(this, horizontal ? "horizontal" : "vertical");
+
+ this._horizontal = (horizontal == true);
+
+ this._scrollBar = new qx.ui.layout.CanvasLayout;
+ if (qx.sys.Client.getInstance().isGecko()) {
+ // NOTE: We have to force not using position:absolute, because this causes
+ // strange looking scrollbars in some cases (e.g. in Firefox under
+ // Linux the horizontal scrollbar is too high)
+ this._scrollBar.setStyleProperty("position", "");
+ }
+ this._scrollBar.setOverflow(horizontal ? "scrollX" : "scrollY");
+ this._scrollBar.enableInlineEvent("scroll");
+ this._scrollBar.addEventListener("scroll", this._onscroll, this);
+
+ this._scrollContent = new qx.ui.basic.Terminator;
+ if (qx.sys.Client.getInstance().isGecko()) {
+ this._scrollContent.setStyleProperty("position", "");
+ }
+ this._scrollBar.add(this._scrollContent);
+
+ if (this._horizontal) {
+ this._scrollContent.setHeight(5);
+ this._scrollBar.setWidth("100%");
+ this._scrollBar.setHeight(this._getScrollBarWidth());
+
+ // IE needs that the scrollbar element has a width of +1
+ if (qx.sys.Client.getInstance().isMshtml()) {
+ this.setHeight(this._getScrollBarWidth());
+ this.setOverflow("hidden");
+ this._scrollBar.setHeight(this._getScrollBarWidth() + 1);
+ this._scrollBar.setTop(-1);
+ }
+ } else {
+ this._scrollContent.setWidth(5);
+ this._scrollBar.setHeight("100%");
+ this._scrollBar.setWidth(this._getScrollBarWidth());
+
+ // IE needs that the scrollbar element has a width of +1
+ if (qx.sys.Client.getInstance().isMshtml()) {
+ this.setWidth(this._getScrollBarWidth());
+ this.setOverflow("hidden");
+ this._scrollBar.setWidth(this._getScrollBarWidth() + 1);
+ this._scrollBar.setLeft(-1);
+ }
+ }
+
+ this.add(this._scrollBar);
+
+ this.setMaximum(0);
+});
+
+/**
+ * The current value of the scroll bar. This value is between 0 and
+ * (maxium - size), where size is the width of a horizontal resp. the height of
+ * a vertical scroll bar in pixels.
+ *
+ * @see #maximum
+ */
+qx.OO.addProperty({ name:"value", type:"number", defaultValue:0, allowNull:false });
+
+/**
+ * The maximum value of the scroll bar. Note that the size of the scroll bar is
+ * substracted.
+ *
+ * @see #value
+ */
+qx.OO.addProperty({ name:"maximum", type:"number", allowNull:false });
+
+/**
+ * Whether to merge consecutive scroll event. If true, events will be collected
+ * until the user stops scrolling, so the scroll bar itself will move smoothly
+ * and the scrolled content will update asynchroniously.
+ */
+qx.OO.addProperty({ name:"mergeEvents", type:"boolean", defaultValue:false, allowNull:false });
+
+
+// property checker
+qx.Proto._checkValue = function(propValue, propData) {
+ var innerSize = !this.getElement() ? 0 :
+ (this._horizontal ? this.getInnerWidth() : this.getInnerHeight());
+
+ // NOTE: We can't use Number.limit here because our maximum may get negative
+ // (when the scrollbar isn't needed). In this case Number.limit returns
+ // this negative maximum instead of 0. But we need that the minimum is
+ // stronger than the maximum.
+ // -> We use Math.max and Math.min
+ return Math.max(0, Math.min(this.getMaximum() - innerSize, propValue));
+}
+
+
+// property modifier
+qx.Proto._modifyValue = function(propValue, propOldValue, propData) {
+ if (! this._internalValueChange && this._isCreated) {
+ this._positionKnob(propValue);
+ }
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyMaximum = function(propValue, propOldValue, propData) {
+ if (this._horizontal) {
+ this._scrollContent.setWidth(propValue);
+ } else {
+ this._scrollContent.setHeight(propValue);
+ }
+
+ // recheck the value
+ this.setValue(this._checkValue(this.getValue()));
+
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyVisibility = function(propValue, propOldValue, propData) {
+ if (! propValue) {
+ this._positionKnob(0);
+ } else {
+ this._positionKnob(this.getValue());
+ }
+
+ return qx.ui.layout.BoxLayout.prototype._modifyVisibility.call(this, propValue, propOldValue, propData);
+};
+
+
+// overridden
+qx.Proto._computePreferredInnerWidth = function() {
+ return this._horizontal ? 0 : this._getScrollBarWidth();
+}
+
+
+// overridden
+qx.Proto._computePreferredInnerHeight = function() {
+ return this._horizontal ? this._getScrollBarWidth() : 0;
+}
+
+
+/**
+ * Gets the width of vertical scroll bar.
+ *
+ * @return {int} the width in pixels.
+ */
+qx.Proto._getScrollBarWidth = function() {
+ // Auto-detect the scrollbar width
+ if (qx.ui.core.ScrollBar._scrollBarWidth == null) {
+ var dummy = document.createElement("div");
+ dummy.style.width = "100px";
+ dummy.style.height = "100px";
+ dummy.style.overflow = "scroll";
+ dummy.style.visibility = "hidden";
+ document.body.appendChild(dummy);
+ qx.ui.core.ScrollBar._scrollBarWidth = dummy.offsetWidth - dummy.clientWidth;
+ document.body.removeChild(dummy);
+ }
+ return qx.ui.core.ScrollBar._scrollBarWidth;
+}
+
+
+/**
+ * Event handler. Called when the user scrolled.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onscroll = function(evt) {
+ var value = this._horizontal ? this._scrollBar.getScrollLeft() : this._scrollBar.getScrollTop();
+ if (this.getMergeEvents()) {
+ this._lastScrollEventValue = value;
+ window.clearTimeout(this._setValueTimerId);
+ var self = this;
+ this._setValueTimerId = window.setTimeout(function() {
+ self._internalValueChange = true;
+ self.setValue(self._lastScrollEventValue);
+ self._internalValueChange = false;
+ qx.ui.core.Widget.flushGlobalQueues();
+ }, qx.ui.core.ScrollBar.EVENT_DELAY);
+ } else {
+ this._internalValueChange = true;
+ this.setValue(value);
+ this._internalValueChange = false;
+ qx.ui.core.Widget.flushGlobalQueues();
+ }
+}
+
+
+/**
+ * Positions the scroll bar knob at a certain value.
+ *
+ * @param value {int} The value where to postion the scroll bar.
+ */
+qx.Proto._positionKnob = function(value) {
+ if (this._horizontal) {
+ this._scrollBar.setScrollLeft(value);
+ } else {
+ this._scrollBar.setScrollTop(value);
+ }
+}
+
+
+// overridden
+qx.Proto._afterAppear = function() {
+ qx.ui.layout.BoxLayout.prototype._afterAppear.call(this);
+
+ //this.debug("Setting to value: " + this.getValue());
+ this._positionKnob(this.getValue());
+}
+
+
+// overridden
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (this._scrollContent) {
+ this._scrollContent.dispose();
+ this._scrollContent = null;
+ }
+
+ return qx.ui.layout.BoxLayout.prototype.dispose.call(this);
+}
+
+
+/**
+ * The delay when to update the scroll bar value after a scroll event if
+ * {@link #mergeEvents} is true (in milliseconds). All scroll events that arrive
+ * in shorter time will be merged.
+ */
+qx.Class.EVENT_DELAY = 250;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/Widget.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/Widget.js
new file mode 100644
index 0000000000..de775ac97b
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/Widget.js
@@ -0,0 +1,5703 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_core)
+#require(qx.renderer.color.ColorCache)
+#require(qx.renderer.border.BorderCache)
+#require(qx.manager.object.AppearanceManager)
+#after(qx.component.init.InterfaceInitComponent)
+#optional(qx.ui.core.Parent)
+#optional(qx.ui.form.Button)
+#optional(qx.client.Timer)
+#optional(qx.client.Command)
+#optional(qx.ui.popup.ToolTip)
+#optional(qx.ui.menu.Menu)
+#optional(qx.ui.basic.Inline)
+
+************************************************************************ */
+
+/**
+ * This is the main widget, all visible objects in the application extend this.
+ *
+ * @event beforeAppear {qx.event.type.Event}
+ * @event appear {qx.event.type.Event}
+ * @event beforeDisappear {qx.event.type.Event}
+ * @event disappear {qx.event.type.Event}
+ * @event beforeInsertDom {qx.event.type.Event}
+ * @event insertDom {qx.event.type.Event}
+ * @event beforeRemoveDom {qx.event.type.Event}
+ * @event removeDom {qx.event.type.Event}
+ * @event create {qx.event.type.Event}
+ * @event execute {qx.event.type.Event}
+ * @event FADE_FINISHED {qx.event.type.DataEvent}
+ * @event mouseover {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event mousemove {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event mouseout {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event mousedown {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event mouseup {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event mousewheel {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event click {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event dblclick {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event contextmenu {qx.event.type.MouseEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event keydown {qx.event.type.KeyEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event keypress {qx.event.type.KeyEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event keyinput {qx.event.type.KeyEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event keyup {qx.event.type.KeyEvent} (Fired by {@link qx.event.handler.EventHandler})
+ * @event focusout {qx.event.type.FocusEvent} (Fired by {@link qx.ui.core.Parent})
+ * @event focusin {qx.event.type.FocusEvent} (Fired by {@link qx.ui.core.Parent})
+ * @event blur {qx.event.type.FocusEvent} (Fired by {@link qx.ui.core.Parent})
+ * @event focus {qx.event.type.FocusEvent} (Fired by {@link qx.ui.core.Parent})
+ */
+qx.OO.defineClass("qx.ui.core.Widget", qx.core.Target,
+function()
+{
+ if (this.classname == qx.ui.core.Widget.ABSTRACT_CLASS) {
+ throw new Error("Please omit the usage of qx.ui.core.Widget directly. Choose between qx.ui.core.Parent and qx.ui.basic.Terminator instead!");
+ }
+
+ qx.core.Target.call(this, true);
+
+
+ // ************************************************************************
+ // HTML MAPPING DATA STRUCTURES
+ // ************************************************************************
+ // Allows the user to setup styles and attributes without a
+ // need to have the target element created already.
+ /*
+ this._htmlProperties = { className : this.classname }
+ this._htmlAttributes = { qxhashcode : this._hashCode }
+ */
+ this._styleProperties = { position : "absolute" }
+
+
+ // ************************************************************************
+ // LAYOUT CHANGES
+ // ************************************************************************
+ this._layoutChanges = {};
+
+
+ // ************************************************************************
+ // APPEARANCE
+ // ************************************************************************
+ this._states = {};
+ this._applyInitialAppearance();
+});
+
+qx.Class.ABSTRACT_CLASS = "qx.ui.core.Widget";
+
+// Will be calculated later (TODO: Move to qx.Dom?)
+qx.Class.SCROLLBAR_SIZE = 16;
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DEFAULT SETTINGS
+---------------------------------------------------------------------------
+*/
+
+qx.Settings.setDefault("enableQueueDebug", false);
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ BASIC PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ The parent widget (the real object, no ID or something)
+*/
+qx.OO.addProperty({ name : "parent", type : "object", instance : "qx.ui.core.Parent", defaultValue : null });
+
+/*!
+ The element node (if the widget is created, otherwise null)
+*/
+qx.OO.addProperty({ name : "element" });
+
+/*!
+ Simple and fast switch of the visibility of a widget.
+*/
+qx.OO.addProperty({ name : "visibility", type : "boolean", defaultValue : true });
+
+/*!
+ If the widget should be displayed. Use this property instead of visibility if the change
+ in visibility should have effects on the parent widget.
+*/
+qx.OO.addProperty({ name : "display", type : "boolean", defaultValue : true });
+
+/*!
+ If you switch this to true, the widget doesn't handle
+ events directly. It will redirect them to the parent
+ widget.
+*/
+qx.OO.addProperty({ name : "anonymous", type : "boolean", defaultValue : false, getAlias : "isAnonymous" });
+
+/*!
+ The tagname of the element which should automatically be created
+*/
+qx.OO.addProperty({ name : "tagName", type : "string", defaultValue : "div" });
+
+/*!
+ This is used by many layout managers to control the individual horizontal alignment of this widget inside this parent.
+
+ This should be used with caution since in some cases
+ this might give unrespected results.
+*/
+qx.OO.addProperty({ name : "horizontalAlign", type : "string" });
+
+/*!
+ This is used by many layout managers to control the individual vertical alignment of this widget inside this parent.
+
+ This should be used with caution since in some cases
+ this might give unrespected results.
+*/
+qx.OO.addProperty({ name : "verticalAlign", type : "string" });
+
+/*!
+ Should this widget be stretched on the x-axis if the layout handler will do this?
+ Used by some layout handlers (qx.ui.layout.BoxLayout, ...).
+*/
+qx.OO.addProperty({ name : "allowStretchX", type : "boolean", defaultValue : true });
+
+/*!
+ Should this widget be stretched on the y-axis if the layout handler will do this?
+ Used by some layout handlers (qx.ui.layout.BoxLayout, ...).
+*/
+qx.OO.addProperty({ name : "allowStretchY", type : "boolean", defaultValue : true });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ STYLE PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Mapping to native style property z-index.
+
+ This should be used with caution since in some cases
+ this might give unrespected results.
+*/
+qx.OO.addProperty({ name : "zIndex", type : "number" });
+
+/*!
+ The backgroundColor style property of the rendered widget.
+ As input are allowed any instance of qx.renderer.color.Color or a string which defines the color itself.
+*/
+qx.OO.addProperty({ name : "backgroundColor", type : "object", instance : "qx.renderer.color.Color", convert : qx.renderer.color.ColorCache, allowMultipleArguments : true });
+
+/*!
+ The color style property of the rendered widget.
+ As input are allowed any instance of qx.renderer.color.Color or a string which defines the color itself.
+*/
+qx.OO.addProperty({ name : "color", type : "object", instance : "qx.renderer.color.Color", convert : qx.renderer.color.ColorCache, allowMultipleArguments : true });
+
+/*!
+ The border property describes how to paint the border on the widget.
+
+ This should be used with caution since in some cases (mostly complex widgets)
+ this might give unrespected results.
+*/
+qx.OO.addProperty({ name : "border", type : "object", instance : "qx.renderer.border.Border", convert : qx.renderer.border.BorderCache, allowMultipleArguments : true });
+
+/*!
+ Mapping to native style property opacity.
+
+ The uniform opacity setting to be applied across an entire object. Behaves like the new CSS-3 Property.
+ Any values outside the range 0.0 (fully transparent) to 1.0 (fully opaque) will be clamped to this range.
+*/
+qx.OO.addProperty({ name : "opacity", type : "number" });
+
+/*!
+ Mapping to native style property cursor.
+
+ The name of the cursor to show when the mouse pointer is over the widget.
+ This is any valid CSS2 cursor name defined by W3C.
+
+ The following values are possible:
+ default
+ crosshair
+ pointer (hand is the ie name and will mapped to pointer in non-ie).
+ move
+ n-resize
+ ne-resize
+ e-resize
+ se-resize
+ s-resize
+ sw-resize
+ w-resize
+ nw-resize
+ text
+ wait
+ help
+ url([file]) = self defined cursor, file should be an ANI- or CUR-type
+
+*/
+qx.OO.addProperty({ name : "cursor", type : "string" });
+
+/*!
+ Mapping to native style property background-image.
+
+ The URI of the image file to use as background image.
+*/
+qx.OO.addProperty({ name : "backgroundImage", type : "string" });
+
+/**
+ * Describes how to handle content that is too large to fit inside the widget.
+ *
+ * Overflow modes:
+ * * hidden: The content is clipped
+ * * auto: Scroll bars are shown as needed
+ * * scroll: Scroll bars are always shown. Even if there is enough room for the content inside the widget.
+ * * scrollX: Scroll bars for the X-Axis are always shown. Even if there is enough room for the content inside the widget.
+ * * scrollY: Scroll bars for the Y-Axis are always shown. Even if there is enough room for the content inside the widget.
+ */
+qx.OO.addProperty({ name : "overflow", type : "string", addToQueue : true });
+
+/*!
+ Clipping of the widget (left)
+*/
+qx.OO.addProperty({ name : "clipLeft", type : "number", impl : "clip" });
+
+/*!
+ Clipping of the widget (top)
+*/
+qx.OO.addProperty({ name : "clipTop", type : "number", impl : "clip" });
+
+/*!
+ Clipping of the widget (width)
+*/
+qx.OO.addProperty({ name : "clipWidth", type : "number", impl : "clip" });
+
+/*!
+ Clipping of the widget (height)
+*/
+qx.OO.addProperty({ name : "clipHeight", type : "number", impl : "clip" });
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MANAGMENT PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Set this to a positive value makes the widget able to get the focus.
+ It even is reachable through the usage of the tab-key.
+
+ Widgets with the same tabIndex are handled through there position
+ in the document.
+*/
+qx.OO.addProperty({ name : "tabIndex", type : "number", defaultValue : -1 });
+
+/*!
+ If the focus outline should be hidden.
+*/
+qx.OO.addProperty({ name : "hideFocus", type : "boolean", defaultValue : false });
+
+/*!
+ Use DOM focussing (focus() and blur() methods of DOM nodes)
+*/
+qx.OO.addProperty({ name : "enableElementFocus", type : "boolean", defaultValue : true });
+
+/*!
+ Handle focus state of this widget.
+
+ someWidget.setFocused(true) set the current focus to this widget.
+ someWidget.setFocused(false) remove the current focus and leave it blank.
+
+ Normally you didn't need to set this directly.
+*/
+qx.OO.addProperty({ name : "focused", type : "boolean", defaultValue : false });
+
+/*!
+ Toggle the possibility to select the element of this widget.
+*/
+qx.OO.addProperty({ name : "selectable", type : "boolean", defaultValue : true, getAlias : "isSelectable" });
+
+/*!
+ Contains the tooltip object connected to the widget.
+*/
+qx.OO.addProperty({ name : "toolTip", type : "object", instance : "qx.ui.popup.ToolTip" });
+
+/*!
+ Contains the context menu object connected to the widget. (Need real implementation)
+*/
+qx.OO.addProperty({ name : "contextMenu", type : "object", instance : "qx.ui.menu.Menu" });
+
+/*!
+ Capture all events and map them to this widget
+*/
+qx.OO.addProperty({ name : "capture", type : "boolean", defaultValue : false });
+
+/*!
+ Contains the support drop types for drag and drop support
+*/
+qx.OO.addProperty({ name : "dropDataTypes" });
+
+/*!
+ A command called if the widget should be excecuted (a placeholder for buttons, ...)
+*/
+qx.OO.addProperty({ name : "command", type : "object", instance : "qx.client.Command" });
+
+/*!
+ Appearance of the widget
+*/
+qx.OO.addProperty({ name : "appearance", type : "string" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MARGIN/PADDING PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Margin of the widget (top)
+*/
+qx.OO.addProperty({ name : "marginTop", type : "number", addToQueue : true, impl : "marginY" });
+
+/*!
+ Margin of the widget (right)
+*/
+qx.OO.addProperty({ name : "marginRight", type : "number", addToQueue : true, impl : "marginX" });
+
+/*!
+ Margin of the widget (bottom)
+*/
+qx.OO.addProperty({ name : "marginBottom", type : "number", addToQueue : true, impl : "marginY" });
+
+/*!
+ Margin of the widget (left)
+*/
+qx.OO.addProperty({ name : "marginLeft", type : "number", addToQueue : true, impl : "marginX" });
+
+
+/*!
+ Padding of the widget (top)
+*/
+qx.OO.addProperty({ name : "paddingTop", type : "number", addToQueue : true, impl : "paddingY" });
+
+/*!
+ Padding of the widget (right)
+*/
+qx.OO.addProperty({ name : "paddingRight", type : "number", addToQueue : true, impl : "paddingX" });
+
+/*!
+ Padding of the widget (bottom)
+*/
+qx.OO.addProperty({ name : "paddingBottom", type : "number", addToQueue : true, impl : "paddingY" });
+
+/*!
+ Padding of the widget (left)
+*/
+qx.OO.addProperty({ name : "paddingLeft", type : "number", addToQueue : true, impl : "paddingX" });
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HORIZONAL DIMENSION PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ The distance from the outer left border to the parent left area edge.
+
+ You could only set two of the three horizonal dimension properties (boxLeft, boxRight, boxWidth)
+ at the same time. This will be omitted during the setup of the new third value. To reset a value
+ you didn't want anymore, set it to null.
+*/
+qx.OO.addProperty({ name : "left", addToQueue : true, unitDetection : "pixelPercent" });
+
+/*!
+ The distance from the outer right border to the parent right area edge.
+
+ You could only set two of the three horizonal dimension properties (boxLeft, boxRight, boxWidth)
+ at the same time. This will be omitted during the setup of the new third value. To reset a value
+ you didn't want anymore, set it to null.
+*/
+qx.OO.addProperty({ name : "right", addToQueue : true, unitDetection : "pixelPercent" });
+
+/*!
+ The width of the box (including padding and border).
+
+ You could only set two of the three horizonal dimension properties (boxLeft, boxRight, boxWidth)
+ at the same time. This will be omitted during the setup of the new third value. To reset a value
+ you didn't want anymore, set it to null.
+*/
+qx.OO.addProperty({ name : "width", addToQueue : true, unitDetection : "pixelPercentAutoFlex" });
+
+/*!
+ The minimum width of the box (including padding and border).
+
+ Set this to omit the shrinking of the box width under this value.
+*/
+qx.OO.addProperty({ name : "minWidth", addToQueue : true, unitDetection : "pixelPercentAuto" });
+
+/*!
+ The maximum width of the box (including padding and border).
+
+ Set this to omit the expanding of the box width above this value.
+*/
+qx.OO.addProperty({ name : "maxWidth", addToQueue : true, unitDetection : "pixelPercentAuto" });
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ VERTICAL DIMENSION PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ The distance from the outer top border to the parent top area edge.
+
+ You could only set two of the three vertical dimension properties (boxTop, boxBottom, boxHeight)
+ at the same time. This will be omitted during the setup of the new third value. To reset a value
+ you didn't want anymore, set it to null.
+*/
+qx.OO.addProperty({ name : "top", addToQueue : true, unitDetection : "pixelPercent" });
+
+/*!
+ The distance from the outer bottom border to the parent bottom area edge.
+
+ You could only set two of the three vertical dimension properties (boxTop, boxBottom, boxHeight)
+ at the same time. This will be omitted during the setup of the new third value. To reset a value
+ you didn't want anymore, set it to null.
+*/
+qx.OO.addProperty({ name : "bottom", addToQueue : true, unitDetection : "pixelPercent" });
+
+/*!
+ The height of the box (including padding and border).
+
+ You could only set two of the three vertical dimension properties (boxTop, boxBottom, boxHeight)
+ at the same time. This will be omitted during the setup of the new third value. To reset a value
+ you didn't want anymore, set it to null.
+*/
+qx.OO.addProperty({ name : "height", addToQueue : true, unitDetection : "pixelPercentAutoFlex" });
+
+/*!
+ The minimum height of the box (including padding and border).
+
+ Set this to omit the shrinking of the box height under this value.
+*/
+qx.OO.addProperty({ name : "minHeight", addToQueue : true, unitDetection : "pixelPercentAuto" });
+
+/*!
+ The maximum height of the box (including padding and border).
+
+ Set this to omit the expanding of the box height above this value.
+*/
+qx.OO.addProperty({ name : "maxHeight", addToQueue : true, unitDetection : "pixelPercentAuto" });
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTY GROUPS
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addPropertyGroup({ name : "location", members : [ "left", "top" ]});
+qx.OO.addPropertyGroup({ name : "dimension", members : [ "width", "height" ]});
+
+qx.OO.addPropertyGroup({ name : "space", members : [ "left", "width", "top", "height" ]});
+qx.OO.addPropertyGroup({ name : "edge", members : [ "top", "right", "bottom", "left" ], mode : "shorthand" });
+
+qx.OO.addPropertyGroup({ name : "padding", members : [ "paddingTop", "paddingRight", "paddingBottom", "paddingLeft" ], mode: "shorthand" });
+qx.OO.addPropertyGroup({ name : "margin", members : [ "marginTop", "marginRight", "marginBottom", "marginLeft" ], mode: "shorthand" });
+
+qx.OO.addPropertyGroup({ name : "heights", members : [ "minHeight", "height", "maxHeight" ]});
+qx.OO.addPropertyGroup({ name : "widths", members : [ "minWidth", "width", "maxWidth" ]});
+
+qx.OO.addPropertyGroup({ name : "align", members : [ "horizontalAlign", "verticalAlign" ]});
+qx.OO.addPropertyGroup({ name : "stretch", members : [ "stretchX", "stretchY" ]});
+
+qx.OO.addPropertyGroup({ name : "clipLocation", members : [ "clipLeft", "clipTop" ]});
+qx.OO.addPropertyGroup({ name : "clipDimension", members : [ "clipWidth", "clipHeight" ]});
+qx.OO.addPropertyGroup({ name : "clip", members : [ "clipLeft", "clipTop", "clipWidth", "clipHeight" ]});
+
+
+
+
+
+
+
+
+/* ************************************************************************
+ Class data, properties and methods
+************************************************************************ */
+
+/*
+---------------------------------------------------------------------------
+ ALL QUEUES
+---------------------------------------------------------------------------
+*/
+
+if (qx.Settings.getValueOfClass("qx.ui.core.Widget", "enableQueueDebug"))
+{
+ qx.ui.core.Widget.flushGlobalQueues = function()
+ {
+ if (qx.ui.core.Widget._inFlushGlobalQueues || !qx.core.Init.getInstance().getComponent().isUiReady()) {
+ return;
+ }
+
+ if (!(qx.ui.core.Widget._globalWidgetQueue.length > 0 || qx.ui.core.Widget._globalElementQueue.length > 0 ||
+ qx.ui.core.Widget._globalStateQueue.length > 0 || qx.ui.core.Widget._globalJobQueue.length > 0 ||
+ qx.ui.core.Widget._globalLayoutQueue.length > 0 || qx.ui.core.Widget._fastGlobalDisplayQueue.length > 0 ||
+ !qx.lang.Object.isEmpty(qx.ui.core.Widget._lazyGlobalDisplayQueue))) {
+ return;
+ }
+
+ var globalWidgetQueueLength = qx.ui.core.Widget._globalWidgetQueue.length;
+ var globalElementQueueLength = qx.ui.core.Widget._globalElementQueue.length;
+ var globalStateQueueLength = qx.ui.core.Widget._globalStateQueue.length;
+ var globalJobQueueLength = qx.ui.core.Widget._globalJobQueue.length;
+ var globalLayoutQueueLength = qx.ui.core.Widget._globalLayoutQueue.length;
+ var fastGlobalDisplayQueueLength = qx.ui.core.Widget._fastGlobalDisplayQueue.length;
+ var lazyGlobalDisplayQueueLength = qx.ui.core.Widget._lazyGlobalDisplayQueue ? qx.ui.core.Widget._lazyGlobalDisplayQueue.length : 0;
+
+ // Also used for inline event handling to seperate 'real' events
+ qx.ui.core.Widget._inFlushGlobalQueues = true;
+
+ var vStart;
+
+ vStart = (new Date).valueOf();
+ qx.ui.core.Widget.flushGlobalWidgetQueue();
+ var vWidgetDuration = (new Date).valueOf() - vStart;
+
+ vStart = (new Date).valueOf();
+ qx.ui.core.Widget.flushGlobalStateQueue();
+ var vStateDuration = (new Date).valueOf() - vStart;
+
+ vStart = (new Date).valueOf();
+ qx.ui.core.Widget.flushGlobalElementQueue();
+ var vElementDuration = (new Date).valueOf() - vStart;
+
+ vStart = (new Date).valueOf();
+ qx.ui.core.Widget.flushGlobalJobQueue();
+ var vJobDuration = (new Date).valueOf() - vStart;
+
+ vStart = (new Date).valueOf();
+ qx.ui.core.Widget.flushGlobalLayoutQueue();
+ var vLayoutDuration = (new Date).valueOf() - vStart;
+
+ vStart = (new Date).valueOf();
+ qx.ui.core.Widget.flushGlobalDisplayQueue();
+ var vDisplayDuration = (new Date).valueOf() - vStart;
+
+ var vSum = vWidgetDuration + vStateDuration + vElementDuration + vJobDuration + vLayoutDuration + vDisplayDuration;
+
+ if (vSum > 0)
+ {
+ var logger = qx.dev.log.Logger.getClassLogger(qx.ui.core.Widget);
+ logger.debug("Flush Global Queues");
+ logger.debug("Widgets: " + vWidgetDuration + "ms (" + globalWidgetQueueLength + ")");
+ logger.debug("State: " + vStateDuration + "ms (" + globalStateQueueLength + ")");
+ logger.debug("Element: " + vElementDuration + "ms (" + globalElementQueueLength + ")");
+ logger.debug("Job: " + vJobDuration + "ms (" + globalJobQueueLength + ")");
+ logger.debug("Layout: " + vLayoutDuration + "ms (" + globalLayoutQueueLength + ")");
+ logger.debug("Display: " + vDisplayDuration + "ms (fast:" + fastGlobalDisplayQueueLength + ",lazy:" + lazyGlobalDisplayQueueLength + ")");
+
+ window.status = "Flush: Widget:" + vWidgetDuration + " State:" + vStateDuration + " Element:" + vElementDuration + " Job:" + vJobDuration + " Layout:" + vLayoutDuration + " Display:" + vDisplayDuration;
+ }
+
+ delete qx.ui.core.Widget._inFlushGlobalQueues;
+ }
+}
+else
+{
+ qx.ui.core.Widget.flushGlobalQueues = function()
+ {
+ if (qx.ui.core.Widget._inFlushGlobalQueues || !qx.core.Init.getInstance().getComponent().isUiReady()) {
+ return;
+ }
+
+ // Also used for inline event handling to seperate 'real' events
+ qx.ui.core.Widget._inFlushGlobalQueues = true;
+
+ qx.ui.core.Widget.flushGlobalWidgetQueue();
+ qx.ui.core.Widget.flushGlobalStateQueue();
+ qx.ui.core.Widget.flushGlobalElementQueue();
+ qx.ui.core.Widget.flushGlobalJobQueue();
+ qx.ui.core.Widget.flushGlobalLayoutQueue();
+ qx.ui.core.Widget.flushGlobalDisplayQueue();
+
+ delete qx.ui.core.Widget._inFlushGlobalQueues;
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ WIDGET QUEUE
+
+ Allows widgets to register to the widget queue to do multiple things
+ before the other queues will be flushed
+---------------------------------------------------------------------------
+*/
+
+qx.ui.core.Widget._globalWidgetQueue = [];
+
+qx.ui.core.Widget.addToGlobalWidgetQueue = function(vWidget)
+{
+ if (!vWidget._isInGlobalWidgetQueue && vWidget._isDisplayable)
+ {
+ qx.ui.core.Widget._globalWidgetQueue.push(vWidget);
+ vWidget._isInGlobalWidgetQueue = true;
+ }
+}
+
+qx.ui.core.Widget.removeFromGlobalWidgetQueue = function(vWidget)
+{
+ if (vWidget._isInGlobalWidgetQueue)
+ {
+ qx.lang.Array.remove(qx.ui.core.Widget._globalWidgetQueue, vWidget);
+ delete vWidget._isInGlobalWidgetQueue;
+ }
+}
+
+qx.ui.core.Widget.flushGlobalWidgetQueue = function()
+{
+ var vQueue=qx.ui.core.Widget._globalWidgetQueue, vLength, vWidget;
+
+ while ((vLength=vQueue.length) > 0)
+ {
+ for (var i=0; i 0)
+ {
+ for (var i=0; i 0)
+ {
+ for (var i=0; i 0)
+ {
+ for (var i=0; i 0)
+ {
+ for (var i=0; i= 3)
+ {
+ // creating new document fragment
+ vFragment = document.createDocumentFragment();
+
+ // appending all widget elements to fragment
+ for (var i=0, l=vLazyQueue.length; i 0 && el.offsetHeight > 0);
+}
+
+/*!
+ A single setup to the current preferred pixel values of the widget
+*/
+qx.Proto.pack = function()
+{
+ this.setWidth(this.getPreferredBoxWidth());
+ this.setHeight(this.getPreferredBoxHeight());
+}
+
+/*!
+ A bounded setup to the preferred width/height of the widget. Keeps in
+ sync if the content or requirements of the widget changes
+*/
+qx.Proto.auto = function()
+{
+ this.setWidth("auto");
+ this.setHeight("auto");
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN HANDLING: ALL
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Get an array of the current children
+*/
+qx.Proto.getChildren = qx.util.Return.returnNull;
+
+/*!
+ Get the number of children
+*/
+qx.Proto.getChildrenLength = qx.util.Return.returnZero;
+
+/*!
+ Get if the widget has any children
+*/
+qx.Proto.hasChildren = qx.util.Return.returnFalse;
+
+/*!
+ Get if the widget has no children
+*/
+qx.Proto.isEmpty = qx.util.Return.returnTrue;
+
+/*!
+ Return the position of the child inside
+*/
+qx.Proto.indexOf = qx.util.Return.returnNegativeIndex;
+
+/*!
+ Test if this widget contains the given widget
+*/
+qx.Proto.contains = qx.util.Return.returnFalse;
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN HANDLING: VISIBLE ONES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Get an array of the current visible children
+*/
+qx.Proto.getVisibleChildren = qx.util.Return.returnNull;
+
+/*!
+ Get the number of children
+*/
+qx.Proto.getVisibleChildrenLength = qx.util.Return.returnZero;
+
+/*!
+ If this widget has visible children
+*/
+qx.Proto.hasVisibleChildren = qx.util.Return.returnFalse;
+
+/*!
+ Check if there are any visible children inside
+*/
+qx.Proto.isVisibleEmpty = qx.util.Return.returnTrue;
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CORE MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._hasParent = false;
+qx.Proto._isDisplayable = false;
+
+qx.Proto.isDisplayable = function() {
+ return this._isDisplayable;
+}
+
+qx.Proto._checkParent = function(propValue, propOldValue, propData)
+{
+ if (this.contains(propValue)) {
+ throw new Error("Could not insert myself into a child " + propValue + "!");
+ }
+
+ return propValue;
+}
+
+qx.Proto._modifyParent = function(propValue, propOldValue, propData)
+{
+ if (propOldValue)
+ {
+ var vOldIndex = propOldValue.getChildren().indexOf(this);
+
+ // Reset cached dimension and location values
+ this._computedWidthValue = this._computedMinWidthValue = this._computedMaxWidthValue = this._computedLeftValue = this._computedRightValue = null;
+ this._computedHeightValue = this._computedMinHeightValue = this._computedMaxHeightValue = this._computedTopValue = this._computedBottomValue = null;
+
+ this._cachedBoxWidth = this._cachedInnerWidth = this._cachedOuterWidth = null;
+ this._cachedBoxHeight = this._cachedInnerHeight = this._cachedOuterHeight = null;
+
+ // Finally remove from children array
+ qx.lang.Array.removeAt(propOldValue.getChildren(), vOldIndex);
+
+ // Invalidate visible children cache
+ propOldValue._invalidateVisibleChildren();
+
+ // Remove child from old parent's children queue
+ propOldValue._removeChildFromChildrenQueue(this);
+
+ // The layouter adds some layout jobs
+ propOldValue.getLayoutImpl().updateChildrenOnRemoveChild(this, vOldIndex);
+
+ // Inform job queue
+ propOldValue.addToJobQueue("removeChild");
+
+ // Invalidate inner preferred dimensions
+ propOldValue._invalidatePreferredInnerDimensions();
+
+ // Store old parent (needed later by _handleDisplayable)
+ this._oldParent = propOldValue;
+ }
+
+ if (propValue)
+ {
+ this._hasParent = true;
+
+ if (qx.util.Validation.isValidNumber(this._insertIndex))
+ {
+ qx.lang.Array.insertAt(propValue.getChildren(), this, this._insertIndex);
+ delete this._insertIndex;
+ }
+ else
+ {
+ propValue.getChildren().push(this);
+ }
+ }
+ else
+ {
+ this._hasParent = false;
+ }
+
+ return this._handleDisplayable("parent");
+}
+
+qx.Proto._modifyDisplay = function(propValue, propOldValue, propData) {
+ return this._handleDisplayable("display");
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPLAYBLE HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._handleDisplayable = function(vHint)
+{
+ // Detect changes. Return if there is no change.
+ // Also handle the case if the displayable keeps true and the parent
+ // was changed then we must not return here.
+ var vDisplayable = this._computeDisplayable();
+ if (this._isDisplayable == vDisplayable && !(vDisplayable && vHint == "parent")) {
+ return true;
+ }
+
+ this._isDisplayable = vDisplayable;
+
+ var vParent = this.getParent();
+
+ // Invalidate visible children
+ if (vParent)
+ {
+ vParent._invalidateVisibleChildren();
+ vParent._invalidatePreferredInnerDimensions();
+ }
+
+ // Remove old parent's elements from DOM and delete old parent
+ if (vHint && this._oldParent && this._oldParent._initialLayoutDone)
+ {
+ var vElement = this.getElement();
+ if(vElement)
+ {
+ if (this.getVisibility()) {
+ this._beforeDisappear();
+ }
+
+ this._beforeRemoveDom();
+
+ this._oldParent._getTargetNode().removeChild(vElement);
+
+ this._afterRemoveDom();
+
+ if (this.getVisibility()) {
+ this._afterDisappear();
+ }
+ }
+
+ delete this._oldParent;
+ }
+
+ // Handle 'show'
+ if (vDisplayable)
+ {
+ /* --------------------------------
+ Update current parent
+ -------------------------------- */
+
+ // The layouter added some layout jobs
+ if (vParent._initialLayoutDone)
+ {
+ vParent.getLayoutImpl().updateChildrenOnAddChild(this, vParent.getChildren().indexOf(this));
+
+ // Inform parents job queue
+ vParent.addToJobQueue("addChild");
+ }
+
+ // Add to parents children queue
+ // (indirectly with a new layout request)
+ this.addToLayoutChanges("initial");
+
+ // Add to custom queues
+ this.addToCustomQueues(vHint);
+
+ // Handle beforeAppear signals
+ if (this.getVisibility()) {
+ this._beforeAppear();
+ }
+
+
+
+ /* --------------------------------
+ Add to global Queues
+ -------------------------------- */
+
+ // Add element (and create if not ready)
+ if (!this._isCreated) {
+ qx.ui.core.Widget.addToGlobalElementQueue(this);
+ }
+
+ // Add to global queues
+ qx.ui.core.Widget.addToGlobalStateQueue(this);
+
+ if (!qx.lang.Object.isEmpty(this._jobQueue)) {
+ qx.ui.core.Widget.addToGlobalJobQueue(this);
+ }
+
+ if (!qx.lang.Object.isEmpty(this._childrenQueue)) {
+ qx.ui.core.Widget.addToGlobalLayoutQueue(this);
+ }
+ }
+
+ // Handle 'hide'
+ else
+ {
+ // Removing from global queues
+ qx.ui.core.Widget.removeFromGlobalElementQueue(this);
+ qx.ui.core.Widget.removeFromGlobalStateQueue(this);
+ qx.ui.core.Widget.removeFromGlobalJobQueue(this);
+ qx.ui.core.Widget.removeFromGlobalLayoutQueue(this);
+
+ // Add to top-level tree queue
+ this.removeFromCustomQueues(vHint);
+
+ // only remove when itself want to be removed
+ // through a property change - not a parent signal
+ if (vParent && vHint)
+ {
+ if (this.getVisibility()) {
+ this._beforeDisappear();
+ }
+
+ // The layouter added some layout jobs
+ if (vParent._initialLayoutDone && this._initialLayoutDone)
+ {
+ vParent.getLayoutImpl().updateChildrenOnRemoveChild(this, vParent.getChildren().indexOf(this));
+
+ // Inform parent's job queue
+ vParent.addToJobQueue("removeChild");
+
+ // Before Remove DOM Event
+ this._beforeRemoveDom();
+
+ // DOM action
+ vParent._getTargetNode().removeChild(this.getElement());
+
+ // After Remove DOM Event
+ this._afterRemoveDom();
+ }
+
+ // Remove from parents children queue
+ vParent._removeChildFromChildrenQueue(this);
+
+ if (this.getVisibility()) {
+ this._afterDisappear();
+ }
+ }
+ }
+
+ this._handleDisplayableCustom(vDisplayable, vParent, vHint);
+
+ return true;
+}
+
+qx.Proto.addToCustomQueues = qx.util.Return.returnTrue;
+qx.Proto.removeFromCustomQueues = qx.util.Return.returnTrue;
+
+qx.Proto._handleDisplayableCustom = qx.util.Return.returnTrue;
+
+qx.Proto._computeDisplayable = function() {
+ return this.getDisplay() && this._hasParent && this.getParent()._isDisplayable ? true : false;
+}
+
+qx.Proto._beforeAppear = function()
+{
+ // this.debug("_beforeAppear");
+ this.createDispatchEvent("beforeAppear");
+}
+
+qx.Proto._afterAppear = function()
+{
+ // this.debug("_afterAppear");
+ this._isSeeable = true;
+ this.createDispatchEvent("appear");
+}
+
+qx.Proto._beforeDisappear = function()
+{
+ // this.debug("_beforeDisappear");
+
+ // Remove any hover/pressed styles
+ this.removeState("over");
+
+ if (qx.OO.isAvailable("qx.ui.form.Button"))
+ {
+ this.removeState("pressed");
+ this.removeState("abandoned");
+ }
+
+ // this.debug("_beforeDisappear");
+ this.createDispatchEvent("beforeDisappear");
+}
+
+qx.Proto._afterDisappear = function()
+{
+ // this.debug("_afterDisappear");
+ this._isSeeable = false;
+ this.createDispatchEvent("disappear");
+}
+
+qx.Proto._isSeeable = false;
+
+/**
+ * If the widget is currently seeable which means that it:
+ *
+ * * has a also seeable parent
+ * * visibility is true
+ * * display is true
+ */
+qx.Proto.isSeeable = function() {
+ return this._isSeeable;
+}
+
+qx.Proto.isAppearRelevant = function() {
+ return this.getVisibility() && this._isDisplayable;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DOM SIGNAL HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._beforeInsertDom = function()
+{
+ // this.debug("_beforeInsertDom");
+ this.createDispatchEvent("beforeInsertDom");
+}
+
+qx.Proto._afterInsertDom = function()
+{
+ // this.debug("_afterInsertDom");
+ this.createDispatchEvent("insertDom");
+}
+
+qx.Proto._beforeRemoveDom = function()
+{
+ // this.debug("_beforeRemoveDom");
+ this.createDispatchEvent("beforeRemoveDom");
+}
+
+qx.Proto._afterRemoveDom = function()
+{
+ // this.debug("_afterRemoveDom");
+ this.createDispatchEvent("removeDom");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ VISIBILITY HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyVisibility = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ if (this._isDisplayable) {
+ this._beforeAppear();
+ }
+
+ this.removeStyleProperty("display");
+
+ if (this._isDisplayable) {
+ this._afterAppear();
+ }
+ }
+ else
+ {
+ if (this._isDisplayable) {
+ this._beforeDisappear();
+ }
+
+ this.setStyleProperty("display", "none");
+
+ if (this._isDisplayable) {
+ this._afterDisappear();
+ }
+ }
+
+ return true;
+}
+
+qx.Proto.show = function()
+{
+ this.setVisibility(true);
+ this.setDisplay(true);
+}
+
+qx.Proto.hide = function() {
+ this.setVisibility(false);
+}
+
+qx.Proto.connect = function() {
+ this.setDisplay(true);
+}
+
+qx.Proto.disconnect = function() {
+ this.setDisplay(false);
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ENHANCED BORDER SUPPORT
+---------------------------------------------------------------------------
+*/
+
+if (qx.sys.Client.getInstance().isGecko())
+{
+ qx.Proto._createElementForEnhancedBorder = qx.util.Return.returnTrue;
+}
+else
+{
+ qx.Proto._createElementForEnhancedBorder = function()
+ {
+ // Enhanced Border Test (for IE and Opera)
+ if (qx.renderer.border.Border.enhancedCrossBrowserMode &&
+ this.getTagName() == "div" &&
+ !this._borderElement)
+ {
+ var el = this.getElement();
+ var cl = this._borderElement = document.createElement("div");
+
+ var es = el.style;
+ var cs = this._borderStyle = cl.style;
+
+ cs.width = cs.height = "100%";
+ cs.position = "absolute";
+
+ for (var i in this._styleProperties)
+ {
+ switch(i)
+ {
+ case "position":
+ case "zIndex":
+ case "filter":
+ case "display":
+ break;
+
+ default:
+ cs[i] = this._styleProperties[i];
+ es[i] = "";
+ }
+ }
+
+ // Move existing children
+ while(el.firstChild) {
+ cl.appendChild(el.firstChild);
+ }
+
+ el.appendChild(cl);
+ }
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DOM ELEMENT HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._isCreated = false;
+
+if (qx.sys.Client.getInstance().isGecko())
+{
+ qx.Proto._getTargetNode = function() {
+ return this._element;
+ }
+}
+else
+{
+ qx.Proto._getTargetNode = function() {
+ return this._borderElement || this._element;
+ }
+}
+
+qx.Proto.addToDocument = function() {
+ qx.ui.core.ClientDocument.getInstance().add(this);
+}
+
+/*!
+ Check if the widget is created (or the element is already available).
+*/
+qx.Proto.isCreated = function() {
+ return this._isCreated;
+}
+
+/*!
+ Create widget with empty element (of specified tagname).
+*/
+qx.Proto._createElementImpl = function() {
+ this.setElement(this.getTopLevelWidget().getDocumentElement().createElement(this.getTagName()));
+}
+
+qx.Proto._modifyElement = function(propValue, propOldValue, propData)
+{
+ this._isCreated = qx.util.Validation.isValidElement(propValue);
+
+ if (propOldValue)
+ {
+ // reset reference to widget instance
+ propOldValue.qx_Widget = null;
+
+ // remove events
+ this._removeInlineEvents(propOldValue);
+ }
+
+ if (propValue)
+ {
+ // add reference to widget instance
+ propValue.qx_Widget = this;
+
+ // link element and style reference
+ this._element = propValue;
+ this._style = propValue.style;
+
+ this._applyStyleProperties(propValue);
+ this._applyHtmlProperties(propValue);
+ this._applyHtmlAttributes(propValue);
+ this._applyElementData(propValue);
+
+ // attach inline events
+ this._addInlineEvents(propValue);
+
+ // send out create event
+ this.createDispatchEvent("create");
+ }
+ else
+ {
+ this._element = this._style = null;
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ JOBS QUEUE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.addToJobQueue = function(p)
+{
+ if (this._hasParent) {
+ qx.ui.core.Widget.addToGlobalJobQueue(this);
+ }
+
+ if (!this._jobQueue) {
+ this._jobQueue = {};
+ }
+
+ this._jobQueue[p] = true;
+ return true;
+}
+
+qx.Proto._flushJobQueue = function(q)
+{
+ /* --------------------------------------------------------------------------------
+ 1. Pre checks
+ -------------------------------------------------------------------------------- */
+
+ try
+ {
+ var vQueue = this._jobQueue;
+ var vParent = this.getParent();
+
+ if (!vParent || qx.lang.Object.isEmpty(vQueue)) {
+ return;
+ }
+
+ var vLayoutImpl = this instanceof qx.ui.core.Parent ? this.getLayoutImpl() : null;
+
+ if (vLayoutImpl) {
+ vLayoutImpl.updateSelfOnJobQueueFlush(vQueue);
+ }
+ }
+ catch(ex)
+ {
+ this.error("Flushing job queue (prechecks#1) failed", ex);
+ }
+
+
+
+
+
+ /* --------------------------------------------------------------------------------
+ 2. Recompute dimensions
+ -------------------------------------------------------------------------------- */
+
+ try
+ {
+ var vFlushParentJobQueue = false;
+ var vRecomputeOuterWidth = vQueue.marginLeft || vQueue.marginRight;
+ var vRecomputeOuterHeight = vQueue.marginTop || vQueue.marginBottom;
+ var vRecomputeInnerWidth = vQueue.frameWidth;
+ var vRecomputeInnerHeight = vQueue.frameHeight;
+ var vRecomputeParentPreferredInnerWidth = (vQueue.frameWidth || vQueue.preferredInnerWidth) && this._recomputePreferredBoxWidth();
+ var vRecomputeParentPreferredInnerHeight = (vQueue.frameHeight || vQueue.preferredInnerHeight) && this._recomputePreferredBoxHeight();
+
+ if (vRecomputeParentPreferredInnerWidth)
+ {
+ var vPref = this.getPreferredBoxWidth();
+
+ if (this._computedWidthTypeAuto)
+ {
+ this._computedWidthValue = vPref;
+ vQueue.width = true;
+ }
+
+ if (this._computedMinWidthTypeAuto)
+ {
+ this._computedMinWidthValue = vPref;
+ vQueue.minWidth = true;
+ }
+
+ if (this._computedMaxWidthTypeAuto)
+ {
+ this._computedMaxWidthValue = vPref;
+ vQueue.maxWidth = true;
+ }
+ }
+
+ if (vRecomputeParentPreferredInnerHeight)
+ {
+ var vPref = this.getPreferredBoxHeight();
+
+ if (this._computedHeightTypeAuto)
+ {
+ this._computedHeightValue = vPref;
+ vQueue.height = true;
+ }
+
+ if (this._computedMinHeightTypeAuto)
+ {
+ this._computedMinHeightValue = vPref;
+ vQueue.minHeight = true;
+ }
+
+ if (this._computedMaxHeightTypeAuto)
+ {
+ this._computedMaxHeightValue = vPref;
+ vQueue.maxHeight = true;
+ }
+ }
+
+ if ((vQueue.width || vQueue.minWidth || vQueue.maxWidth || vQueue.left || vQueue.right) && this._recomputeBoxWidth()) {
+ vRecomputeOuterWidth = vRecomputeInnerWidth = true;
+ }
+
+ if ((vQueue.height || vQueue.minHeight || vQueue.maxHeight || vQueue.top || vQueue.bottom) && this._recomputeBoxHeight()) {
+ vRecomputeOuterHeight = vRecomputeInnerHeight = true;
+ }
+ }
+ catch(ex)
+ {
+ this.error("Flushing job queue (recompute#2) failed", ex);
+ }
+
+
+
+
+
+ /* --------------------------------------------------------------------------------
+ 3. Signals to parent widgets
+ -------------------------------------------------------------------------------- */
+
+ try
+ {
+ if ((vRecomputeOuterWidth && this._recomputeOuterWidth()) ||
+ vRecomputeParentPreferredInnerWidth)
+ {
+ vParent._invalidatePreferredInnerWidth();
+ vParent.getLayoutImpl().updateSelfOnChildOuterWidthChange(this);
+
+ vFlushParentJobQueue = true;
+ }
+
+ if ((vRecomputeOuterHeight && this._recomputeOuterHeight()) ||
+ vRecomputeParentPreferredInnerHeight)
+ {
+ vParent._invalidatePreferredInnerHeight();
+ vParent.getLayoutImpl().updateSelfOnChildOuterHeightChange(this);
+
+ vFlushParentJobQueue = true;
+ }
+
+ if (vFlushParentJobQueue) {
+ vParent._flushJobQueue();
+ }
+ }
+ catch(ex)
+ {
+ this.error("Flushing job queue (parentsignals#3) failed", ex);
+ }
+
+
+
+
+
+ /* --------------------------------------------------------------------------------
+ 4. Add layout jobs
+ -------------------------------------------------------------------------------- */
+
+ try
+ {
+ // add to layout queue
+ vParent._addChildToChildrenQueue(this);
+
+ // convert jobs to layout jobs
+ for (var i in vQueue) {
+ this._layoutChanges[i] = true;
+ }
+ }
+ catch(ex)
+ {
+ this.error("Flushing job queue (addjobs#4) failed", ex);
+ }
+
+
+
+
+
+ /* --------------------------------------------------------------------------------
+ 5. Signals to children
+ -------------------------------------------------------------------------------- */
+
+ try
+ {
+ // inform children about padding change
+ if (this instanceof qx.ui.core.Parent &&
+ (vQueue.paddingLeft ||
+ vQueue.paddingRight ||
+ vQueue.paddingTop ||
+ vQueue.paddingBottom))
+ {
+ var ch=this.getChildren(), chl=ch.length;
+
+ if (vQueue.paddingLeft) {
+ for (var i=0; i= 0;
+}
+
+qx.Proto.isFocusRoot = function() {
+ return false;
+}
+
+qx.Proto.getFocusRoot = function()
+{
+ if(this._hasParent) {
+ return this.getParent().getFocusRoot();
+ }
+
+ return null;
+}
+
+qx.Proto.getActiveChild = function()
+{
+ var vRoot = this.getFocusRoot();
+ if (vRoot) {
+ return vRoot.getActiveChild();
+ }
+
+ return null;
+}
+
+qx.Proto._ontabfocus = qx.util.Return.returnTrue;
+
+qx.Proto._modifyFocused = function(propValue, propOldValue, propData)
+{
+ if (!this.isCreated()) {
+ return true;
+ }
+
+ var vFocusRoot = this.getFocusRoot();
+
+ // this.debug("Focused: " + propValue);
+
+ if (vFocusRoot)
+ {
+ // may be undefined if this widget has been removed
+ if (propValue)
+ {
+ vFocusRoot.setFocusedChild(this);
+ this._visualizeFocus();
+ }
+ else
+ {
+ if (vFocusRoot.getFocusedChild() == this) {
+ vFocusRoot.setFocusedChild(null);
+ }
+
+ this._visualizeBlur();
+ }
+ }
+
+ return true;
+}
+
+qx.Proto._visualizeBlur = function()
+{
+ // Force blur, even if mouseFocus is not active because we
+ // need to be sure that the previous focus rect gets removed.
+ // But this only needs to be done, if there is no new focused element.
+ if (this.getEnableElementFocus() && (!this.getFocusRoot().getFocusedChild() || (this.getFocusRoot().getFocusedChild() && this.getFocusRoot().getFocusedChild().getEnableElementFocus())))
+ {
+ try {
+ this.getElement().blur();
+ } catch(ex) {};
+ }
+
+ this.removeState("focused");
+ return true;
+}
+
+qx.Proto._visualizeFocus = function()
+{
+ //this.info("_visualizeFocus: " + qx.event.handler.FocusHandler.mouseFocus);
+ if (!qx.event.handler.FocusHandler.mouseFocus && this.getEnableElementFocus())
+ {
+ try {
+ this.getElement().focus();
+ } catch(ex) {};
+ }
+
+ this.addState("focused");
+ return true;
+}
+
+qx.Proto.focus = function()
+{
+ delete qx.event.handler.FocusHandler.mouseFocus;
+ this.setFocused(true);
+}
+
+qx.Proto.blur = function()
+{
+ delete qx.event.handler.FocusHandler.mouseFocus;
+ this.setFocused(false);
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CAPTURE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyCapture = function(propValue, propOldValue, propData)
+{
+ var vMgr = qx.event.handler.EventHandler.getInstance();
+
+ if (propOldValue)
+ {
+ vMgr.setCaptureWidget(null);
+ }
+ else if (propValue)
+ {
+ vMgr.setCaptureWidget(this);
+ }
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ZINDEX
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyZIndex = function(propValue, propOldValue, propData) {
+ return this.setStyleProperty(propData.name, propValue);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ TAB INDEX
+---------------------------------------------------------------------------
+*/
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._modifyTabIndex = function(propValue, propOldValue, propData)
+ {
+ if (propValue < 0 || !this.getEnabled()) {
+ this.setHtmlProperty("unselectable",
+ "on");
+ } else {
+ this.removeHtmlProperty("unselectable");
+ }
+
+ this.setHtmlProperty("tabIndex",
+ propValue < 0 ? -1 : 1);
+
+ return true;
+ }
+}
+else if (qx.sys.Client.getInstance().isGecko())
+{
+ qx.Proto._modifyTabIndex = function(propValue, propOldValue, propData)
+ {
+ this.setStyleProperty("MozUserFocus",
+ (propValue < 0
+ ? "ignore"
+ : "normal"));
+
+ // be forward compatible (CSS 3 Draft)
+ this.setStyleProperty("userFocus",
+ (propValue < 0
+ ? "ignore"
+ : "normal"));
+
+ return true;
+ }
+}
+else
+{
+ qx.Proto._modifyTabIndex = function(propValue, propOldValue, propData)
+ {
+ // CSS 3 Draft
+ this.setStyleProperty("userFocus",
+ (propValue < 0
+ ? "ignore"
+ : "normal"));
+
+ // IE Backward Compatible
+ if (propValue < 0 || !this.getEnabled()) {
+ this.setHtmlProperty("unselectable",
+ "on");
+ } else {
+ this.removeHtmlProperty("unselectable");
+ }
+
+ this.setHtmlProperty("tabIndex",
+ propValue < 0 ? -1 : 1);
+
+ return true;
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CSS CLASS NAME
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.setCssClassName = function(propValue) {
+ this.setHtmlProperty("className", propValue);
+}
+
+qx.Proto.getCssClassName = function() {
+ return this.getHtmlProperty("className");
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ WIDGET FROM POINT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getWidgetFromPoint = function(x, y)
+{
+ var ret = this.getWidgetFromPointHelper(x, y);
+ return ret && ret != this ? ret : null;
+}
+
+qx.Proto.getWidgetFromPointHelper = function(x, y) {
+ return this;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CAN SELECT
+---------------------------------------------------------------------------
+*/
+
+if(qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._modifySelectable = function(propValue, propOldValue, propData)
+ {
+ if (propValue)
+ {
+ return this.removeHtmlProperty("unselectable");
+ }
+ else
+ {
+ return this.setHtmlProperty("unselectable", "on");
+ }
+ }
+}
+else if(qx.sys.Client.getInstance().isGecko())
+{
+ qx.Proto._modifySelectable = function(propValue, propOldValue, propData)
+ {
+ if (propValue)
+ {
+ this.removeStyleProperty("MozUserSelect");
+ }
+ else
+ {
+ this.setStyleProperty("MozUserSelect", "none");
+ }
+
+ return true;
+ };
+}
+else if (qx.sys.Client.getInstance().isOpera())
+{
+ // No known method available for this client
+ qx.Proto._modifySelectable = function(propValue, propOldValue, propData) {
+ return true;
+ }
+}
+else if (qx.sys.Client.getInstance().isKhtml() || qx.sys.Client.getInstance().isWebkit())
+{
+ qx.Proto._modifySelectable = function(propValue, propOldValue, propData)
+ {
+ // Be forward compatible and use both userSelect and KhtmlUserSelect
+ if (propValue)
+ {
+ this.removeStyleProperty("KhtmlUserSelect");
+ }
+ else
+ {
+ this.setStyleProperty("KhtmlUserSelect", "none");
+ }
+
+ return true;
+ };
+}
+else
+{
+ qx.Proto._modifySelectable = function(propValue, propOldValue, propData)
+ {
+ if (propValue)
+ {
+ return this.removeStyleProperty("userSelect");
+ }
+ else
+ {
+ this.setStyleProperty("userSelect", "none");
+ }
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ OPACITY
+---------------------------------------------------------------------------
+*/
+
+/*!
+Sets the opacity for the widget. Any child widget inside the widget will also
+become (semi-)transparent. The value should be a number between 0 and 1
+inclusive, where 1 means totally opaque and 0 invisible.
+*/
+if(qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._modifyOpacity = function(propValue, propOldValue, propData)
+ {
+ if(propValue == null || propValue >= 1 || propValue < 0)
+ {
+ this.removeStyleProperty("filter");
+ }
+ else if (qx.util.Validation.isValidNumber(propValue))
+ {
+ this.setStyleProperty("filter",
+ ("Alpha(Opacity=" +
+ Math.round(propValue * 100) +
+ ")"));
+ }
+ else
+ {
+ throw new Error("Unsupported opacity value: " + propValue);
+ }
+
+ return true;
+ }
+}
+else
+{
+ qx.Proto._modifyOpacity = function(propValue, propOldValue, propData)
+ {
+ if(propValue == null || propValue > 1)
+ {
+ if (qx.sys.Client.getInstance().isGecko())
+ {
+ this.removeStyleProperty("MozOpacity");
+ }
+ else if (qx.sys.Client.getInstance().isKhtml())
+ {
+ this.removeStyleProperty("KhtmlOpacity");
+ }
+
+ this.removeStyleProperty("opacity");
+ }
+ else if (qx.util.Validation.isValidNumber(propValue))
+ {
+ propValue = qx.lang.Number.limit(propValue, 0, 1);
+
+ // should we omit gecko's flickering here
+ // and limit the max value to 0.99?
+
+ if (qx.sys.Client.getInstance().isGecko())
+ {
+ this.setStyleProperty("MozOpacity", propValue);
+ }
+ else if (qx.sys.Client.getInstance().isKhtml())
+ {
+ this.setStyleProperty("KhtmlOpacity", propValue);
+ }
+
+ this.setStyleProperty("opacity", propValue);
+ }
+
+ return true;
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CURSOR
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyCursor = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ if (propValue == "pointer" &&
+ qx.sys.Client.getInstance().isMshtml()) {
+ this.setStyleProperty("cursor",
+ "hand");
+ } else {
+ this.setStyleProperty("cursor",
+ propValue);
+ }
+ }
+ else
+ {
+ this.removeStyleProperty("cursor");
+ }
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ BACKGROUND IMAGE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyBackgroundImage = function(propValue, propOldValue, propData)
+{
+ return qx.util.Validation.isValidString(propValue) ?
+ this.setStyleProperty("backgroundImage",
+ "url(" +
+ qx.manager.object.AliasManager.getInstance().resolvePath(propValue) +
+ ")") :
+ this.removeStyleProperty("backgroundImage");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CLIPPING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyClip = function(propValue, propOldValue, propData) {
+ return this._compileClipString();
+}
+
+qx.Proto._compileClipString = function()
+{
+ var vLeft = this.getClipLeft();
+ var vTop = this.getClipTop();
+ var vWidth = this.getClipWidth();
+ var vHeight = this.getClipHeight();
+
+ var vRight, vBottom;
+
+ if(vLeft == null)
+ {
+ vRight = (vWidth == null
+ ? "auto"
+ : vWidth + "px");
+ vLeft = "auto";
+ }
+ else
+ {
+ vRight = (vWidth == null
+ ? "auto"
+ : vLeft + vWidth + "px");
+ vLeft = vLeft + "px";
+ }
+
+ if(vTop == null)
+ {
+ vBottom = (vHeight == null
+ ? "auto"
+ : vHeight + "px");
+ vTop = "auto";
+ }
+ else
+ {
+ vBottom = (vHeight == null
+ ? "auto"
+ : vTop + vHeight + "px");
+ vTop = vTop + "px";
+ }
+
+ return this.setStyleProperty("clip",
+ ("rect(" +
+ vTop +
+ "," +
+ vRight +
+ "," +
+ vBottom +
+ "," +
+ vLeft +
+ ")"));
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ OVERFLOW
+---------------------------------------------------------------------------
+*/
+
+/*
+ This will measure the typical native scrollbar size in the environment
+*/
+qx.ui.core.Widget.initOverflow = function()
+{
+ if (qx.ui.core.Widget.initOverflowDone) {
+ return;
+ }
+
+ var t = document.createElement("div");
+ var s = t.style;
+
+ s.height = s.width = "100px";
+ s.overflow = "scroll";
+
+ document.body.appendChild(t);
+
+ var c = qx.dom.Dimension.getScrollBarSizeRight(t);
+ if (c) {
+ qx.ui.core.Widget.SCROLLBAR_SIZE = c;
+ }
+
+ document.body.removeChild(t);
+
+ qx.ui.core.Widget.initOverflowDone = true;
+}
+
+if (qx.sys.Client.getInstance().isGecko())
+{
+ qx.Proto._modifyOverflow = function(propValue, propOldValue, propData)
+ {
+ var pv = propValue;
+ var pn = propData.name;
+
+ switch(pv)
+ {
+ case "hidden":
+ pv = "-moz-scrollbars-none";
+ break;
+
+ case "scrollX":
+ pv = "-moz-scrollbars-horizontal";
+ break;
+
+ case "scrollY":
+ pv = "-moz-scrollbars-vertical";
+ break;
+ }
+
+ return this._applyOverflow(pn, pv, propValue, propOldValue);
+ }
+}
+
+// Mshtml conforms here to CSS3 Spec. Eventually there will be multiple
+// browsers which support these new overflowX overflowY properties.
+else if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._modifyOverflow = function(propValue, propOldValue, propData)
+ {
+ var pv = propValue;
+ var pn = propData.name;
+
+ switch(pv)
+ {
+ case "scrollX":
+ pn = "overflowX";
+ pv = "scroll";
+ break;
+
+ case "scrollY":
+ pn = "overflowY";
+ pv = "scroll";
+ break;
+ }
+
+ // Clear up concurrenting rules
+ var a = [ "overflow",
+ "overflowX",
+ "overflowY" ];
+ for (var i=0; i= 0){
+ this.setOpacity(this._computeFadeOpacity());
+ this.getFadeTimer().restart();
+ } else if(this.hasEventListeners(qx.ui.core.Widget.FADE_FINISHED)) {
+ this.createDispatchDataEvent(qx.ui.core.Widget.FADE_FINISHED, qx.ui.core.Widget.FADE_OUT);
+ };
+ break;
+ };
+ qx.ui.core.Widget.flushGlobalQueues();
+};
+
+qx.Proto._modifyFadeSteps = function(propValue, propOldValue, propData) {
+ if(propValue < 1) return;
+ this.setFadeInterval(parseInt(this.getFadeTime() / propValue));
+ this.setFadeUnit(Math.round(this.getFadeMax()/propValue));
+ return true;
+};
+
+qx.Proto._modifyFadeTime = function(propValue, propOldValue, propData) {
+ if(propValue < 1) return;
+ this.setFadeInterval(parseInt(propValue / this.getFadeSteps()));
+ return true;
+};
+
+qx.Proto._modifyFadeUnit = function(propValue, propOldValue, propData) {
+ this.setFadeSteps(Math.round(this.getFadeMax()/propValue));
+ return true;
+};
+
+qx.Proto._modifyFadeMax = function(propValue, propOldValue, propData) {
+ this.setFadeUnit(Math.round(propValue / this.getFadeSteps()));
+ return true;
+};
+
+qx.Proto._computeFadeOpacity = function() {
+ var op = this.getFadeUnit() * this.getFadeCounter() / 100;
+ return(op);
+};
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+qx.Proto.dispose = function()
+{
+ if(this.getDisposed()) {
+ return;
+ }
+
+ var vElement = this.getElement();
+
+ if (vElement)
+ {
+ this._removeInlineEvents(vElement);
+
+ delete this._isCreated;
+
+ vElement.qx_Widget = null;
+
+ this._element = null;
+ this._style = null;
+ }
+
+ this._inlineEvents = null;
+ this._element = null;
+ this._style = null;
+ this._borderElement = null;
+ this._borderStyle = null;
+ this._oldParent = null;
+
+ // should be enough to remove the hashTables
+ delete this._styleProperties;
+ delete this._htmlProperties;
+ delete this._htmlAttributes;
+ delete this._states;
+
+ // remove queue content
+ for (var i in this._jobQueue) {
+ delete this._jobQueue[i];
+ }
+ delete this._jobQueue;
+
+ for (var i in this._layoutChanges) {
+ delete this._layoutChanges[i];
+ }
+ delete this._layoutChanges;
+
+ // dispose the fader
+ if(this._fadeTimer){
+ this._fadeTimer.dispose();
+ this._fadeTimer = null;
+ }
+
+ return qx.core.Target.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Flash.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Flash.js
new file mode 100644
index 0000000000..30f32319f2
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Flash.js
@@ -0,0 +1,468 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+/*!
+ Original non qooxdoo Version by Geoff Stearns
+ Flash detection and embed - http://blog.deconcept.com/flashobject/
+ FlashObject is (c) 2005 Geoff Stearns and is released under the MIT License
+ http://www.opensource.org/licenses/mit-license.php
+
+ Modified for qooxdoo by Sebastian Werner
+ Based on version 1.2.3
+ Relicensed under LGPL in assent of Geoff Stearns
+*/
+
+qx.OO.defineClass("qx.ui.embed.Flash", qx.ui.basic.Terminator,
+function(vSource, vVersion)
+{
+ qx.ui.basic.Terminator.call(this);
+
+ // Use background handling of qx.ui.core.Widget instead
+ this._params = {};
+ this._variables = {};
+
+ if(qx.util.Validation.isValidString(vSource)) {
+ this.setSource(vSource);
+ }
+
+ this.setVersion(qx.util.Validation.isValidString(vVersion) ? vVersion : qx.ui.embed.Flash.MINREQUIRED);
+});
+
+qx.OO.addProperty({ name : "source", type : "string" });
+qx.OO.addProperty({ name : "version" });
+
+qx.OO.addProperty({ name : "enableExpressInstall", type : "boolean", defaultValue : false });
+qx.OO.addProperty({ name : "enableDetection", type : "boolean", defaultValue : true });
+qx.OO.addProperty({ name : "redirectUrl", type : "string" });
+
+qx.OO.addProperty({ name : "quality", type : "string", impl : "param", defaultValue : "high", possibleValues : [ "low", "autolow", "autohigh", "medium", "high", "best" ] });
+qx.OO.addProperty({ name : "scale", type : "string", impl : "param", defaultValue : "showall", possibleValues : [ "showall", "noborder", "excactfit", "noscale" ] });
+qx.OO.addProperty({ name : "wmode", type : "string", impl : "param", defaultValue : "", possibleValues : [ "window", "opaque", "transparent" ] });
+qx.OO.addProperty({ name : "play", type : "boolean", impl : "param", defaultValue : true });
+qx.OO.addProperty({ name : "loop", type : "boolean", impl : "param", defaultValue : true });
+qx.OO.addProperty({ name : "menu", type : "boolean", impl : "param", defaultValue : true });
+
+qx.ui.embed.Flash.EXPRESSINSTALL = [6,0,65];
+qx.ui.embed.Flash.MINREQUIRED = "1";
+qx.ui.embed.Flash.PLAYERVERSION = null;
+qx.ui.embed.Flash.PLUGINKEY = "Shockwave Flash";
+qx.ui.embed.Flash.ACTIVEXKEY = "ShockwaveFlash.ShockwaveFlash";
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PLAYER VERSION CACHE
+---------------------------------------------------------------------------
+*/
+
+qx.ui.embed.Flash.getPlayerVersion = function()
+{
+ if (qx.ui.embed.Flash.PLAYERVERSION != null) {
+ return qx.ui.embed.Flash.PLAYERVERSION;
+ }
+
+ var vPlayerVersion = new qx.type.Version(0,0,0);
+
+ if(navigator.plugins && navigator.mimeTypes.length)
+ {
+ var x = navigator.plugins[qx.ui.embed.Flash.PLUGINKEY];
+
+ if(x && x.description) {
+ vPlayerVersion = new qx.type.Version(x.description.replace(/([a-z]|[A-Z]|\s)+/, '').replace(/(\s+r|\s+b[0-9]+)/, '.'));
+ }
+ }
+ else if (window.ActiveXObject)
+ {
+ try {
+ var axo = new ActiveXObject(qx.ui.embed.Flash.ACTIVEXKEY);
+ vPlayerVersion = new qx.type.Version(axo.GetVariable("$version").split(" ")[1].split(","));
+ }
+ catch (e) {}
+ }
+
+ return qx.ui.embed.Flash.PLAYERVERSION = vPlayerVersion;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ BASICS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._version = null;
+qx.Proto._source = "";
+
+qx.Proto._applyElementData = function(el)
+{
+ qx.ui.basic.Terminator.prototype._applyElementData.call(this, el);
+
+ // Check for ExpressInstall
+ this._expressInstall = false;
+
+ if (this.getEnableExpressInstall())
+ {
+ // check to see if we need to do an express install
+ var expressInstallReqVer = new qx.type.Version(qx.ui.embed.Flash.EXPRESSINSTALL);
+ var installedVer = qx.ui.embed.Flash.getPlayerVersion();
+
+ if (installedVer.versionIsValid(expressInstallReqVer) && !installedVer.versionIsValid(this._version)) {
+ this._expressInstall = true;
+ }
+ }
+
+ // this.debug("ExpressInstall Enabled: " + this._expressInstall);
+
+ // Apply HTML
+ if(!this.getEnableDetection() || this._expressInstall || qx.ui.embed.Flash.getPlayerVersion().versionIsValid(this._version))
+ {
+ el.innerHTML = this.generateHTML();
+ }
+ else
+ {
+ var redir = this.getRedirectUrl();
+
+ if(redir != "") {
+ document.location.replace(redir);
+ }
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifySource = function(propValue, propOldValue, propName)
+{
+ this._source = qx.util.Validation.isValidString(propValue) ? qx.manager.object.AliasManager.getInstance().resolvePath(propValue) : "";
+ return true;
+}
+
+qx.Proto._modifyVersion = function(propValue, propOldValue, propData)
+{
+ if (this._version)
+ {
+ this._version.dispose();
+ this._version = null;
+ }
+
+ if (qx.util.Validation.isValidString(propValue)) {
+ this._version = new qx.type.Version(propValue);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyParam = function(propValue, propOldValue, propData)
+{
+ this.setParam(propData.name, propValue.toString());
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ OVERWRITE BACKGROUND COLOR HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyBackgroundColor = function(propValue, propOldValue, propData)
+{
+ if (propOldValue) {
+ propOldValue.remove(this);
+ }
+
+ if (propValue)
+ {
+ this._applyBackgroundColor(propValue.getHex());
+ propValue.add(this);
+ }
+ else
+ {
+ this._resetBackgroundColor();
+ }
+
+ return true;
+}
+
+qx.Proto._applyBackgroundColor = function(vNewValue) {
+ this.setParam("bgcolor", vNewValue);
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PARAMS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.setParam = function(name, value){
+ this._params[name] = value;
+}
+
+qx.Proto.getParam = function(name){
+ return this._params[name];
+}
+
+qx.Proto.getParams = function() {
+ return this._params;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ VARIABLES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.setVariable = function(name, value){
+ this._variables[name] = value;
+}
+
+qx.Proto.getVariable = function(name){
+ return this._variables[name];
+}
+
+qx.Proto.getVariables = function(){
+ return this._variables;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HTML UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.generateParamTags = function()
+{
+ var vParams = this.getParams();
+ var vParamTags = [];
+
+ for (var vKey in vParams)
+ {
+ vParamTags.push(" ");
+ }
+
+ return vParamTags.join("");
+}
+
+qx.Proto.getVariablePairs = function()
+{
+ var variables = this.getVariables();
+ var variablePairs = [];
+
+ for (var key in variables) {
+ variablePairs.push(key + "=" + variables[key]);
+ }
+
+ return variablePairs.join("&");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HTML GENERATOR
+---------------------------------------------------------------------------
+*/
+
+// Netscape Plugin Architecture
+if (navigator.plugins && navigator.mimeTypes && navigator.mimeTypes.length)
+{
+ qx.Proto.generateHTML = function()
+ {
+ var html = [];
+
+ // Express Install Handling
+ if (this._expressInstall)
+ {
+ document.title = document.title.slice(0, 47) + ' - Flash Player Installation';
+
+ this.addVariable('MMredirectURL', escape(window.location));
+ this.addVariable('MMdoctitle', document.title);
+ this.addVariable('MMplayerType', 'PlugIn');
+ }
+
+ html.push(" 0)
+ {
+ html.push(" ");
+ html.push("flashvars");
+ html.push("=");
+ html.push("'");
+ html.push(pairs);
+ html.push("'");
+ }
+
+ html.push("> ");
+
+ return html.join("");
+ }
+}
+
+// Internet Explorer ActiveX Architecture
+else
+{
+ qx.Proto.generateHTML = function()
+ {
+ var html = [];
+
+ // Express Install Handling
+ if (this._expressInstall)
+ {
+ document.title = document.title.slice(0, 47) + ' - Flash Player Installation';
+
+ this.addVariable("MMredirectURL", escape(window.location));
+ this.addVariable("MMdoctitle", document.title);
+ this.addVariable("MMplayerType", "ActiveX");
+ }
+
+ html.push("");
+ html.push(" ");
+
+ var tags = this.generateParamTags();
+
+ if(tags.length > 0) {
+ html.push(tags);
+ }
+
+ var pairs = this.getVariablePairs();
+
+ if(pairs.length > 0)
+ {
+ html.push(" ");
+ }
+
+ html.push(" ");
+
+ return html.join("");
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ METHODS TO GIVE THE LAYOUTERS INFORMATIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._isWidthEssential = qx.util.Return.returnTrue;
+qx.Proto._isHeightEssential = qx.util.Return.returnTrue;
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PREFERRED DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computePreferredInnerWidth = qx.util.Return.returnZero;
+qx.Proto._computePreferredInnerHeight = qx.util.Return.returnZero;
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ delete this._source;
+ delete this._params;
+ delete this._variables;
+
+ if (this._version)
+ {
+ this._version.dispose();
+ this._version = null;
+ }
+
+ qx.ui.basic.Terminator.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Gallery.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Gallery.js
new file mode 100644
index 0000000000..11a40e9046
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Gallery.js
@@ -0,0 +1,556 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+/**
+ * @event beforeToolTipAppear {qx.event.type.Event}
+ * @event loadComplete {qx.event.type.Event}
+ */
+qx.OO.defineClass("qx.ui.embed.Gallery", qx.ui.basic.Terminator,
+function(vGalleryList)
+{
+ qx.ui.basic.Terminator.call(this);
+
+ this._blank = qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif");
+ this._list = vGalleryList;
+ this._listSize = vGalleryList.length;
+ this._processedImages = 0;
+
+ this.setOverflow("auto");
+
+ this.setHtmlProperty("className", "qx_ui_embed_Gallery");
+
+ this._manager = new qx.manager.selection.DomSelectionManager(this);
+
+ this._manager.setMultiColumnSupport(true);
+
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+ this.addEventListener("mousemove", this._onmousemove);
+
+ this.addEventListener("click", this._onclick);
+ this.addEventListener("dblclick", this._ondblclick);
+
+ this.addEventListener("keypress", this._onkeypress);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "thumbMaxWidth", type : "number", defaultValue : 100 });
+qx.OO.addProperty({ name : "thumbMaxHeight", type : "number", defaultValue : 100 });
+qx.OO.addProperty({ name : "decorHeight", type : "number", defaultValue : 40 });
+qx.OO.addProperty({ name : "showTitle", type : "boolean", defaultValue : true });
+qx.OO.addProperty({ name : "showComment", type : "boolean", defaultValue : true });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ELEMENT HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyElementData = function() {
+ this.getElement().appendChild(this.createView());
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getManager = function() {
+ return this._manager;
+}
+
+qx.Proto.getList = function() {
+ return this._list;
+}
+
+qx.Proto.update = function(vGalleryList)
+{
+ this._manager.deselectAll();
+
+ this._list = vGalleryList;
+
+ var el = this.getElement();
+ el.replaceChild(this.createView(), el.firstChild);
+}
+
+qx.Proto.removeAll = function()
+{
+ this._manager.deselectAll();
+ this.getElement().innerHTML = "";
+}
+
+qx.Proto.updateImageById = function(vId, vSrc, vWidth, vHeight) {
+ this.updateImageSrcById(vId, vSrc);
+ this.updateImageDimensionsById(vId, vWidth, vHeight);
+}
+
+qx.Proto.updateImageDimensionsById = function(vId, vWidth, vHeight) {
+ this.updateImageDimensionsByPosition(this.getPositionById(vId), vWidth, vHeight);
+}
+
+qx.Proto.updateImageDimensionsByPosition = function(vPos, vWidth, vHeight) {
+ // TBD: compare dimensions with max. thumb size and scale proportionally if necessary
+ if (vPos == -1) {
+ throw new Error("No valid Position: " + vPos);
+ }
+
+ var cnode = this.getNodeByPosition(vPos).getElementsByTagName("img")[0];
+
+ cnode.width = vWidth;
+ cnode.height = vHeight;
+
+ cnode.style.marginLeft = cnode.style.marginRight = Math.floor((this.getThumbMaxWidth()-vWidth)/2) + "px";
+ cnode.style.marginTop = cnode.style.marginBottom = Math.floor((this.getThumbMaxHeight()-vHeight)/2) + "px";
+
+ this._list[vPos].thumbWidth = vWidth;
+ this._list[vPos].thumbHeight = vHeight;
+}
+
+qx.Proto.updateImageSrcById = function(vId, vSrc) {
+ this.updateImageSrcByPosition(this.getPositionById(vId), vSrc);
+}
+
+qx.Proto.updateImageSrcByPosition = function(vPos, vSrc)
+{
+ if (vPos == -1) {
+ throw new Error("No valid Position: " + vPos);
+ }
+
+ var vNode = this.getNodeByPosition(vPos);
+
+ vNode.getElementsByTagName("img")[0].src = vSrc;
+ this._list[vPos].src = vSrc;
+}
+
+qx.Proto.deleteById = function(vId) {
+ this.deleteByPosition(this.getPositionById(vId));
+}
+
+qx.Proto.deleteByPosition = function(vPos)
+{
+ this._manager.deselectAll();
+
+ if (vPos == -1) {
+ throw new Error("No valid Position: " + vPos);
+ }
+
+ var vNode = this.getNodeByPosition(vPos);
+
+ if (vNode) {
+ vNode.parentNode.removeChild(vNode);
+ }
+
+ this._list.splice(vPos, 1);
+}
+
+qx.Proto.getPositionById = function(vId)
+{
+ for (var i=0, a=this._list, l=a.length; i ");
+ }
+
+ if (qx.util.Validation.isValidString(this.getHtml())) {
+ vHtml.push(this.getHtml());
+ }
+
+ this.getElement().innerHTML = vHtml.join("");
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Iframe.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Iframe.js
new file mode 100644
index 0000000000..ef10aa2730
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Iframe.js
@@ -0,0 +1,430 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+/**
+ * @event load {qx.event.type.Event}
+ */
+qx.OO.defineClass("qx.ui.embed.Iframe", qx.ui.basic.Terminator,
+function(vSource)
+{
+ // **********************************************************************
+ // INIT
+ // **********************************************************************
+ qx.ui.basic.Terminator.call(this);
+
+ this.setSelectable(false);
+ this.setTabIndex(0);
+
+ var o = this;
+ this.__onreadystatechange = function(e) { return o._onreadystatechange(e); }
+ this.__onload = function(e) { return o._onload(e); }
+
+ if (qx.util.Validation.isValid(vSource)) {
+ this.setSource(vSource);
+ }
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "iframe" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "source", type : "string" });
+
+qx.OO.addProperty({ name : "frameName", type : "string" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INTERNAL PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+
+// iframe DOM node
+
+qx.Proto._iframeNode = null;
+
+qx.Proto.getIframeNode = function() {
+ return this._iframeNode;
+}
+
+qx.Proto.setIframeNode = function(vIframeNode) {
+ return this._iframeNode = vIframeNode;
+}
+
+
+// blocker div DOM node
+
+qx.Proto._blockerNode = null;
+
+qx.Proto.getBlockerNode = function() {
+ return this._blockerNode;
+}
+
+qx.Proto.setBlockerNode = function(vBlockerNode) {
+ return this._blockerNode = vBlockerNode;
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.reload = function() {
+ this._applySource();
+}
+
+
+qx.Proto.block = function()
+{
+ if (this._blockerNode) {
+ this._blockerNode.style.display = "";
+ }
+};
+
+qx.Proto.release = function()
+{
+ if (this._blockerNode) {
+ this._blockerNode.style.display = "none";
+ }
+};
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyElement = function(propValue, propOldValue, propData)
+{
+
+ var iframeNode = this.getIframeNode();
+
+ if (!iframeNode)
+ {
+
+ qx.ui.embed.Iframe.initIframe(this.getFrameName());
+
+ // clone proto element and assign iframe
+ iframeNode = this.setIframeNode(qx.ui.embed.Iframe._element.cloneNode(true));
+
+ qx.ui.embed.Iframe.initBlocker();
+
+ // clone proto blocker
+ blockerNode = this.setBlockerNode(qx.ui.embed.Iframe._blocker.cloneNode(true));
+
+ if (qx.sys.Client.getInstance().isMshtml()) {
+ iframeNode.onreadystatechange = this.__onreadystatechange;
+ } else {
+ iframeNode.onload = this.__onload;
+ }
+ }
+
+ this._applySource();
+
+ propValue.appendChild(iframeNode);
+ propValue.appendChild(blockerNode);
+
+ // create basic widget
+ qx.ui.basic.Terminator.prototype._modifyElement.call(this, propValue, propOldValue, propData);
+
+ return true;
+}
+
+
+qx.Proto._beforeAppear = function() {
+ qx.ui.basic.Terminator.prototype._beforeAppear.call(this);
+
+ // register to iframe manager as active widget
+ qx.manager.object.IframeManager.getInstance().add(this);
+};
+
+
+qx.Proto._beforeDisappear = function() {
+ qx.ui.basic.Terminator.prototype._beforeDisappear.call(this);
+
+ // deregister from iframe manager
+ qx.manager.object.IframeManager.getInstance().remove(this);
+};
+
+
+qx.Proto._modifySource = function(propValue, propOldValue, propData)
+{
+ if(this.isCreated()) {
+ this._applySource();
+ }
+
+ return true;
+}
+
+qx.Proto._applySource = function()
+{
+ var currentSource = this.getSource();
+
+ if (qx.util.Validation.isInvalidString(currentSource)) {
+ currentSource = qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif");
+ }
+
+ this._isLoaded = false;
+ this.getIframeNode().src = currentSource;
+}
+
+qx.Proto._modifyFrameName = function (propValue, propOldValue, propName, uniqModIds)
+{
+ if( this.isCreated()) {
+ throw new Error("Not allowed to set frame name after it has been created");
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onreadystatechange = function()
+{
+ if (this.getIframeNode().readyState == "complete") {
+ this.dispatchEvent(new qx.event.type.Event("load"), true);
+ }
+}
+
+qx.Proto._onload = function()
+{
+ this._isLoaded = true;
+ this.dispatchEvent(new qx.event.type.Event("load"), true);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ WINDOW & DOCUMENT ACCESS
+---------------------------------------------------------------------------
+*/
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto.getContentWindow = function()
+ {
+ if (this.isCreated()) {
+ try { return this.getIframeNode().contentWindow; }
+ catch (ex) {}
+ }
+
+ return null;
+ }
+
+ qx.Proto.getContentDocument = function()
+ {
+ var win = this.getContentWindow();
+ if (win) {
+ try { return win.document; }
+ catch (ex) {}
+ }
+
+ return null;
+ }
+}
+else
+{
+ qx.Proto.getContentWindow = function()
+ {
+ var doc = this.getContentDocument();
+ return doc ? doc.defaultView : null;
+ }
+
+ qx.Proto.getContentDocument = function()
+ {
+ if (this.isCreated()) {
+ try { return this.getIframeNode().contentDocument; }
+ catch (ex) {}
+ }
+
+ return null;
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LOAD STATUS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._isLoaded = false;
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto.isLoaded = function()
+ {
+ var doc = this.getContentDocument();
+ return doc ? doc.readyState == "complete" : false;
+ }
+}
+else
+{
+ qx.Proto.isLoaded = function()
+ {
+ return this._isLoaded;
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this.__onreadystatechange = this.__onload = null;
+
+ if (this._iframeNode)
+ {
+ this._iframeNode.onreadystatechange = null;
+ this._iframeNode.onload = null;
+
+ this._iframeNode = null;
+ }
+
+ qx.ui.basic.Terminator.prototype.dispose.call(this);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INIT
+---------------------------------------------------------------------------
+*/
+qx.ui.embed.Iframe.initIframe = function(vFrameName)
+{
+ if (qx.ui.embed.Iframe._element && !vFrameName) {
+ return;
+ }
+
+ if (vFrameName && qx.sys.Client.getInstance().isMshtml()) {
+ var f = qx.ui.embed.Iframe._element = document.createElement('');
+ } else {
+ var f = qx.ui.embed.Iframe._element = document.createElement("iframe");
+ if (vFrameName) {
+ f.name = vFrameName;
+ }
+ }
+
+ f.frameBorder = "0";
+ f.frameSpacing = "0";
+
+ f.marginWidth = "0";
+ f.marginHeight = "0";
+
+ f.width = "100%";
+ f.height = "100%";
+
+ f.hspace = "0";
+ f.vspace = "0";
+
+ f.border = "0";
+ f.scrolling = "auto";
+ f.unselectable = "on";
+ f.allowTransparency = "true";
+
+ f.style.position = "absolute";
+ f.style.top = 0;
+ f.style.left = 0;
+ };
+
+qx.ui.embed.Iframe.initBlocker = function()
+{
+
+ if (qx.ui.embed.Iframe._blocker) {
+ return;
+ }
+
+ var b = qx.ui.embed.Iframe._blocker = document.createElement("div");
+
+ if (qx.sys.Client.getInstance().isMshtml()) {
+ b.style.backgroundImage = "url(" + qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif") + ")";
+ }
+
+ b.style.position = "absolute";
+ b.style.top = 0;
+ b.style.left = 0;
+ b.style.width = "100%";
+ b.style.height = "100%";
+ b.style.zIndex = 1;
+ b.style.display = "none";
+};
+
+
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/LinkEmbed.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/LinkEmbed.js
new file mode 100644
index 0000000000..97bf2a0965
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/LinkEmbed.js
@@ -0,0 +1,88 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.embed.LinkEmbed", qx.ui.embed.HtmlEmbed,
+function(vHtml, vUri, vTarget)
+{
+ qx.ui.embed.HtmlEmbed.call(this, vHtml);
+
+ if (typeof vUri != "undefined") {
+ this.setUri(vUri);
+ }
+
+ if (typeof vTarget != "undefined") {
+ this.setTarget(vTarget);
+ }
+});
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Any valid html URI
+*/
+qx.OO.addProperty({ name : "uri", type : "string", defaultValue : "#", impl : "html" });
+
+/*!
+ Any valid html target
+*/
+qx.OO.addProperty({ name : "target", type : "string", defaultValue : "_blank", impl : "html" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.ui.embed.LinkEmbed.LINK_START = "";
+qx.ui.embed.LinkEmbed.LINK_STOP = " ";
+
+qx.Proto._syncHtml = function()
+{
+ var vHtml = [];
+
+ vHtml.push(qx.ui.embed.LinkEmbed.LINK_START);
+ vHtml.push(this.getTarget());
+ vHtml.push(qx.ui.embed.LinkEmbed.HREF_START);
+ vHtml.push(this.getUri());
+ vHtml.push(qx.ui.embed.LinkEmbed.HREF_STOP);
+ vHtml.push(this.getHtml());
+ vHtml.push(qx.ui.embed.LinkEmbed.LINK_STOP);
+
+ this.getElement().innerHTML = vHtml.join("");
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/NodeEmbed.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/NodeEmbed.js
new file mode 100644
index 0000000000..e5e9fd0d91
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/NodeEmbed.js
@@ -0,0 +1,48 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.embed.NodeEmbed", qx.ui.basic.Terminator,
+function(vId)
+{
+ qx.ui.basic.Terminator.call(this);
+
+ if (qx.util.Validation.isValidString(vId)) {
+ this.setSourceNodeId(vId);
+ }
+});
+
+qx.OO.addProperty({ name : "sourceNodeId", type : "string" });
+
+qx.Proto._createElementImpl = function()
+{
+ var vNode = document.getElementById(this.getSourceNodeId());
+
+ if (!vNode) {
+ throw new Error("Could not find source node with ID: " + this.getSourceNodeId());
+ }
+
+ vNode.style.display = "";
+
+ return this.setElement(vNode);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/TextEmbed.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/TextEmbed.js
new file mode 100644
index 0000000000..d702eef789
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/TextEmbed.js
@@ -0,0 +1,121 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+#require(qx.renderer.font.FontCache)
+#after(qx.renderer.font.FontObject)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.embed.TextEmbed", qx.ui.basic.Terminator,
+function(vText)
+{
+ qx.ui.basic.Terminator.call(this);
+
+ if (qx.util.Validation.isValidString(vText)) {
+ this.setText(vText);
+ }
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Any text string which can contain TEXT, too
+*/
+qx.OO.addProperty({ name : "text", type : "string" });
+
+/*!
+ The font property describes how to paint the font on the widget.
+*/
+qx.OO.addProperty({ name : "font", type : "object", instance : "qx.renderer.font.Font", convert : qx.renderer.font.FontCache, allowMultipleArguments : true });
+
+/*!
+ Wrap the text?
+*/
+qx.OO.addProperty({ name : "wrap", type : "boolean", defaultValue : true });
+
+/** The horizontal alignment of the text. */
+qx.OO.addProperty({ name : "textAlign", type : "string", defaultValue : "left", possibleValues : [ "left", "center", "right", "justify" ], allowNull : false });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyText = function()
+{
+ if (this._isCreated) {
+ this._syncText();
+ }
+
+ return true;
+}
+
+qx.Proto._modifyFont = function(propValue, propOldValue, propData)
+{
+ if (propValue) {
+ propValue._applyWidget(this);
+ } else if (propOldValue) {
+ propOldValue._resetWidget(this);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyWrap = function(propValue, propOldValue, propData)
+{
+ this.setStyleProperty("whiteSpace", propValue ? "normal" : "nowrap");
+ return true;
+}
+
+// property modifier
+qx.Proto._modifyTextAlign = function(propValue, propOldValue, propData) {
+ this.setStyleProperty("textAlign", propValue);
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ELEMENT HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyElementData = function() {
+ this.getElement().appendChild(document.createTextNode(this.getText()));
+}
+
+qx.Proto._syncText = function() {
+ this.getElement().firstChild.nodeValue = this.getText();
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/Button.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/Button.js
new file mode 100644
index 0000000000..29412a39d8
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/Button.js
@@ -0,0 +1,200 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_form)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.form.Button", qx.ui.basic.Atom,
+function(vText, vIcon, vIconWidth, vIconHeight, vFlash)
+{
+ // ************************************************************************
+ // INIT
+ // ************************************************************************
+ qx.ui.basic.Atom.call(this, vText, vIcon, vIconWidth, vIconHeight, vFlash);
+
+ // Make focusable
+ this.setTabIndex(1);
+
+
+ // ************************************************************************
+ // MOUSE EVENTS
+ // ************************************************************************
+ this.addEventListener("mouseover", this._onmouseover);
+ this.addEventListener("mouseout", this._onmouseout);
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+
+
+ // ************************************************************************
+ // KEY EVENTS
+ // ************************************************************************
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keyup", this._onkeyup);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "button" });
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmouseover = function(e)
+{
+ if (e.getTarget() != this) {
+ return;
+ }
+
+ if (this.hasState("abandoned"))
+ {
+ this.removeState("abandoned");
+ this.addState("pressed");
+ }
+
+ this.addState("over");
+}
+
+qx.Proto._onmouseout = function(e)
+{
+ if (e.getTarget() != this) {
+ return;
+ }
+
+ this.removeState("over");
+
+ if (this.hasState("pressed"))
+ {
+ // Activate capturing if the button get a mouseout while
+ // the button is pressed.
+ this.setCapture(true);
+
+ this.removeState("pressed");
+ this.addState("abandoned");
+ }
+}
+
+qx.Proto._onmousedown = function(e)
+{
+ if (e.getTarget() != this || !e.isLeftButtonPressed()) {
+ return;
+ }
+
+ this.removeState("abandoned");
+ this.addState("pressed");
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ this.setCapture(false);
+
+ // We must remove the states before executing the command
+ // because in cases were the window lost the focus while
+ // executing we get the capture phase back (mouseout).
+ var hasPressed = this.hasState("pressed");
+ var hasAbandoned = this.hasState("abandoned");
+
+ if (hasPressed) {
+ this.removeState("pressed");
+ }
+
+ if (hasAbandoned) {
+ this.removeState("abandoned");
+ }
+
+ if (!hasAbandoned)
+ {
+ this.addState("over");
+
+ if (hasPressed) {
+ this.execute();
+ }
+ }
+}
+
+qx.Proto._onkeydown = function(e)
+{
+ switch(e.getKeyIdentifier())
+ {
+ case "Enter":
+ case "Space":
+ this.removeState("abandoned");
+ this.addState("pressed");
+ }
+}
+
+qx.Proto._onkeyup = function(e)
+{
+ switch(e.getKeyIdentifier())
+ {
+ case "Enter":
+ case "Space":
+ if (this.hasState("pressed"))
+ {
+ this.removeState("abandoned");
+ this.removeState("pressed");
+ this.execute();
+ }
+ }
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ // ************************************************************************
+ // MOUSE EVENTS
+ // ************************************************************************
+ this.removeEventListener("mouseover", this._onmouseover, this);
+ this.removeEventListener("mouseout", this._onmouseout, this);
+ this.removeEventListener("mousedown", this._onmousedown, this);
+ this.removeEventListener("mouseup", this._onmouseup, this);
+
+
+ // ************************************************************************
+ // KEY EVENTS
+ // ************************************************************************
+ this.removeEventListener("keydown", this._onkeydown, this);
+ this.removeEventListener("keyup", this._onkeyup, this);
+
+
+ // ************************************************************************
+ // SUPER CLASS
+ // ************************************************************************
+ return qx.ui.basic.Atom.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/CheckBox.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/CheckBox.js
new file mode 100644
index 0000000000..6e414bf30f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/CheckBox.js
@@ -0,0 +1,210 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_form)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.form.CheckBox", qx.ui.basic.Atom,
+function(vText, vValue, vName, vChecked)
+{
+ qx.ui.basic.Atom.call(this, vText);
+
+ this.setTabIndex(1);
+ this.setPadding(2, 3);
+
+ this._createIcon();
+
+ if (qx.util.Validation.isValidString(vValue)) {
+ this.setValue(vValue);
+ }
+
+ if (qx.util.Validation.isValidString(vName)) {
+ this.setName(vName);
+ }
+
+ if (qx.util.Validation.isValidBoolean(vChecked)) {
+ this.setChecked(vChecked);
+ } else {
+ this.setChecked(false);
+ }
+
+ this.addEventListener("click", this._onclick);
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keyup", this._onkeyup);
+});
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.OO.removeProperty({ name : "icon" });
+qx.OO.removeProperty({ name : "disabledIcon" });
+
+/*!
+ The HTML name of the form element used by the widget
+*/
+qx.OO.addProperty({ name : "name", type : "string" });
+
+/*!
+ The HTML value of the form element used by the widget
+*/
+qx.OO.addProperty({ name : "value", type : "string" });
+
+/*!
+ If the widget is checked
+*/
+qx.OO.addProperty({ name : "checked", type : "boolean", getAlias : "isChecked" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ICON HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.INPUT_TYPE = "checkbox";
+
+qx.Proto._createIcon = function()
+{
+ var i = this._iconObject = new qx.ui.form.InputCheckSymbol;
+
+ i.setType(this.INPUT_TYPE);
+ i.setChecked(this.isChecked());
+ i.setEnabled(this.isEnabled());
+ i.setAnonymous(true);
+
+ this.addAtBegin(i);
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyChecked = function(propValue, propOldValue, propData)
+{
+ if (this._iconObject) {
+ this._iconObject.setChecked(propValue);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyEnabled = function(propValue, propOldValue, propData)
+{
+ if (this._iconObject) {
+ this._iconObject.setEnabled(propValue);
+ }
+
+ return qx.ui.basic.Atom.prototype._modifyEnabled.call(this, propValue, propOldValue, propData);
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._handleIcon = function()
+{
+ switch(this.getShow())
+ {
+ case qx.ui.basic.Atom.SHOW_ICON:
+ case qx.ui.basic.Atom.SHOW_BOTH:
+ this._iconIsVisible = true;
+ break;
+
+ default:
+ this._iconIsVisible = false;
+ }
+
+ if (this._iconIsVisible)
+ {
+ this._iconObject ? this._iconObject.setDisplay(true) : this._createIcon();
+ }
+ else if (this._iconObject)
+ {
+ this._iconObject.setDisplay(false);
+ }
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT-HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onclick = function(e) {
+ this.toggleChecked();
+};
+
+
+qx.Proto._onkeydown = function(e)
+{
+ if(e.getKeyIdentifier() == "Enter" && !e.getAltKey()) {
+ this.toggleChecked();
+ }
+};
+
+
+qx.Proto._onkeyup = function(e)
+{
+ if(e.getKeyIdentifier() == "Space") {
+ this.toggleChecked();
+ }
+};
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if(this.getDisposed()) {
+ return;
+ }
+
+ this.removeEventListener("click", this._onclick);
+ this.removeEventListener("keydown", this._onkeydown);
+ this.removeEventListener("keyup", this._onkeyup);
+
+ return qx.ui.basic.Atom.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ComboBox.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ComboBox.js
new file mode 100644
index 0000000000..ad73ccbf1c
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ComboBox.js
@@ -0,0 +1,826 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_form)
+
+************************************************************************ */
+
+/**
+ * A combo-box for qooxdoo.
+ *
+ * The major additional feature compared to typical select fields is that it allows
+ * it to be editable. Also images are supported inside the popup list.
+ *
+ * Features:
+ *
+ * Editable text field
+ * Complete key-navigation
+ * Images inside the list
+ * Images and text inside the list
+ *
+ *
+ * @event beforeInitialOpen {qx.event.type.Event}
+ */
+qx.OO.defineClass("qx.ui.form.ComboBox", qx.ui.layout.HorizontalBoxLayout,
+function()
+{
+ qx.ui.layout.HorizontalBoxLayout.call(this);
+
+
+ // ************************************************************************
+ // LIST
+ // ************************************************************************
+ var l = this._list = new qx.ui.form.List;
+
+ l.setAppearance("combo-box-list");
+
+
+ // ************************************************************************
+ // MANAGER
+ // ************************************************************************
+ var m = this._manager = this._list.getManager();
+
+ m.setMultiSelection(false);
+ m.setDragSelection(false);
+
+
+ // ************************************************************************
+ // POPUP
+ // ************************************************************************
+ var p = this._popup = new qx.ui.popup.Popup;
+
+ p.setAppearance("combo-box-popup");
+ p.setAutoHide(false);
+
+ p.add(l);
+
+
+ // ************************************************************************
+ // TEXTFIELD
+ // ************************************************************************
+ var f = this._field = new qx.ui.form.TextField;
+
+ f.setAppearance("combo-box-text-field");
+ f.setTabIndex(-1);
+
+ this.add(f);
+
+
+ // ************************************************************************
+ // BUTTON
+ // ************************************************************************
+
+ // Use qx.ui.basic.Atom instead of qx.ui.form.Button here to omit the registration
+ // of the unneeded and complex button events.
+ var b = this._button = new qx.ui.basic.Atom(null, "widget/arrows/down.gif");
+
+ b.setAppearance("combo-box-button");
+ b.setTabIndex(-1);
+
+ this.add(b);
+
+
+ // ************************************************************************
+ // BEHAVIOR
+ // ************************************************************************
+ this.setTabIndex(1);
+ this.setEditable(false);
+
+
+ // ************************************************************************
+ // WIDGET MOUSE EVENTS
+ // ************************************************************************
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+ this.addEventListener("mouseover", this._onmouseover);
+ this.addEventListener("mousewheel", this._onmousewheel);
+
+
+ // ************************************************************************
+ // WIDGET KEY EVENTS
+ // ************************************************************************
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keypress", this._onkeypress);
+ this.addEventListener("keyinput", this._onkeyinput);
+
+
+ // ************************************************************************
+ // WIDGET STATE EVENTS
+ // ************************************************************************
+ this.addEventListener("beforeDisappear", this._onbeforedisappear);
+
+
+ // ************************************************************************
+ // CHILDREN EVENTS
+ // ************************************************************************
+ this._popup.addEventListener("appear", this._onpopupappear, this);
+ this._field.addEventListener("input", this._oninput, this);
+
+
+ // ************************************************************************
+ // DOCUMENT EVENTS
+ // ************************************************************************
+ var vDoc = qx.ui.core.ClientDocument.getInstance();
+ vDoc.addEventListener("windowblur", this._onwindowblur, this);
+
+
+ // ************************************************************************
+ // REMAPPING
+ // ************************************************************************
+ this.remapChildrenHandlingTo(l);
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "combo-box" });
+
+qx.OO.addProperty({ name: "editable", type: "boolean", getAlias: "isEditable" });
+qx.OO.addProperty({ name: "selected", type: "object", instance : "qx.ui.form.ListItem" });
+qx.OO.addProperty({ name: "value", type : "string" });
+qx.OO.addProperty({ name: "pagingInterval", type: "number", defaultValue: 10 });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getManager = function() {
+ return this._manager;
+}
+
+qx.Proto.getPopup = function() {
+ return this._popup;
+}
+
+qx.Proto.getList = function() {
+ return this._list;
+}
+
+qx.Proto.getField = function() {
+ return this._field;
+}
+
+qx.Proto.getButton = function() {
+ return this._button;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifySelected = function(propValue, propOldValue, propData)
+{
+ this._fromSelected = true;
+
+ // only do this if we called setSelected seperatly
+ // and not from the property "value".
+ if (!this._fromValue) {
+ this.setValue(propValue ? propValue.getLabel() : "");
+ }
+
+ // reset manager cache
+ this._manager.setLeadItem(propValue);
+ this._manager.setAnchorItem(propValue);
+
+ // sync to manager
+ if (propValue)
+ {
+ this._manager.setSelectedItem(propValue);
+ }
+ else
+ {
+ this._manager.deselectAll();
+ }
+
+ // reset hint
+ delete this._fromSelected;
+
+ return true;
+}
+
+qx.Proto._modifyValue = function(propValue, propOldValue, propData)
+{
+ this._fromValue = true;
+
+ // only do this if we called setValue seperatly
+ // and not from the event "input".
+ if (!this._fromInput)
+ {
+ if (this._field.getValue() == propValue) {
+ this._field.forceValue(null);
+ }
+
+ this._field.setValue(propValue);
+ }
+
+ // only do this if we called setValue seperatly
+ // and not from the property "selected".
+ if (!this._fromSelected)
+ {
+ // inform selected property
+ var vSelItem = this._list.findStringExact(propValue);
+
+ // ignore disabled items
+ if (vSelItem != null && !vSelItem.getEnabled()) {
+ vSelItem = null;
+ }
+
+ this.setSelected(vSelItem);
+ }
+
+ // reset hint
+ delete this._fromValue;
+
+ return true;
+}
+
+qx.Proto._modifyEditable = function(propValue, propOldValue, propData)
+{
+ var f = this._field;
+
+ f.setReadOnly(!propValue);
+ f.setCursor(propValue ? null : "default");
+ f.setSelectable(propValue);
+
+ return true;
+}
+
+qx.Proto._modifyEnabled = function(propValue, propOldValue, propData)
+{
+ if (this._button) {
+ this._button.setEnabled(propValue);
+ }
+
+ if (this._field) {
+ this._field.setEnabled(propValue);
+ }
+
+ return qx.ui.layout.HorizontalBoxLayout.prototype._modifyEnabled.call(this, propValue, propOldValue, propData);
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ POPUP HELPER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._oldSelected = null;
+
+qx.Proto._openPopup = function()
+{
+ var p = this._popup;
+ var el = this.getElement();
+
+ if (!p.isCreated()) {
+ this.createDispatchEvent("beforeInitialOpen");
+ }
+
+ if (this._list.getChildrenLength() == 0) {
+ return;
+ }
+
+ p.positionRelativeTo(el, 1, qx.dom.Dimension.getBoxHeight(el));
+ p.setWidth(this.getBoxWidth()-2);
+
+ p.setParent(this.getTopLevelWidget());
+ p.show();
+
+ this._oldSelected = this.getSelected();
+
+ this.setCapture(true);
+}
+
+qx.Proto._closePopup = function()
+{
+ this._popup.hide();
+ this.setCapture(false);
+}
+
+qx.Proto._testClosePopup = function()
+{
+ if (this._popup.isSeeable()) {
+ this._closePopup();
+ }
+}
+
+qx.Proto._togglePopup = function() {
+ this._popup.isSeeable() ? this._closePopup() : this._openPopup();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ OTHER EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onpopupappear = function(e)
+{
+ var vSelItem = this.getSelected();
+ if (vSelItem) {
+ vSelItem.scrollIntoView();
+ }
+}
+
+qx.Proto._oninput = function(e)
+{
+ // Hint for modifier
+ this._fromInput = true;
+
+ this.setValue(this._field.getComputedValue());
+
+ // be sure that the found item is in view
+ if (this.getPopup().isSeeable() && this.getSelected()) {
+ this.getSelected().scrollIntoView();
+ }
+
+ delete this._fromInput;
+}
+
+qx.Proto._onbeforedisappear = function(e)
+{
+ this._testClosePopup();
+}
+
+
+
+/*
+---------------------------------------------------------------------------
+ MOUSE EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousedown = function(e)
+{
+ var vTarget = e.getTarget();
+
+ switch(vTarget)
+ {
+ case this._field:
+ if (this.getEditable()) {
+ break;
+ }
+
+ // no break here
+
+ case this._button:
+ this._button.addState("pressed");
+ this._togglePopup();
+ break;
+
+ case this:
+ case this._list:
+ break;
+
+ default:
+ if (vTarget instanceof qx.ui.form.ListItem && vTarget.getParent() == this._list)
+ {
+ this._list._onmousedown(e);
+ this.setSelected(this._list.getSelectedItem());
+
+ this._closePopup();
+ this.setFocused(true);
+ }
+ else if (this._popup.isSeeable())
+ {
+ this._popup.hide();
+ this.setCapture(false);
+ }
+ }
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ switch(e.getTarget())
+ {
+ case this._field:
+ if (this.getEditable()) {
+ break;
+ }
+
+ // no break here
+
+ default:
+ this._button.removeState("pressed");
+ break;
+ }
+}
+
+qx.Proto._onmouseover = function(e)
+{
+ var vTarget = e.getTarget();
+
+ if (vTarget instanceof qx.ui.form.ListItem)
+ {
+ var vManager = this._manager;
+
+ vManager.deselectAll();
+
+ vManager.setLeadItem(vTarget);
+ vManager.setAnchorItem(vTarget);
+
+ vManager.setSelectedItem(vTarget);
+ }
+}
+
+qx.Proto._onmousewheel = function(e)
+{
+ if (!this._popup.isSeeable())
+ {
+ var toSelect;
+
+ var isSelected = this.getSelected();
+
+ if (e.getWheelDelta() < 0)
+ {
+ toSelect = isSelected ? this._manager.getNext(isSelected) : this._manager.getFirst();
+ }
+ else
+ {
+ toSelect = isSelected ? this._manager.getPrevious(isSelected) : this._manager.getLast();
+ }
+
+ if (toSelect)
+ {
+ this.setSelected(toSelect);
+ }
+ }
+ /* close the popup if the event target is not the combobox or
+ * not one of the list items of the popup list
+ */
+ else {
+ var vTarget = e.getTarget();
+
+ if (vTarget!=this && vTarget.getParent()!=this._list) {
+ this._popup.hide();
+ this.setCapture(false);
+ }
+ }
+}
+
+
+
+/*
+---------------------------------------------------------------------------
+ KEY EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeydown = function(e)
+{
+ var vManager = this._manager;
+ var vVisible = this._popup.isSeeable();
+
+ switch(e.getKeyIdentifier())
+ {
+ // Handle
+ case "Enter":
+ if (vVisible)
+ {
+ this.setSelected(this._manager.getSelectedItem());
+ this._closePopup();
+ this.setFocused(true);
+ }
+ else
+ {
+ this._openPopup();
+ }
+
+ return;
+
+ // Handle
+ case "Escape":
+ if (vVisible)
+ {
+ vManager.setLeadItem(this._oldSelected);
+ vManager.setAnchorItem(this._oldSelected);
+
+ vManager.setSelectedItem(this._oldSelected);
+
+ this._field.setValue(this._oldSelected ? this._oldSelected.getLabel() : "");
+
+ this._closePopup();
+ this.setFocused(true);
+ }
+
+ return;
+
+ // Handle Alt+Down
+ case "Down":
+ if (e.getAltKey())
+ {
+ this._togglePopup();
+ return;
+ }
+
+ break;
+ }
+};
+
+
+qx.Proto._onkeypress = function(e)
+{
+ var vVisible = this._popup.isSeeable();
+ var vManager = this._manager;
+
+ switch(e.getKeyIdentifier())
+ {
+ // Handle
+ case "PageUp":
+ if (!vVisible)
+ {
+ var vPrevious;
+ var vTemp = this.getSelected();
+
+ if (vTemp)
+ {
+ var vInterval = this.getPagingInterval();
+
+ do {
+ vPrevious = vTemp;
+ } while(--vInterval && (vTemp = vManager.getPrevious(vPrevious)));
+ }
+ else
+ {
+ vPrevious = vManager.getLast();
+ }
+
+ this.setSelected(vPrevious);
+
+ return;
+ }
+
+ break;
+
+ // Handle
+ case "PageDown":
+ if (!vVisible)
+ {
+ var vNext;
+ var vTemp = this.getSelected();
+
+ if (vTemp)
+ {
+ var vInterval = this.getPagingInterval();
+
+ do {
+ vNext = vTemp;
+ } while(--vInterval && (vTemp = vManager.getNext(vNext)));
+ }
+ else
+ {
+ vNext = vManager.getFirst();
+ }
+
+ this.setSelected(vNext);
+
+ return;
+ }
+
+ break;
+ }
+
+ // Default Handling
+ if (!this.isEditable() || vVisible)
+ {
+ this._list._onkeypress(e);
+
+ var vSelected = this._manager.getSelectedItem();
+
+ if (!vVisible)
+ {
+ this.setSelected(vSelected);
+ }
+ else if (vSelected)
+ {
+ this._field.setValue(vSelected.getLabel());
+ }
+ }
+};
+
+
+qx.Proto._onkeyinput = function(e)
+{
+ var vVisible = this._popup.isSeeable();
+ if (!this.isEditable() || vVisible)
+ {
+ this._list._onkeyinput(e);
+
+ var vSelected = this._manager.getSelectedItem();
+
+ if (!vVisible)
+ {
+ this.setSelected(vSelected);
+ }
+ else if (vSelected)
+ {
+ this._field.setValue(vSelected.getLabel());
+ }
+ }
+};
+
+
+
+/*
+---------------------------------------------------------------------------
+ GLOBAL BLUR/FOCUS HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onwindowblur = qx.Proto._testClosePopup;
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ FOCUS HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._visualizeBlur = function()
+{
+ // Force blur, even if mouseFocus is not active because we
+ // need to be sure that the previous focus rect gets removed.
+ // But this only needs to be done, if there is no new focused element.
+ if (qx.sys.Client.getInstance().isMshtml())
+ {
+ if (this.getEnableElementFocus() && !this.getFocusRoot().getFocusedChild())
+ {
+ try
+ {
+ if (this.getEditable())
+ {
+ this.getField().getElement().blur();
+ }
+ else
+ {
+ this.getElement().blur();
+ }
+ }
+ catch(ex) {};
+ }
+ }
+ else
+ {
+ if (this.getEnableElementFocus())
+ {
+ try
+ {
+ if (this.getEditable())
+ {
+ this.getField().getElement().blur();
+ }
+ else if (!this.getFocusRoot().getFocusedChild())
+ {
+ this.getElement().blur();
+ }
+ }
+ catch(ex) {};
+ }
+ }
+
+ this.removeState("focused");
+ return true;
+}
+
+qx.Proto._visualizeFocus = function()
+{
+ if (!qx.event.handler.FocusHandler.mouseFocus && this.getEnableElementFocus())
+ {
+ try
+ {
+ if (this.getEditable())
+ {
+ this.getField().getElement().focus();
+ this.getField()._ontabfocus();
+ }
+ else
+ {
+ this.getElement().focus();
+ }
+ }
+ catch(ex) {};
+ }
+
+ this.addState("focused");
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ // ************************************************************************
+ // WIDGET MOUSE EVENTS
+ // ************************************************************************
+ this.removeEventListener("mousedown", this._onmousedown);
+ this.removeEventListener("mouseup", this._onmouseup);
+ this.removeEventListener("mouseover", this._onmouseover);
+ this.removeEventListener("mousewheel", this._onmousewheel);
+
+
+ // ************************************************************************
+ // WIDGET KEY EVENTS
+ // ************************************************************************
+ this.removeEventListener("keydown", this._onkeydown);
+ this.removeEventListener("keypress", this._onkeypress);
+ this.removeEventListener("keyinput", this._onkeyinput);
+
+ // ************************************************************************
+ // DOCUMENT EVENTS
+ // ************************************************************************
+ var vDoc = qx.ui.core.ClientDocument.getInstance();
+ vDoc.removeEventListener("windowblur", this._onwindowblur, this);
+
+ if (this._list)
+ {
+ this._list.dispose();
+ this._list = null;
+ }
+
+ if (this._manager)
+ {
+ this._manager.dispose();
+ this._manager = null;
+ }
+
+ if (this._popup)
+ {
+ this._popup.removeEventListener("appear", this._onpopupappear, this);
+ this._popup.dispose();
+ this._popup = null;
+ }
+
+ if (this._field)
+ {
+ this._field.removeEventListener("input", this._oninput, this);
+ this._field.dispose();
+ this._field = null;
+ }
+
+ if (this._button)
+ {
+ this._button.dispose();
+ this._button = null;
+ }
+
+ return qx.ui.layout.HorizontalBoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ComboBoxEx.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ComboBoxEx.js
new file mode 100644
index 0000000000..935b2e78a7
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ComboBoxEx.js
@@ -0,0 +1,1044 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * David Perez Carmona (david-perez), based on qx.ui.form.ComboBox
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_comboboxex)
+#require(qx.ui.table.Table)
+
+************************************************************************ */
+
+/**
+ * An enhanced combo-box for qooxdoo.
+ *
+ * Features:
+ *
+ * Editable text field
+ * Complete key-navigation
+ * Mouse wheel navigation
+ * Multicolumn display in list
+ * If more than one column, headers are automatically shown
+ * Can show the ID and/or description of each list item
+ * Automatically calculating needed width
+ * Popup list always shows full contents, and can be wider than text field
+ * Search values through popup dialog
+ * Internationalization support of messages (through custom settings)
+ *
+ * Pending features:
+ *
+ * Images inside the list
+ * Autocomplete on key input
+ *
+ *
+ * @event beforeInitialOpen {qx.event.type.Event}
+ */
+qx.OO.defineClass('qx.ui.form.ComboBoxEx', qx.ui.layout.HorizontalBoxLayout, function() {
+ qx.ui.layout.HorizontalBoxLayout.call(this);
+
+ // ************************************************************************
+ // POPUP
+ // ************************************************************************
+ var p = this._popup = new qx.ui.popup.Popup;
+ p.setAppearance('combo-box-ex-popup');
+
+ // ************************************************************************
+ // LIST
+ // ************************************************************************
+ this._createList([ this._getComboSetting('idHeader'), this._getComboSetting('descriptionHeader') ]);
+
+ // ************************************************************************
+ // FIELD
+ // ************************************************************************
+ var f = this._field = new qx.ui.form.TextField;
+ f.setAppearance('combo-box-ex-text-field');
+ f.addEventListener("input", this._oninput, this);
+ this.add(f);
+ this.setEditable(false);
+
+ // ************************************************************************
+ // BUTTON
+ // ************************************************************************
+
+ // Use qx.ui.basic.Atom instead of qx.ui.form.Button here to omit the registration
+ // of the unneeded and complex button events.
+ var b = this._button = new qx.ui.basic.Atom(null, "widget/arrows/down.gif");
+ b.set({
+ appearance: "combo-box-button",
+ tabIndex: -1
+ });
+ this.add(b);
+
+ // ************************************************************************
+ // BEHAVIOR
+ // ************************************************************************
+ this.setTabIndex(1);
+
+ // ************************************************************************
+ // WIDGET MOUSE EVENTS
+ // ************************************************************************
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+ this.addEventListener("mousewheel", this._onmousewheel);
+ this.addEventListener("dblclick", function() {
+ if (this.getAllowSearch()) {
+ this.openSearchDialog();
+ }
+ });
+
+ // ************************************************************************
+ // WIDGET KEY EVENTS
+ // ************************************************************************
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keypress", this._onkeypress);
+
+ // ************************************************************************
+ // WIDGET STATE EVENTS
+ // ************************************************************************
+ this.addEventListener("beforeDisappear", this._testClosePopup);
+
+ // ************************************************************************
+ // CHILDREN EVENTS
+ // ************************************************************************
+ this._popup.addEventListener("appear", this._onpopupappear, this);
+});
+
+/*
+---------------------------------------------------------------------------
+ LOCALIZATION SUPPORT
+---------------------------------------------------------------------------
+*/
+
+qx.Settings.setDefault('titleSearch', 'Search items in list');
+qx.Settings.setDefault('toolTipSearchNext', 'Search next occurrence');
+qx.Settings.setDefault('idHeader', 'ID');
+qx.Settings.setDefault('descriptionHeader', 'Description');
+qx.Settings.setDefault('caseSensitiveCaption', 'Case sensitive');
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "combo-box-ex" });
+
+/*!Is the text field component editable or the user can only select from the list?*/
+qx.OO.addProperty({ name: "editable", type: "boolean", getAlias: "isEditable" });
+
+/*!0 based. -1 means no selected index. It retrieves always the value column of the selection, not the description.*/
+qx.OO.addProperty({ name: "value", type : "string" });
+
+/*!How many items to transverse with PageUp and PageDn.*/
+qx.OO.addProperty({ name: "pagingInterval", type: "number", defaultValue: 10 });
+
+/*!Show the ID column (column 0) of the selection data?*/
+qx.OO.addProperty({ name: "idColumnVisible", type: "boolean", getAlias: "isIdColumnVisible", defaultValue: false });
+
+/*!Only used when editable is false. It determines what to show in the text field of the combo box.*/
+qx.OO.addProperty({ name: "showOnTextField", type: "string", defaultValue: 'description', possibleValues : [ 'description', 'idAndDescription' ] });
+
+/*!Only used when editable is false and showOnTextField=='idAndDescription'.*/
+qx.OO.addProperty({ name: "idDescriptionSeparator", type: "string", defaultValue: '- ' });
+
+/*!Ensures that always an item is selected (in case the selection isn't empty). Only used when editable is false.*/
+qx.OO.addProperty({ name: 'ensureSomethingSelected', type: "boolean", defaultValue: true });
+
+/*!Allow the search dialog when double clicking the combo, or pressing special keys?.*/
+qx.OO.addProperty({ name: 'allowSearch', type: "boolean", defaultValue: true });
+
+/*!Maximum number of visible rows in the popup list.*/
+qx.OO.addProperty({ name: 'maxVisibleRows', type: "number", defaultValue: 10 });
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getPopup = function() {
+ return this._popup;
+}
+
+qx.Proto.getList = function() {
+ return this._list;
+}
+
+qx.Proto.getField = function() {
+ return this._field;
+}
+
+qx.Proto.getButton = function() {
+ return this._button;
+}
+
+qx.Proto._getComboSetting = function(key) {
+ return qx.Settings.getValueOfClass('qx.ui.form.ComboBoxEx', key);
+}
+
+/**Gets the current selected row of the selection.
+ * @return null if nothing selected or an array*/
+qx.Proto.getSelectedRow = function() {
+ var ind = this.getSelectedIndex();
+ return ind < 0 ? null : this._model.getData()[ind];
+}
+
+/**Creates the list component.*/
+qx.Proto._createList = function(columns) {
+ this._model = new qx.ui.table.SimpleTableModel;
+ // Default column titles
+ this._model.setColumns(columns);
+ var l = this._list = new qx.ui.table.Table(this._model);
+ l.setFocusedCell = function() {}
+ l.setAppearance('combo-box-ex-list');
+ // We receive this: Modification of property "keepFirstVisibleRowComplete" failed with exception: TypeError - vCurrentChild has no properties or
+ // this: Modification of property "keepFirstVisibleRowComplete" failed with exception: TypeError - this.getParent() has no properties
+ l.forceKeepFirstVisibleRowComplete(false);
+ var selMan = l._getSelectionManager();
+ var oldHandle = selMan.handleMouseUp, me = this;
+ selMan.handleMouseUp = function(vItem, e) {
+ oldHandle.apply(selMan, arguments);
+ if (e.isLeftButtonPressed()) {
+ me._testClosePopup();
+ }
+ }
+ this._modifyIdColumnVisible(this.getIdColumnVisible());
+ this._manager = l.getSelectionModel();
+ this._manager.addEventListener('changeSelection', this._onChangeSelection, this);
+ // Avoid deselection from user
+ this._manager.removeSelectionInterval = function() {};
+ this._manager.setSelectionMode(qx.ui.table.SelectionModel.SINGLE_SELECTION);
+ this._popup.add(l);
+ // Invalidate calculation of column widths
+ delete this._calcDimensions;
+}
+
+
+/*
+---------------------------------------------------------------------------
+ PSEUDO-PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/**Sets the header for each column.
+ * @param columns {String[]}*/
+qx.Proto.setColumnHeaders = function(columns) {
+ if (!this._list || columns.length != this._model.getColumnCount()) {
+ if (this._list) {
+ var data = this._model.getData();
+ this._list.setParent(null);
+ this._list.dispose();
+ this._list = null;
+ }
+ this._createList(columns);
+ if (data && data.length) {
+ this._model.setData(data);
+ }
+ } else {
+ this._model.setColumns(columns);
+ this._list.getTableColumnModel().init(columns.length);
+ delete this._calcDimensions;
+ }
+ this._modifyIdColumnVisible(this.getIdColumnVisible());
+}
+
+/**Getter for {@link #setColumnHeaders}.
+ * @return {String[]}*/
+qx.Proto.getColumnHeaders = function(propVal) {
+ var cols = [];
+ cols.length = this._model.getColumnCount();
+ for (var col = 0; col < cols.length; col++) {
+ cols[col] = this._model.getColumnName(col);
+ }
+ return cols;
+}
+
+/**Sets the list of selectable items.
+ * @param data {var[][]} Array of values. Its value is an array, with the following info:.
+ * Column 0 represents the ID, i.e. the value that is stored internally and used by the app.
+ * Column 1 represents the description, the text that the end user normally sees.
+ * Columns > 1 will also be shown in the popup list, it you have set the appropiate column headers with {@link #setColumnHeaders}.
+ * */
+qx.Proto.setSelection = function(data) {
+ // Invalidate calculation of column widths
+ delete this._calcDimensions;
+ this._model.setData(data);
+ // Try to preserve currently selected value
+ if (!this.getEditable()) {
+ this._modifyValue(this.getValue());
+ }
+}
+
+/**Getter for {@link #setSelection}.
+ * @return {Array}*/
+qx.Proto.getSelection = function() {
+ return this._model.getData();
+}
+
+/**Sets the index of the currently selected item in the list.
+ * @param index {Number} -1 means no selected index*/
+qx.Proto.setSelectedIndex = function(index) {
+ var items = this.getSelection().length;
+ if (items >= 0) {
+ if (index < 0 && !this.getEditable() && this.getEnsureSomethingSelected()) {
+ index = 0;
+ }
+ if (index >= 0) {
+ index = qx.lang.Number.limit(index, 0, items-1);
+ this._manager.setSelectionInterval(index, index);
+ if (this._popup.isSeeable()) {
+ this._list.scrollCellVisible(0, index);
+ }
+ } else {
+ this._manager.clearSelection();
+ }
+ }
+ return true;
+}
+
+/**Getter for {@link #setSelectedIndex}.*/
+qx.Proto.getSelectedIndex = function() {
+ var index = this._manager.getAnchorSelectionIndex();
+ return this._manager.isSelectedIndex(index) ? index:-1;
+}
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyShowOnTextField = function(propVal) {
+ if (!this.getEditable()) {
+ this.setSelectedIndex(this.getSelectedIndex());
+ delete this._calcDimensions; // Invalidate this._neededTextFieldWidth
+ }
+ return true;
+}
+
+qx.Proto._modifyMaxVisibleRows = function() {
+ delete this._calcDimensions; // Invalidate this._list.height
+ return true;
+}
+
+qx.Proto._checkIdDescriptionSeparator = function(propVal) {
+ // For measuring widths, it is better to replace spaces with non-breakable spaces
+ return String(propVal).replace(/ /g, '\u00A0')
+}
+
+qx.Proto._modifyIdDescriptionSeparator = function(propVal) {
+ if (!this.getEditable() && this.getShowOnTextField() == 'idAndDescription') {
+ this.setSelectedIndex(this.getSelectedIndex());
+ delete this._calcDimensions; // Invalidate this._neededTextFieldWidth
+ }
+ return true;
+}
+
+qx.Proto._modifyIdColumnVisible = function(propVal) {
+ this._list.getTableColumnModel().setColumnVisible(0, propVal);
+ delete this._calcDimensions;
+ return true;
+}
+
+qx.Proto._modifyEditable = function(propValue/*, propOldValue, propData*/) {
+ var f = this._field;
+ f.setReadOnly(!propValue);
+ f.setCursor(propValue ? null : "default");
+ f.setSelectable(propValue);
+ return true;
+}
+
+qx.Proto._modifyValue = function(propValue/*, propOldValue, propData*/) {
+ this._fromValue = true;
+
+ var values = this._model.getData();
+ var i = -1;
+ if (propValue != null) {
+ for (var i = 0; i < values.length; i++) {
+ if (propValue == values[i][0]) {
+ break;
+ }
+ }
+ if (i == values.length) {
+ i = -1;
+ }
+ }
+ if (this.getEditable()) {
+ this._field.setValue(propValue);
+ }
+ // only do this if we called setValue separately
+ // and not from the property "selected".
+ if (!this._fromSelected) {
+ this.setSelectedIndex(i);
+ }
+ // reset hint
+ delete this._fromValue;
+ return true;
+}
+
+qx.Proto._modifyEnabled = function(propValue/*, propOldValue, propData*/) {
+ if (this._button) {
+ this._button.setEnabled(propValue);
+ }
+ if (this._field) {
+ this._field.setEnabled(propValue);
+ }
+ return qx.ui.layout.HorizontalBoxLayout.prototype._modifyEnabled.apply(this, arguments);
+}
+
+
+/*
+---------------------------------------------------------------------------
+ POPUP HELPER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._oldSelected = null;
+
+qx.Proto._openPopup = function() {
+ if (this.isSearchInProgress()) {
+ return;
+ }
+ var p = this._popup;
+ p.setAutoHide(false);
+ var el = this.getElement();
+ if (!p.isCreated()) {
+ this.createDispatchEvent("beforeInitialOpen");
+ }
+ if (!this.getSelection().length) {
+ return;
+ }
+ p.positionRelativeTo(el, 1, qx.dom.Dimension.getBoxHeight(el));
+ this._calculateDimensions();
+ p.setParent(this.getTopLevelWidget());
+ p.auto();
+ p.show();
+ this._oldSelected = this.getSelectedIndex();
+ window.setInterval(function() {
+ p.setAutoHide(true);
+ }, 0);
+}
+
+/**Hide the popup list.*/
+qx.Proto._closePopup = function() {
+ this._popup.hide();
+}
+
+/**Hide the popup list only when needed.*/
+qx.Proto._testClosePopup = function() {
+ if (this._popup.isSeeable()) {
+ this._closePopup();
+ }
+}
+
+/**Toggle the visibility of the popup list.*/
+qx.Proto._togglePopup = function() {
+ this._popup.isSeeable() ? this._closePopup() : this._openPopup();
+}
+
+/*
+---------------------------------------------------------------------------
+ DIMENSIONING
+---------------------------------------------------------------------------
+*/
+
+/**Sizes the width of the text field component to the needed value to show any selection item.*/
+qx.Proto.sizeTextFieldToContent = function() {
+ this._calculateDimensions();
+ this._field.setWidth(this._neededTextFieldWidth);
+}
+
+/**Calculates the needed dimensions for the text field and list components*/
+qx.Proto._calculateDimensions = function() {
+ if (this._calcDimensions) {
+ // Already calculated
+ return;
+ }
+ var data = this.getSelection();
+ var cols = this.getColumnHeaders(), nCols = cols.length;
+ var columnWidths = [];
+ this._neededTextFieldWidth = 0;
+ columnWidths.length = cols.length;
+ for (var col = 0; col < cols.length; col++) {
+ columnWidths[col] = 0;
+ }
+ var withDescript = this.getShowOnTextField() == 'idAndDescription';
+ for (var row = 0, rows = Math.min(data.length, 50); row < rows; row++) {
+ var r = data[row], wi0, wi1;
+ for (col = 0; col < nCols; col++) {
+ var wi = this._getTextWidth(r[col]);
+ if (col == 0) {
+ wi0 = wi;
+ } else if (col == 1) {
+ wi1 = wi;
+ }
+ columnWidths[col] = Math.max(wi, columnWidths[col]);
+ }
+ this._neededTextFieldWidth = Math.max(this._neededTextFieldWidth,
+ wi1+(withDescript ? wi0:0));
+ }
+ if (this.getShowOnTextField() == 'idAndDescription') {
+ this._neededTextFieldWidth += this._getTextWidth(this.getIdDescriptionSeparator());
+ }
+ this._neededTextFieldWidth += 8; /*Extra margins*/
+ var maxRows = this.getMaxVisibleRows(),
+ // Only assign room for the vertical scrollbar when needed
+ width = data.length > maxRows ? (new qx.ui.core.ScrollBar)._getScrollBarWidth():0,
+ colModel = this._list.getTableColumnModel(),
+ countVisible = 0;
+
+ // ##Only show headers if we have more than 1 column visible
+ for (col = 0; col < nCols; col++) {
+ if (colModel.isColumnVisible(col)) {
+ countVisible++;
+ }
+ }
+ var hasHeaders = countVisible > 1;
+ this._list.getPaneScroller(0).getHeader().setHeight(hasHeaders ? 'auto' : 1);
+
+ // ##Size each column
+ for (col = 0; col < nCols; col++) {
+ if (colModel.isColumnVisible(col)) {
+ var w = columnWidths[col];
+ if (hasHeaders) {
+ w = Math.max(w, this._getTextWidth(cols[col]));
+ }
+ w += 8;
+ this._list.setColumnWidth(col, w);
+ width += w;
+ }
+ }
+
+ // ##Final width and height
+ this._list.set({
+ width: width,
+ height: this._list.getRowHeight()*
+ Math.min(maxRows, (hasHeaders ? 1:0)+data.length)+2+(hasHeaders ? 2:0)
+ });
+ // This denotes dimensions are already calculated
+ this._calcDimensions = true;
+}
+
+/**Calculates the width of the given text.
+ * The default font is used.
+ * @return {integer}*/
+qx.Proto._getTextWidth = function(text) {
+ var lab = new qx.ui.basic.Label(text);
+ var res = lab.getPreferredBoxWidth();
+ lab.dispose();
+ return res;
+}
+
+
+/*
+---------------------------------------------------------------------------
+ SEARCHING
+---------------------------------------------------------------------------
+*/
+
+/**Does this combo have the searched dialog open?*/
+qx.Proto.isSearchInProgress = function() {
+ return !this._popup.contains(this._list);
+}
+
+/**Searches the given text. Called from the search dialog.
+ * @param startIndex {Number} Start index, 0 based
+ * @param txt {String} Text to find
+ * @param caseSens {Boolean} Case sensivity flag.*/
+qx.Proto._search = function(startIndex, txt, caseSens) {
+ if (txt == null || !txt.length) {
+ return;
+ }
+ var row = startIndex,
+ nCols = this._model.getColumnCount(),
+ nRows = this.getSelection().length,
+ data = this._model.getData();
+ if (!caseSens) {
+ txt = txt.toLowerCase();
+ }
+ var colModel = this._list.getTableColumnModel();
+ while (true) {
+ var dataRow = data[row];
+ if (dataRow) {
+ for (var col = 0; col < nCols; col++) {
+ if (colModel.isColumnVisible(col)) {
+ var txtCol = dataRow[col];
+ if (!caseSens) {
+ txtCol = txtCol.toLowerCase();
+ }
+ if (txtCol.indexOf(txt) >= 0) {
+ this._manager.setSelectionInterval(row, row);
+ this._list.scrollCellVisible(1, row);
+ return;
+ }
+ }
+ }
+ }
+ row = (row+1)% nRows;
+ if (row == startIndex) {
+ break;
+ }
+ }
+}
+
+/**Opens a popup search dialog, useful when the combo has a lot of items.
+ * This dialog is triggered by double clicking the combo, pressing F3 or Ctrl+F.*/
+qx.Proto.openSearchDialog = function() {
+ var sel = this.getSelection();
+ if (!sel || !sel.length || this.isSearchInProgress()) {
+ return;
+ }
+ this._testClosePopup();
+
+ var me = this,
+ oldSelectedIndex = this.getSelectedIndex(),
+ startIndex = oldSelectedIndex;
+
+ //###searchField
+ function search() {
+ me._search(startIndex, searchField.getComputedValue(), checkCase.isChecked());
+ }
+ var searchField = new qx.ui.form.TextField;
+ searchField.set({
+ minWidth: this._field.getWidth(),
+ width: '100%'
+ });
+ searchField.addEventListener("input", function() {
+ search();
+ });
+
+ //###checkCase
+ var checkCase = new qx.ui.form.CheckBox(this._getComboSetting('caseSensitiveCaption'));
+ checkCase.set({
+ horizontalAlign: 'center',
+ marginBottom: 4
+ });
+
+ //###vbox
+ var vbox = new qx.ui.layout.VerticalBoxLayout;
+ vbox.set({
+ spacing: 6,
+ horizontalChildrenAlign: 'center',
+ height: '100%'
+ });
+ vbox.auto();
+ vbox.add(searchField, checkCase);
+
+ //###list, we reuse the same list in the popup
+ this._calculateDimensions();
+ var border = qx.renderer.border.BorderPresets.getInstance().inset;
+ var newListSettings = {
+ /*minHeight: border.getTopWidth()+this._list.getHeight()+border.getBottomWidth(),
+ height: '1*',*/
+ height: border.getTopWidth()+this._list.getHeight()+border.getBottomWidth(),
+ width: border.getLeftWidth()+this._list.getWidth()+border.getRightWidth(),
+ border: border,
+ parent: vbox
+ };
+ // Save old list settings
+ var oldListSettings = {};
+ for (var prop in newListSettings) {
+ oldListSettings[prop] = this._list[qx.OO.getter[prop]]();
+ }
+ this._list.set(newListSettings);
+
+ //###buttons
+ var butNext = new qx.ui.form.Button('', 'icon/16/find.png');
+ butNext.set({
+ toolTip: new qx.ui.popup.ToolTip(this._getComboSetting('toolTipSearchNext'))
+ });
+ butNext.addEventListener("execute", function() {
+ startIndex = (this.getSelectedIndex()+1) % sel.length;
+ search();
+ }, this);
+
+ var butOk = new qx.ui.form.Button('', 'icon/16/button-ok.png');
+ butOk.addEventListener('execute', function() {
+ oldSelectedIndex = null;
+ win.close();
+ }, this);
+
+ var butCancel = new qx.ui.form.Button('', 'icon/16/button-cancel.png');
+ butCancel.addEventListener('execute', function() {
+ win.close();
+ }, this);
+
+ var butBox = new qx.ui.layout.VerticalBoxLayout;
+ butBox.auto();
+ butBox.set({
+ spacing: 10
+ });
+ butBox.add(butNext, butOk, butCancel);
+
+ //###hbox
+ var hbox = new qx.ui.layout.BoxLayout;
+ hbox.auto();
+ hbox.setPadding(10);
+ hbox.set({
+ spacing: 8,
+ minHeight: 'auto',
+ height: '100%'
+ });
+ hbox.add(vbox, butBox);
+
+ //###Window
+ var win = new qx.ui.window.Window(this._getComboSetting('titleSearch'), 'icon/16/find.png');
+ win.add(hbox);
+ win.positionRelativeTo(this);
+ win.set({
+ autoHide: true,
+ allowMaximize: false,
+ showMaximize: false,
+ allowMinimize: false,
+ showMinimize: false
+ });
+ win.addEventListener("appear", function() {
+ searchField.focus();
+ });
+ win.addEventListener("disappear", function() {
+ if (oldSelectedIndex != null) {
+ // Hit Cancel button
+ this.setSelectedIndex(oldSelectedIndex);
+ }
+ this._list.set(oldListSettings);
+ this.focus();
+ }, this);
+ win.addEventListener("keydown", function(e) {
+ switch (e.getKeyIdentifier()) {
+ case "Enter":
+ butOk.createDispatchEvent('execute');
+ break;
+ case "Escape":
+ butCancel.createDispatchEvent('execute');
+ break;
+ case "F3":
+ butNext.createDispatchEvent('execute');
+ break;
+ default:
+ return;
+ }
+ e.preventDefault();
+ }, this);
+ win.auto();
+ win.addToDocument();
+ win.open();
+}
+
+/*
+---------------------------------------------------------------------------
+ OTHER EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onChangeSelection = function(e) {
+ this._fromSelected = true;
+
+ // only do this if we called setValue separately
+ // and not from the event "input".
+ if (!this._fromInput) {
+ var index = this.getSelectedIndex();
+ if (index >= 0) {
+ var row = this._model.getData()[index];
+ }
+ if (row || !this.getEditable()) {
+ this.setValue(row && row[0]);
+ }
+ // In case of editable, this.setValue() already calls this._field.setValue()
+ if (!this.getEditable()) {
+ var val = "";
+ if (row) {
+ val = this.getShowOnTextField() == 'description' ?
+ row[1] :
+ (row[0] != null && row[0] != '' ? row[0] + this.getIdDescriptionSeparator() + row[1]:row[1]);
+ }
+ this._field.setValue(val);
+ }
+ }
+ // reset hint
+ delete this._fromSelected;
+}
+
+qx.Proto._onpopupappear = function(e) {
+ var index = this.getSelectedIndex();
+ if (index >= 0) {
+ this._list.scrollCellVisible(0, index);
+ }
+}
+
+qx.Proto._oninput = function(e) {
+ // Hint for modifier
+ this._fromInput = true;
+ this.setValue(this._field.getComputedValue());
+ delete this._fromInput;
+}
+
+
+/*
+---------------------------------------------------------------------------
+ MOUSE EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousedown = function(e) {
+ switch(e.getTarget()) {
+ case this._field:
+ if (this.getEditable()) {
+ break;
+ }
+ // no break here
+ case this._button:
+ this._button.addState("pressed");
+ this._togglePopup();
+ // Assure we receive the mouse up event
+ this.setCapture(true);
+ break;
+ }
+}
+
+qx.Proto._onmouseup = function(e) {
+ switch(e.getTarget()) {
+ case this._field:
+ if (this.getEditable()) {
+ break;
+ }
+ // no break here
+ default:
+ this._button.removeState("pressed");
+ break;
+ }
+ this.setCapture(false);
+}
+
+qx.Proto._onmousewheel = function(e) {
+ if (!this._popup.isSeeable()) {
+ this.setSelectedIndex(Math.max(0, this.getSelectedIndex()+(e.getWheelDelta() < 0 ? -1:1)));
+ }
+}
+
+
+/*
+---------------------------------------------------------------------------
+ KEY EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeydown = function(e) {
+ var vVisible = this._popup.isSeeable();
+
+ switch (e.getKeyIdentifier()) {
+ case "Enter":
+ if (vVisible) {
+ this._closePopup();
+ this.setFocused(true);
+ } else {
+ this._openPopup();
+ }
+ break;
+
+ case "Escape":
+ if (vVisible) {
+ this.setSelectedIndex(this._oldSelected);
+ this._closePopup();
+ this.setFocused(true);
+ }
+ break;
+
+ case "Home":
+ this.setSelectedIndex(0);
+ break;
+
+ case "End":
+ var items = this.getSelection().length;
+ if (items) {
+ this.setSelectedIndex(items-1);
+ }
+ break;
+
+ case "Down":
+ if (e.getAltKey()) {
+ this._togglePopup();
+ }
+ break;
+
+ case "F3":
+ if (this.getAllowSearch()) {
+ this.openSearchDialog();
+ }
+ break;
+
+ case "F":
+ if (e.getCtrlKey()) {
+ if (this.getAllowSearch()) {
+ this.openSearchDialog();
+ }
+ break;
+ }
+ return;
+
+ default:
+ if (vVisible) {
+ this._list.dispatchEvent(e);
+ }
+ return;
+ }
+ e.preventDefault();
+}
+
+
+qx.Proto._onkeypress = function(e) {
+ var vVisible = this._popup.isSeeable();
+
+ switch (e.getKeyIdentifier()) {
+ case "Up":
+ this.setSelectedIndex(Math.max(0, this.getSelectedIndex()-1));
+ break;
+
+ case "Down":
+ this.setSelectedIndex(Math.max(0, this.getSelectedIndex()+1));
+ break;
+
+ case "PageUp":
+ this.setSelectedIndex(Math.max(0, this.getSelectedIndex()-this.getPagingInterval()));
+ break;
+
+ case "PageDown":
+ this.setSelectedIndex(this.getSelectedIndex()+this.getPagingInterval());
+ break;
+
+ default:
+ if (vVisible) {
+ this._list.dispatchEvent(e);
+ }
+ return;
+ }
+ e.preventDefault();
+
+ if (!this.isEditable() && this._list.isSeeable()) {
+ this._list.dispatchEvent(e);
+ }
+
+}
+
+
+/*
+---------------------------------------------------------------------------
+ FOCUS HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._visualizeBlur = function() {
+ // Force blur, even if mouseFocus is not active because we
+ // need to be sure that the previous focus rect gets removed.
+ // But this only needs to be done, if there is no new focused element.
+ if (qx.sys.Client.getInstance().isMshtml()) {
+ if (this.getEnableElementFocus() && !this.getFocusRoot().getFocusedChild()) {
+ try {
+ if (this.getEditable()) {
+ this.getField().getElement().blur();
+ } else {
+ this.getElement().blur();
+ }
+ }
+ catch(ex) {};
+ }
+ } else {
+ if (this.getEnableElementFocus()) {
+ try {
+ if (this.getEditable()) {
+ this.getField().getElement().blur();
+ } else if (!this.getFocusRoot().getFocusedChild()) {
+ this.getElement().blur();
+ }
+ }
+ catch(ex) {};
+ }
+ }
+ this.removeState("focused");
+ return true;
+}
+
+qx.Proto._visualizeFocus = function() {
+ if (!qx.event.handler.FocusHandler.mouseFocus && this.getEnableElementFocus()) {
+ try {
+ if (this.getEditable()) {
+ this.getField().getElement().focus();
+ this.getField()._ontabfocus();
+ } else {
+ this.getElement().focus();
+ }
+ } catch(ex) {
+ }
+ }
+ this.addState("focused");
+ return true;
+}
+
+/*
+---------------------------------------------------------------------------
+ DISPOSE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return;
+ }
+
+ // ************************************************************************
+ // WIDGET MOUSE EVENTS
+ // ************************************************************************
+ this.removeEventListener("mousedown", this._onmousedown);
+ this.removeEventListener("mouseup", this._onmouseup);
+ this.removeEventListener("mousewheel", this._onmousewheel);
+
+
+ // ************************************************************************
+ // WIDGET KEY EVENTS
+ // ************************************************************************
+ this.removeEventListener("keydown", this._onkeydown);
+ this.removeEventListener("keypress", this._onkeypress);
+
+
+ this._model = null;
+ if (this._manager) {
+ this._manager.removeEventListener('changeSelection', this._onChangeSelection);
+ this._manager = null;
+ }
+ if (this._list) {
+ this._list.dispose();
+ this._list = null;
+ }
+ if (this._popup) {
+ this._popup.removeEventListener("appear", this._onpopupappear, this);
+ this._popup.dispose();
+ this._popup = null;
+ }
+ if (this._field) {
+ if (this.getEditable()) {
+ this._field.removeEventListener("input", this._oninput, this);
+ }
+ this._field.dispose();
+ this._field = null;
+ }
+ if (this._button) {
+ this._button.dispose();
+ this._button = null;
+ }
+ return qx.ui.layout.HorizontalBoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/InputCheckSymbol.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/InputCheckSymbol.js
new file mode 100644
index 0000000000..a7acf6f65a
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/InputCheckSymbol.js
@@ -0,0 +1,93 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_form)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.form.InputCheckSymbol", qx.ui.basic.Terminator,
+function()
+{
+ qx.ui.basic.Terminator.call(this);
+
+ this.setTagName("input");
+ this.setSelectable(false);
+
+ if (qx.sys.Client.getInstance().isMshtml())
+ {
+ // Take control over size of element (mshtml)
+ this.setWidth(13);
+ this.setHeight(13);
+ }
+ else if (qx.sys.Client.getInstance().isGecko())
+ {
+ // Remove gecko default margin
+ this.setMargin(0);
+ }
+
+ // we need to be sure that the dom protection of this is added
+ this.forceTabIndex(1);
+ this.setTabIndex(-1);
+ this.setChecked(false);
+});
+
+qx.OO.addProperty({ name : "name", type : "string", impl : "apply" });
+qx.OO.addProperty({ name : "value", impl : "apply" });
+qx.OO.addProperty({ name : "type", impl : "apply" });
+qx.OO.addProperty({ name : "checked", type : "boolean", impl : "apply", getAlias : "isChecked" });
+
+qx.Proto._modifyApply = function(propValue, propOldValue, propData) {
+ return this.setHtmlProperty(propData.name, propValue);
+}
+
+qx.Proto.getPreferredBoxWidth = function() {
+ return 13;
+}
+
+qx.Proto.getPreferredBoxHeight = function() {
+ return 13;
+}
+
+qx.Proto.getBoxWidth = qx.Proto.getPreferredBoxWidth;
+qx.Proto.getBoxHeight = qx.Proto.getPreferredBoxHeight;
+
+qx.Proto.getInnerWidth = qx.Proto.getPreferredBoxWidth;
+qx.Proto.getInnerHeight = qx.Proto.getPreferredBoxHeight;
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._afterAppear = function()
+ {
+ qx.ui.basic.Terminator.prototype._afterAppear.call(this);
+
+ var vElement = this.getElement();
+ vElement.checked = this.getChecked();
+
+ if (!this.getEnabled()) {
+ vElement.disabled = true;
+ }
+ }
+}
+
+qx.Proto._modifyEnabled = function(propValue, propOldValue, propData)
+{
+ propValue ? this.removeHtmlAttribute("disabled") : this.setHtmlAttribute("disabled", "disabled");
+ return qx.ui.basic.Terminator.prototype._modifyEnabled.call(this, propValue, propOldValue, propData);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/List.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/List.js
new file mode 100644
index 0000000000..da58b6a960
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/List.js
@@ -0,0 +1,383 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_form)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.form.List", qx.ui.layout.VerticalBoxLayout,
+function()
+{
+ qx.ui.layout.VerticalBoxLayout.call(this);
+
+
+ // ************************************************************************
+ // INITILISIZE MANAGER
+ // ************************************************************************
+ this._manager = new qx.manager.selection.SelectionManager(this);
+
+
+ // ************************************************************************
+ // BEHAVIOR
+ // ************************************************************************
+ this.setSelectable(false);
+ this.setTabIndex(1);
+
+
+ // ************************************************************************
+ // MOUSE EVENT LISTENER
+ // ************************************************************************
+ this.addEventListener("mouseover", this._onmouseover);
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+ this.addEventListener("click", this._onclick);
+ this.addEventListener("dblclick", this._ondblclick);
+
+
+ // ************************************************************************
+ // KEY EVENT LISTENER
+ // ************************************************************************
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keypress", this._onkeypress);
+ this.addEventListener("keyinput", this._onkeyinput);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list" });
+
+qx.OO.addProperty({ name : "enableInlineFind", type : "boolean", defaultValue : true });
+qx.OO.addProperty({ name : "markLeadingItem", type : "boolean", defaultValue : false });
+
+qx.Proto._pressedString = "";
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MANAGER BINDING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getManager = function() {
+ return this._manager;
+}
+
+qx.Proto.getListItemTarget = function(vItem)
+{
+ while (vItem != null && vItem.getParent() != this) {
+ vItem = vItem.getParent();
+ }
+
+ return vItem;
+}
+
+qx.Proto.getSelectedItem = function() {
+ return this.getSelectedItems()[0];
+}
+
+qx.Proto.getSelectedItems = function() {
+ return this._manager.getSelectedItems();
+}
+
+
+
+/*
+---------------------------------------------------------------------------
+ MOUSE EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmouseover = function(e)
+{
+ var vItem = this.getListItemTarget(e.getTarget());
+
+ if (vItem) {
+ this._manager.handleMouseOver(vItem, e);
+ }
+}
+
+qx.Proto._onmousedown = function(e)
+{
+ var vItem = this.getListItemTarget(e.getTarget());
+
+ if (vItem) {
+ this._manager.handleMouseDown(vItem, e);
+ }
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ var vItem = this.getListItemTarget(e.getTarget());
+
+ if (vItem) {
+ this._manager.handleMouseUp(vItem, e);
+ }
+}
+
+qx.Proto._onclick = function(e)
+{
+ var vItem = this.getListItemTarget(e.getTarget());
+
+ if (vItem) {
+ this._manager.handleClick(vItem, e);
+ }
+}
+
+qx.Proto._ondblclick = function(e)
+{
+ var vItem = this.getListItemTarget(e.getTarget());
+
+ if (vItem) {
+ this._manager.handleDblClick(vItem, e);
+ }
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ KEY EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeydown = function(e)
+{
+ // Execute action on press
+ if (e.getKeyIdentifier() == "Enter" && !e.getAltKey())
+ {
+ var items = this.getSelectedItems();
+ var currentItem;
+
+ for (var i=0; i 1000) {
+ this._pressedString = "";
+ }
+
+ // Combine keys the user pressed to a string
+ this._pressedString += String.fromCharCode(e.getCharCode());
+
+ // Find matching item
+ var matchedItem = this.findString(this._pressedString, null);
+
+ if (matchedItem)
+ {
+ var oldVal = this._manager._getChangeValue();
+
+ // Temporary disable change event
+ var oldFireChange = this._manager.getFireChange();
+ this._manager.setFireChange(false);
+
+ // Reset current selection
+ this._manager._deselectAll();
+
+ // Update manager
+ this._manager.setItemSelected(matchedItem, true);
+ this._manager.setAnchorItem(matchedItem);
+ this._manager.setLeadItem(matchedItem);
+
+ // Scroll to matched item
+ matchedItem.scrollIntoView();
+
+ // Recover event status
+ this._manager.setFireChange(oldFireChange);
+
+ // Dispatch event if there were any changes
+ if (oldFireChange && this._manager._hasChanged(oldVal)) {
+ this._manager._dispatchChange();
+ }
+ }
+
+ // Store timestamp
+ this._lastKeyPress = (new Date).valueOf();
+ e.preventDefault();
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ FIND SUPPORT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._findItem = function(vUserValue, vStartIndex, vType)
+{
+ var vAllItems = this.getChildren();
+
+ // If no startIndex given try to get it by current selection
+ if (vStartIndex == null)
+ {
+ vStartIndex = vAllItems.indexOf(this.getSelectedItem());
+
+ if (vStartIndex == -1) {
+ vStartIndex = 0;
+ }
+ }
+
+ var methodName = "matches" + vType;
+
+ // Mode #1: Find all items after the startIndex
+ for (var i=vStartIndex; i= "0" && vIdentifier <= "9") {
+ return;
+ }
+
+ e.preventDefault();
+ }
+ }
+}
+
+qx.Proto._onkeydown = function(e)
+{
+ var vIdentifier = e.getKeyIdentifier();
+
+ if (this._intervalIncrease == null)
+ {
+ switch(vIdentifier)
+ {
+ case "Up":
+ case "Down":
+ this._intervalIncrease = vIdentifier == "Up";
+ this._intervalMode = "single";
+
+ this._resetIncrements();
+ this._checkValue(true, false, false);
+
+ this._increment();
+ this._timer.startWith(this.getFirstInterval());
+
+ break;
+
+ case "PageUp":
+ case "PageDown":
+ this._intervalIncrease = vIdentifier == "PageUp";
+ this._intervalMode = "page";
+
+ this._resetIncrements();
+ this._checkValue(true, false, false);
+
+ this._pageIncrement();
+ this._timer.startWith(this.getFirstInterval());
+
+ break;
+ }
+ }
+}
+
+qx.Proto._onkeyup = function(e)
+{
+ if (this._intervalIncrease != null)
+ {
+ switch(e.getKeyIdentifier())
+ {
+ case "Up":
+ case "Down":
+ case "PageUp":
+ case "PageDown":
+ this._timer.stop();
+
+ this._intervalIncrease = null;
+ this._intervalMode = null;
+ }
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MOUSE EVENT-HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousedown = function(e)
+{
+ if (!e.isLeftButtonPressed()) {
+ return;
+ }
+
+ this._checkValue(true);
+
+ var vButton = e.getCurrentTarget();
+
+ vButton.addState("pressed");
+
+ vButton.addEventListener("mouseup", this._onmouseup, this);
+ vButton.addEventListener("mouseout", this._onmouseup, this);
+
+ this._intervalIncrease = vButton == this._upbutton;
+ this._resetIncrements();
+ this._increment();
+
+ this._textfield.selectAll();
+
+ this._timer.setInterval(this.getFirstInterval());
+ this._timer.start();
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ var vButton = e.getCurrentTarget();
+
+ vButton.removeState("pressed");
+
+ vButton.removeEventListener("mouseup", this._onmouseup, this);
+ vButton.removeEventListener("mouseout", this._onmouseup, this);
+
+ this._textfield.selectAll();
+ this._textfield.setFocused(true);
+
+ this._timer.stop();
+ this._intervalIncrease = null;
+}
+
+qx.Proto._onmousewheel = function(e)
+{
+ this._manager.setValue(this._manager.getValue() + this.getWheelIncrementAmount() * e.getWheelDelta());
+ this._textfield.selectAll();
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ OTHER EVENT-HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._oninput = function(e) {
+ this._checkValue(true, true);
+}
+
+qx.Proto._onchange = function(e)
+{
+ var vValue = this._manager.getValue();
+
+ this._textfield.setValue(String(vValue));
+
+ if (vValue == this.getMin())
+ {
+ this._downbutton.removeState("pressed");
+ this._downbutton.setEnabled(false);
+ this._timer.stop();
+ }
+ else
+ {
+ this._downbutton.setEnabled(true);
+ }
+
+ if (vValue == this.getMax())
+ {
+ this._upbutton.removeState("pressed");
+ this._upbutton.setEnabled(false);
+ this._timer.stop();
+ }
+ else
+ {
+ this._upbutton.setEnabled(true);
+ }
+
+ if (this.hasEventListeners("change")) {
+ this.dispatchEvent(new qx.event.type.Event("change"), true);
+ }
+}
+
+qx.Proto._onblur = function(e) {
+ this._checkValue(false);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MAPPING TO RANGE MANAGER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.setValue = function(nValue) {
+ this._manager.setValue(nValue);
+}
+
+qx.Proto.getValue = function() {
+ this._checkValue(true);
+ return this._manager.getValue();
+}
+
+qx.Proto.resetValue = function() {
+ return this._manager.resetValue();
+}
+
+qx.Proto.setMax = function(vMax) {
+ return this._manager.setMax(vMax);
+}
+
+qx.Proto.getMax = function() {
+ return this._manager.getMax();
+}
+
+qx.Proto.setMin = function(vMin) {
+ return this._manager.setMin(vMin);
+}
+
+qx.Proto.getMin = function() {
+ return this._manager.getMin();
+}
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INTERVAL HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._intervalIncrease = null;
+
+qx.Proto._oninterval = function(e)
+{
+ this._timer.stop();
+ this.setInterval(Math.max(this.getMinTimer(), this.getInterval()-this.getTimerDecrease()));
+
+ if (this._intervalMode == "page")
+ {
+ this._pageIncrement();
+ }
+ else
+ {
+ if (this.getInterval() == this.getMinTimer()) {
+ this.setIncrementAmount(this.getAmountGrowth() * this.getIncrementAmount());
+ }
+
+ this._increment();
+ }
+
+ switch(this._intervalIncrease)
+ {
+ case true:
+ if (this.getValue() == this.getMax()) {
+ return;
+ }
+
+ case false:
+ if (this.getValue() == this.getMin()) {
+ return;
+ }
+ }
+
+ this._timer.restartWith(this.getInterval());
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITY
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._checkValue = function(acceptEmpty, acceptEdit)
+{
+ var el = this._textfield.getElement();
+
+ if (!el) {
+ return;
+ }
+
+ if (el.value == "")
+ {
+ if (!acceptEmpty)
+ {
+ el.value = this.resetValue();
+ this._textfield.selectAll();
+
+ return;
+ }
+ }
+ else
+ {
+ // cache working variable
+ var val = el.value;
+
+ // fix leading '0'
+ if (val.length > 1)
+ {
+ while(val.charAt(0) == "0") {
+ val = val.substr(1, val.length);
+ }
+
+ var f1 = parseInt(val) || 0;
+
+ if (f1 != el.value) {
+ el.value = f1;
+ return;
+ }
+ }
+
+ // fix for negative integer handling
+ if (val == "-" && acceptEmpty && this.getMin() < 0)
+ {
+ if (el.value != val) {
+ el.value = val;
+ }
+
+ return;
+ }
+
+ // parse the string
+ val = parseInt(val);
+
+ // main check routine
+ var doFix = true;
+ var fixedVal = this._manager._checkValue(val);
+
+ if (isNaN(fixedVal)) {
+ fixedVal = this._manager.getValue();
+ }
+
+ // handle empty string
+ if (acceptEmpty && val == "")
+ {
+ doFix = false;
+ }
+ else if (!isNaN(val))
+ {
+ // check for editmode in keypress events
+ if (acceptEdit)
+ {
+ // fix min/max values
+ if (val > fixedVal && !(val > 0 && fixedVal <= 0) && String(val).length < String(fixedVal).length)
+ {
+ doFix = false;
+ }
+ else if (val < fixedVal && !(val < 0 && fixedVal >= 0) && String(val).length < String(fixedVal).length)
+ {
+ doFix = false;
+ }
+ }
+ }
+
+ // apply value fix
+ if (doFix && el.value != fixedVal) {
+ el.value = fixedVal;
+ }
+
+ // inform manager
+ if (!acceptEdit) {
+ this._manager.setValue(fixedVal);
+ }
+ }
+}
+
+qx.Proto._increment = function() {
+ this._manager.setValue(this._manager.getValue() + ((this._intervalIncrease ? 1 : - 1) * this.getIncrementAmount()));
+}
+
+qx.Proto._pageIncrement = function() {
+ this._manager.setValue(this._manager.getValue() + ((this._intervalIncrease ? 1 : - 1) * this.getPageIncrementAmount()));
+}
+
+qx.Proto._resetIncrements = function()
+{
+ this.resetIncrementAmount();
+ this.resetInterval();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this.removeEventListener("keypress", this._onkeypress, this);
+ this.removeEventListener("keydown", this._onkeydown, this);
+ this.removeEventListener("keyup", this._onkeyup, this);
+ this.removeEventListener("mousewheel", this._onmousewheel, this);
+
+ if (this._textfield)
+ {
+ this._textfield.removeEventListener("blur", this._onblur, this);
+ this._textfield.removeEventListener("input", this._oninput, this);
+ this._textfield.dispose();
+ this._textfield = null;
+ }
+
+ if (this._buttonlayout)
+ {
+ this._buttonlayout.dispose();
+ this._buttonlayout = null;
+ }
+
+ if (this._upbutton)
+ {
+ this._upbutton.removeEventListener("mousedown", this._onmousedown, this);
+ this._upbutton.dispose();
+ this._upbutton = null;
+ }
+
+ if (this._downbutton)
+ {
+ this._downbutton.removeEventListener("mousedown", this._onmousedown, this);
+ this._downbutton.dispose();
+ this._downbutton = null;
+ }
+
+ if (this._timer)
+ {
+ this._timer.removeEventListener("interval", this._oninterval, this);
+ this._timer.stop();
+ this._timer.dispose();
+ this._timer = null;
+ }
+
+ if (this._manager)
+ {
+ this._manager.removeEventListener("change", this._onchange, this);
+ this._manager.dispose();
+ this._manager = null;
+ }
+
+ return qx.ui.layout.HorizontalBoxLayout.prototype.dispose.call(this);
+}
\ No newline at end of file
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/TextArea.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/TextArea.js
new file mode 100644
index 0000000000..5796713417
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/TextArea.js
@@ -0,0 +1,53 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_form)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.form.TextArea", qx.ui.form.TextField,
+function(vValue)
+{
+ qx.ui.form.TextField.call(this, vValue);
+
+ this.setTagName("textarea");
+ this.removeHtmlProperty("type");
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "text-area" });
+
+qx.OO.addProperty({ name : "wrap", type : "boolean" });
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._modifyWrap = function(propValue, propOldValue, propData) {
+ return this.setStyleProperty("whiteSpace", propValue ? "normal" : "nowrap");
+ }
+}
+else
+{
+ qx.Proto._modifyWrap = function(propValue, propOldValue, propData) {
+ return this.setHtmlProperty("wrap", propValue ? "soft" : "off");
+ }
+}
+
+qx.Proto._computePreferredInnerHeight = function() {
+ return 60;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/TextField.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/TextField.js
new file mode 100644
index 0000000000..8ab7005128
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/TextField.js
@@ -0,0 +1,538 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_form)
+#require(qx.renderer.font.FontCache)
+#after(qx.renderer.font.FontObject)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.form.TextField", qx.ui.basic.Terminator,
+function(vValue)
+{
+ // ************************************************************************
+ // INIT
+ // ************************************************************************
+ qx.ui.basic.Terminator.call(this);
+
+ if (typeof vValue === "string") {
+ this.setValue(vValue);
+ }
+
+
+ // ************************************************************************
+ // BEHAVIOR
+ // ************************************************************************
+ this.setTagName("input");
+ this.setHtmlProperty("type", "text");
+ this.setHtmlAttribute("autocomplete", "OFF");
+ this.setTabIndex(1);
+ this.setSelectable(true);
+
+
+ // ************************************************************************
+ // EVENTS
+ // ************************************************************************
+ this.enableInlineEvent("input");
+
+ this.addEventListener("blur", this._onblur);
+ this.addEventListener("focus", this._onfocus);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "text-field" });
+
+qx.OO.addProperty({ name : "value", type : "string", defaultValue : "" });
+qx.OO.addProperty({ name : "maxLength", type : "number" });
+qx.OO.addProperty({ name : "readOnly", type : "boolean" });
+
+qx.OO.addProperty({ name : "selectionStart", type : "number" });
+qx.OO.addProperty({ name : "selectionLength", type : "number" });
+qx.OO.addProperty({ name : "selectionText", type : "string" });
+
+qx.OO.addProperty({ name : "validator", type : "function" });
+
+/*!
+ The font property describes how to paint the font on the widget.
+*/
+qx.OO.addProperty({ name : "font", type : "object", instance : "qx.renderer.font.Font", convert : qx.renderer.font.FontCache, allowMultipleArguments : true });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CLONING
+---------------------------------------------------------------------------
+*/
+
+// Extend ignore list with selection properties
+qx.Proto._clonePropertyIgnoreList += ",selectionStart,selectionLength,selectionText";
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyEnabled = function(propValue, propOldValue, propData)
+{
+ propValue ? this.removeHtmlAttribute("disabled") : this.setHtmlAttribute("disabled", "disabled");
+ return qx.ui.basic.Terminator.prototype._modifyEnabled.call(this, propValue, propOldValue, propData);
+}
+
+qx.Proto._modifyValue = function(propValue, propOldValue, propData)
+{
+ this._inValueProperty = true;
+ this.setHtmlProperty(propData.name, propValue == null ? "" : propValue);
+ delete this._inValueProperty;
+
+ return true;
+}
+
+qx.Proto._modifyMaxLength = function(propValue, propOldValue, propData) {
+ return propValue ? this.setHtmlProperty(propData.name, propValue) : this.removeHtmlProperty(propData.name);
+}
+
+qx.Proto._modifyReadOnly = function(propValue, propOldValue, propData) {
+ return propValue ? this.setHtmlProperty(propData.name, propData.name) : this.removeHtmlProperty(propData.name);
+}
+
+qx.Proto._modifyFont = function(propValue, propOldValue, propData)
+{
+ this._invalidatePreferredInnerDimensions();
+
+ if (propValue) {
+ propValue._applyWidget(this);
+ } else if (propOldValue) {
+ propOldValue._resetWidget(this);
+ }
+
+ return true;
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getComputedValue = function(e)
+{
+ this._visualPropertyCheck();
+ return this.getElement().value;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ VALIDATION
+---------------------------------------------------------------------------
+*/
+
+qx.ui.form.TextField.createRegExpValidator = function(vRegExp)
+{
+ return function(s) {
+ return vRegExp.test(s);
+ }
+}
+
+qx.Proto.isValid = function()
+{
+ var vValidator = this.getValidator();
+ return !vValidator || vValidator(this.getValue());
+}
+
+qx.Proto.isComputedValid = function()
+{
+ var vValidator = this.getValidator();
+ return !vValidator || vValidator(this.getComputedValue());
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PREFERRED DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computePreferredInnerWidth = function() {
+ return 120;
+}
+
+qx.Proto._computePreferredInnerHeight = function() {
+ return 15;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ BROWSER QUIRKS
+---------------------------------------------------------------------------
+*/
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._firstInputFixApplied = false;
+
+ qx.Proto._afterAppear = function()
+ {
+ qx.ui.basic.Terminator.prototype._afterAppear.call(this);
+
+ if (!this._firstInputFixApplied) {
+ qx.client.Timer.once(this._ieFirstInputFix, this, 1);
+ }
+ }
+
+ /*!
+ Fix IE's input event for filled text fields
+ */
+ qx.Proto._ieFirstInputFix = function()
+ {
+ this._inValueProperty = true;
+ this.getElement().value = this.getValue() === null ? "" : this.getValue();
+ this._firstInputFixApplied = true;
+ delete this._inValueProperty;
+ }
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT-HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._textOnFocus = null;
+
+qx.Proto._ontabfocus = function(e) {
+ this.selectAll();
+}
+
+qx.Proto._onfocus = function(e) {
+ this._textOnFocus = this.getComputedValue();
+}
+
+qx.Proto._onblur = function(e)
+{
+ var vValue = this.getComputedValue().toString();
+
+ if (this._textOnFocus != vValue) {
+ this.setValue(vValue);
+ }
+
+ this.setSelectionLength(0);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CROSS-BROWSER SELECTION HANDLING
+---------------------------------------------------------------------------
+*/
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ /*!
+ Microsoft Documentation:
+ http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/createrange.asp
+ http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/obj_textrange.asp
+ */
+
+ qx.Proto._getRange = function()
+ {
+ this._visualPropertyCheck();
+ return this.getElement().createTextRange();
+ }
+
+ qx.Proto._getSelectionRange = function()
+ {
+ this._visualPropertyCheck();
+ return this.getTopLevelWidget().getDocumentElement().selection.createRange();
+ }
+
+ qx.Proto.setSelectionStart = function(vStart)
+ {
+ this._visualPropertyCheck();
+
+ var vText = this.getElement().value;
+
+ // a bit hacky, special handling for line-breaks
+ var i = 0;
+ while (i vOldLength)
+ {
+ for (var i=vOldLength; i vNewLength)
+ {
+ vData.splice(vNewLength, vOldLength - vNewLength);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ GRID SETUP: COLUMNS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._columnCount = 0;
+
+qx.Proto.setColumnCount = function(vCount)
+{
+ this._columnCount = vCount;
+ this._syncColumnDataFields();
+}
+
+qx.Proto.getColumnCount = function() {
+ return this._columnCount;
+}
+
+qx.Proto.addColumn = function()
+{
+ this._columnCount++;
+ this._syncColumnDataFields();
+}
+
+qx.Proto.removeColumn = function()
+{
+ if (this._columnCount > 0)
+ {
+ this._columnCount--;
+ this._syncColumnDataFields();
+ }
+}
+
+qx.Proto._syncColumnDataFields = function()
+{
+ var vData = this._columnData;
+ var vOldLength = vData.length;
+ var vNewLength = this._columnCount;
+
+ this._syncDataFields(vData, vOldLength, vNewLength);
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ GRID SETUP: ROWS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._rowCount = 0;
+
+qx.Proto.setRowCount = function(vCount)
+{
+ this._rowCount = vCount;
+ this._syncRowDataFields();
+}
+
+qx.Proto.getRowCount = function() {
+ return this._rowCount;
+}
+
+qx.Proto.addRow = function()
+{
+ this._rowCount++;
+ this._syncRowDataFields();
+}
+
+qx.Proto.removeRow = function()
+{
+ if (this._rowCount > 0)
+ {
+ this._rowCount--;
+ this._syncRowDataFields();
+ }
+}
+
+qx.Proto._syncRowDataFields = function()
+{
+ var vData = this._rowData;
+ var vOldLength = vData.length;
+ var vNewLength = this._rowCount;
+
+ this._syncDataFields(vData, vOldLength, vNewLength);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DATA HANDLING: COLUMNS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._getColumnProperty = function(vColumnIndex, vProperty)
+{
+ try
+ {
+ return this._columnData[vColumnIndex][vProperty] || null;
+ }
+ catch(ex)
+ {
+ this.error("Error while getting column property (" + vColumnIndex + "|" + vProperty + ")", ex);
+ return null;
+ }
+}
+
+qx.Proto._setupColumnProperty = function(vColumnIndex, vProperty, vValue)
+{
+ this._columnData[vColumnIndex][vProperty] = vValue;
+ this._invalidateColumnLayout();
+}
+
+qx.Proto._removeColumnProperty = function(vColumnIndex, vProperty, vValue)
+{
+ delete this._columnData[vColumnIndex][vProperty];
+ this._invalidateColumnLayout();
+}
+
+qx.Proto._invalidateColumnLayout = function()
+{
+ if (!this._initialLayoutDone || !this._isDisplayable) {
+ return;
+ }
+
+ this.forEachVisibleChild(function() {
+ this.addToQueue("width");
+ });
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DATA HANDLING: ROWS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._getRowProperty = function(vRowIndex, vProperty)
+{
+ try
+ {
+ return this._rowData[vRowIndex][vProperty] || null;
+ }
+ catch(ex)
+ {
+ this.error("Error while getting row property (" + vRowIndex + "|" + vProperty + ")", ex);
+ return null;
+ }
+}
+
+qx.Proto._setupRowProperty = function(vRowIndex, vProperty, vValue)
+{
+ this._rowData[vRowIndex][vProperty] = vValue;
+ this._invalidateRowLayout();
+}
+
+qx.Proto._removeRowProperty = function(vRowIndex, vProperty, vValue)
+{
+ delete this._rowData[vRowIndex][vProperty];
+ this._invalidateRowLayout();
+}
+
+qx.Proto._invalidateRowLayout = function()
+{
+ if (!this._initialLayoutDone || !this._isDisplayable) {
+ return;
+ }
+
+ this.forEachVisibleChild(function() {
+ this.addToQueue("height");
+ });
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES: CELL DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+// SETTER
+
+qx.Proto.setColumnWidth = function(vIndex, vValue)
+{
+ this._setupColumnProperty(vIndex, "widthValue", vValue);
+
+ var vType = qx.ui.core.Parent.prototype._evalUnitsPixelPercentAutoFlex(vValue);
+
+ this._setupColumnProperty(vIndex, "widthType", vType);
+
+ var vParsed, vComputed;
+
+ switch(vType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ vParsed = vComputed = Math.round(vValue);
+ break;
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ case qx.ui.core.Widget.TYPE_FLEX:
+ vParsed = parseFloat(vValue);
+ vComputed = null;
+ break;
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ vParsed = vComputed = null;
+ break;
+
+ default:
+ vParsed = vComputed = null;
+ }
+
+ this._setupColumnProperty(vIndex, "widthParsed", vParsed);
+ this._setupColumnProperty(vIndex, "widthComputed", vComputed);
+}
+
+qx.Proto.setRowHeight = function(vIndex, vValue)
+{
+ this._setupRowProperty(vIndex, "heightValue", vValue);
+
+ var vType = qx.ui.core.Widget.prototype._evalUnitsPixelPercentAutoFlex(vValue);
+ this._setupRowProperty(vIndex, "heightType", vType);
+
+ var vParsed, vComputed;
+
+ switch(vType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ vParsed = vComputed = Math.round(vValue);
+ break;
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ case qx.ui.core.Widget.TYPE_FLEX:
+ vParsed = parseFloat(vValue);
+ vComputed = null;
+ break;
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ vParsed = vComputed = null;
+ break;
+
+ default:
+ vParsed = vComputed = null;
+ }
+
+ this._setupRowProperty(vIndex, "heightParsed", vParsed);
+ this._setupRowProperty(vIndex, "heightComputed", vComputed);
+}
+
+
+
+// GETTER: BOX
+
+qx.Proto.getColumnBoxWidth = function(vIndex)
+{
+ var vComputed = this._getColumnProperty(vIndex, "widthComputed");
+
+ if (vComputed != null) {
+ return vComputed;
+ }
+
+ var vType = this._getColumnProperty(vIndex, "widthType");
+ var vParsed = this._getColumnProperty(vIndex, "widthParsed");
+ var vComputed = null;
+
+ switch(vType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ vComputed = Math.max(0, vParsed);
+ break;
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ vComputed = this.getInnerWidth() * Math.max(0, vParsed) * 0.01;
+ break;
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ // TODO
+ vComputed = null;
+ break;
+
+ case qx.ui.core.Widget.TYPE_FLEX:
+ // TODO
+ vComputed = null;
+ break;
+ }
+
+ this._setupColumnProperty(vIndex, "widthComputed", vComputed);
+ return vComputed;
+}
+
+qx.Proto.getRowBoxHeight = function(vIndex)
+{
+ var vComputed = this._getRowProperty(vIndex, "heightComputed");
+
+ if (vComputed != null) {
+ return vComputed;
+ }
+
+ var vType = this._getRowProperty(vIndex, "heightType");
+ var vParsed = this._getRowProperty(vIndex, "heightParsed");
+ var vComputed = null;
+
+ switch(vType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ vComputed = Math.max(0, vParsed);
+ break;
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ vComputed = this.getInnerHeight() * Math.max(0, vParsed) * 0.01;
+ break;
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ // TODO
+ vComputed = null;
+ break;
+
+ case qx.ui.core.Widget.TYPE_FLEX:
+ // TODO
+ vComputed = null;
+ break;
+ }
+
+ this._setupRowProperty(vIndex, "heightComputed", vComputed);
+ return vComputed;
+}
+
+
+// GETTER: PADDING
+
+qx.Proto.getComputedCellPaddingLeft = function(vCol, vRow) {
+ return this.getColumnPaddingLeft(vCol) || this.getRowPaddingLeft(vRow) || this.getCellPaddingLeft() || 0;
+}
+
+qx.Proto.getComputedCellPaddingRight = function(vCol, vRow) {
+ return this.getColumnPaddingRight(vCol) || this.getRowPaddingRight(vRow) || this.getCellPaddingRight() || 0;
+}
+
+qx.Proto.getComputedCellPaddingTop = function(vCol, vRow) {
+ return this.getRowPaddingTop(vRow) || this.getColumnPaddingTop(vCol) || this.getCellPaddingTop() || 0;
+}
+
+qx.Proto.getComputedCellPaddingBottom = function(vCol, vRow) {
+ return this.getRowPaddingBottom(vRow) || this.getColumnPaddingBottom(vCol) || this.getCellPaddingBottom() || 0;
+}
+
+
+// GETTER: INNER
+
+qx.Proto.getColumnInnerWidth = function(vCol, vRow) {
+ return this.getColumnBoxWidth(vCol) - this.getComputedCellPaddingLeft(vCol, vRow) - this.getComputedCellPaddingRight(vCol, vRow);
+}
+
+qx.Proto.getRowInnerHeight = function(vCol, vRow) {
+ return this.getRowBoxHeight(vRow) - this.getComputedCellPaddingTop(vCol, vRow) - this.getComputedCellPaddingBottom(vCol, vRow);
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES: CELL ALIGNMENT
+---------------------------------------------------------------------------
+*/
+
+// SETTER
+
+qx.Proto.setColumnHorizontalAlignment = function(vIndex, vValue) {
+ this._setupColumnProperty(vIndex, "horizontalAlignment", vValue);
+}
+
+qx.Proto.setColumnVerticalAlignment = function(vIndex, vValue) {
+ this._setupColumnProperty(vIndex, "verticalAlignment", vValue);
+}
+
+qx.Proto.setRowHorizontalAlignment = function(vIndex, vValue) {
+ this._setupRowProperty(vIndex, "horizontalAlignment", vValue);
+}
+
+qx.Proto.setRowVerticalAlignment = function(vIndex, vValue) {
+ this._setupRowProperty(vIndex, "verticalAlignment", vValue);
+}
+
+
+
+// GETTER
+
+qx.Proto.getColumnHorizontalAlignment = function(vIndex) {
+ return this._getColumnProperty(vIndex, "horizontalAlignment");
+}
+
+qx.Proto.getColumnVerticalAlignment = function(vIndex) {
+ return this._getColumnProperty(vIndex, "verticalAlignment");
+}
+
+qx.Proto.getRowHorizontalAlignment = function(vIndex) {
+ return this._getRowProperty(vIndex, "horizontalAlignment");
+}
+
+qx.Proto.getRowVerticalAlignment = function(vIndex) {
+ return this._getRowProperty(vIndex, "verticalAlignment");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES: CELL PADDING
+---------------------------------------------------------------------------
+*/
+
+// SETTER
+
+qx.Proto.setColumnPaddingTop = function(vIndex, vValue) {
+ this._setupColumnProperty(vIndex, "paddingTop", vValue);
+}
+
+qx.Proto.setColumnPaddingRight = function(vIndex, vValue) {
+ this._setupColumnProperty(vIndex, "paddingRight", vValue);
+}
+
+qx.Proto.setColumnPaddingBottom = function(vIndex, vValue) {
+ this._setupColumnProperty(vIndex, "paddingBottom", vValue);
+}
+
+qx.Proto.setColumnPaddingLeft = function(vIndex, vValue) {
+ this._setupColumnProperty(vIndex, "paddingLeft", vValue);
+}
+
+qx.Proto.setRowPaddingTop = function(vIndex, vValue) {
+ this._setupRowProperty(vIndex, "paddingTop", vValue);
+}
+
+qx.Proto.setRowPaddingRight = function(vIndex, vValue) {
+ this._setupRowProperty(vIndex, "paddingRight", vValue);
+}
+
+qx.Proto.setRowPaddingBottom = function(vIndex, vValue) {
+ this._setupRowProperty(vIndex, "paddingBottom", vValue);
+}
+
+qx.Proto.setRowPaddingLeft = function(vIndex, vValue) {
+ this._setupRowProperty(vIndex, "paddingLeft", vValue);
+}
+
+
+
+// GETTER
+
+qx.Proto.getColumnPaddingTop = function(vIndex) {
+ return this._getColumnProperty(vIndex, "paddingTop");
+}
+
+qx.Proto.getColumnPaddingRight = function(vIndex) {
+ return this._getColumnProperty(vIndex, "paddingRight");
+}
+
+qx.Proto.getColumnPaddingBottom = function(vIndex) {
+ return this._getColumnProperty(vIndex, "paddingBottom");
+}
+
+qx.Proto.getColumnPaddingLeft = function(vIndex) {
+ return this._getColumnProperty(vIndex, "paddingLeft");
+}
+
+qx.Proto.getRowPaddingTop = function(vIndex) {
+ return this._getRowProperty(vIndex, "paddingTop");
+}
+
+qx.Proto.getRowPaddingRight = function(vIndex) {
+ return this._getRowProperty(vIndex, "paddingRight");
+}
+
+qx.Proto.getRowPaddingBottom = function(vIndex) {
+ return this._getRowProperty(vIndex, "paddingBottom");
+}
+
+qx.Proto.getRowPaddingLeft = function(vIndex) {
+ return this._getRowProperty(vIndex, "paddingLeft");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DIMENSION CACHE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._changeInnerWidth = function(vNew, vOld)
+{
+ for (var i=0, l=this.getColumnCount(); i 0;
+}
+
+qx.Proto.getSpanEntry = function(vCol, vRow)
+{
+ for (var i=0, s=this._spans, l=s.length, c; i= c.startCol && vCol <= c.endCol && vRow >= c.startRow && vRow <= c.endRow) {
+ return c;
+ }
+ }
+
+ return null;
+}
+
+qx.Proto.isSpanStart = function(vCol, vRow)
+{
+ for (var i=0, s=this._spans, l=s.length, c; i= c.startCol && vCol <= c.endCol && vRow >= c.startRow && vRow <= c.endRow) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+qx.Proto.isFillCell = function(vCol, vRow)
+{
+ for (var i=0, s=this._spans, l=s.length, c; i= c.startCol && vCol <= c.endCol && vRow >= c.startRow && vRow <= c.endRow && (vCol > c.startCol || vRow > c.startRow)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+qx.Proto._collidesWithSpans = function(vStartCol, vStartRow, vEndCol, vEndRow)
+{
+ for (var i=0, s=this._spans, l=s.length, c; i= c.startCol && vStartCol <= c.endCol && vEndRow >= c.startRow && vStartRow <= c.endRow ) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+
+ delete this._columnData;
+ delete this._rowData;
+
+ delete this._spans;
+
+ return qx.ui.core.Parent.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/HorizontalBoxLayout.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/HorizontalBoxLayout.js
new file mode 100644
index 0000000000..8eb08fec65
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/HorizontalBoxLayout.js
@@ -0,0 +1,29 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+#module(ui_layout)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.layout.HorizontalBoxLayout", qx.ui.layout.BoxLayout,
+function() {
+ qx.ui.layout.BoxLayout.call(this, "horizontal");
+});
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/VerticalBoxLayout.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/VerticalBoxLayout.js
new file mode 100644
index 0000000000..9b188f613a
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/VerticalBoxLayout.js
@@ -0,0 +1,29 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_basic)
+#module(ui_layout)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.layout.VerticalBoxLayout", qx.ui.layout.BoxLayout,
+function() {
+ qx.ui.layout.BoxLayout.call(this, "vertical");
+});
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellHtml.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellHtml.js
new file mode 100644
index 0000000000..ed73e294cb
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellHtml.js
@@ -0,0 +1,37 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.listview.ContentCellHtml", qx.ui.embed.HtmlEmbed,
+function(vHtml)
+{
+ qx.ui.embed.HtmlEmbed.call(this, vHtml);
+
+ this.setSelectable(false);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list-view-content-cell-html" });
+
+qx.ui.listview.ContentCellHtml.empty = {
+ html : ""
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellIconHtml.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellIconHtml.js
new file mode 100644
index 0000000000..7203299e38
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellIconHtml.js
@@ -0,0 +1,39 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.listview.ContentCellIconHtml", qx.ui.embed.IconHtmlEmbed,
+function(vHtml, vIcon, vIconWidth, vIconHeight)
+{
+ qx.ui.embed.IconHtmlEmbed.call(this, vHtml, vIcon, vIconWidth, vIconHeight);
+
+ this.setSelectable(false);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list-view-content-cell-icon-html" });
+
+qx.ui.listview.ContentCellIconHtml.empty =
+{
+ icon : "",
+ html : ""
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellImage.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellImage.js
new file mode 100644
index 0000000000..421f2e0f43
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellImage.js
@@ -0,0 +1,57 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.listview.ContentCellImage", qx.ui.basic.Image,
+function(vSource, vWidth, vHeight) {
+ qx.ui.basic.Image.call(this, vSource, vWidth, vHeight);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list-view-content-cell-image" });
+
+qx.ui.listview.ContentCellImage.empty = {
+ source : "static/image/blank.gif"
+}
+
+
+
+/*
+---------------------------------------------------------------------------
+ CUSTOM SETTER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.setSource = function(vSource)
+{
+ if (this._initialLayoutDone)
+ {
+ return this._updateContent(qx.manager.object.AliasManager.getInstance().resolvePath(vSource == "" ? "static/image/blank.gif" : vSource));
+ }
+ else
+ {
+ return qx.ui.basic.Image.prototype.setSource.call(this, vSource);
+ }
+}
+
+// Omit dimension setup in list-view
+qx.Proto._postApplyDimensions = qx.util.Return.returnTrue;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellLink.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellLink.js
new file mode 100644
index 0000000000..b53338a595
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellLink.js
@@ -0,0 +1,40 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.listview.ContentCellLink", qx.ui.embed.LinkEmbed,
+function(vHtml)
+{
+ qx.ui.embed.LinkEmbed.call(this, vHtml);
+
+ // selectable = false will break links in gecko based browsers
+ this.setSelectable(true);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list-view-content-cell-link" });
+
+qx.ui.listview.ContentCellLink.empty =
+{
+ html : "",
+ uri : "#"
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellText.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellText.js
new file mode 100644
index 0000000000..2d4b28544f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellText.js
@@ -0,0 +1,40 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.listview.ContentCellText", qx.ui.embed.TextEmbed,
+function(vText)
+{
+ qx.ui.embed.TextEmbed.call(this, vText);
+
+ this.setStyleProperty("whiteSpace", "nowrap");
+ this.setStyleProperty("textOverflow", "ellipsis");
+
+ this.setSelectable(false);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list-view-content-cell-text" });
+
+qx.ui.listview.ContentCellText.empty = {
+ text : ""
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/Header.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/Header.js
new file mode 100644
index 0000000000..5d11d5bdc0
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/Header.js
@@ -0,0 +1,294 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.listview.Header", qx.ui.layout.HorizontalBoxLayout,
+function(vColumns)
+{
+ qx.ui.layout.HorizontalBoxLayout.call(this);
+
+ // This fixes the innerWidth calculation difference between the grid(pane) and the head.
+ this.setPaddingRight(qx.ui.core.Widget.SCROLLBAR_SIZE);
+
+
+ // ************************************************************************
+ // STORE REFERENCE TO CONFIG ENTRY
+ // ************************************************************************
+ this._columns = vColumns;
+
+
+ // ************************************************************************
+ // CREATE HEADER CELLS
+ // ************************************************************************
+ var vHeadCell, vHeadSeparator;
+
+ for (var vCol in vColumns)
+ {
+ vHeadCell = new qx.ui.listview.HeaderCell(vColumns[vCol], vCol);
+ vHeadSeparator = new qx.ui.listview.HeaderSeparator;
+
+ this.add(vHeadCell, vHeadSeparator);
+
+ if (vColumns[vCol].align) {
+ vHeadCell.setHorizontalChildrenAlign(vColumns[vCol].align);
+
+ if (vColumns[vCol].align == "right") {
+ vHeadCell.setReverseChildrenOrder(true);
+ }
+ }
+
+ // store some additional data
+ vColumns[vCol].contentClass = qx.OO.classes["qx.ui.listview.ContentCell" + qx.lang.String.toFirstUp(vColumns[vCol].type || "text")];
+ vColumns[vCol].headerCell = vHeadCell;
+ }
+
+
+ // ************************************************************************
+ // ADD EVENT LISTENERS
+ // ************************************************************************
+ this.addEventListener("mousemove", this._onmousemove);
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+ this.addEventListener("mouseout", this._onmouseout);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list-view-header" });
+
+
+
+/*
+---------------------------------------------------------------------------
+ RESIZE SYNC
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._syncColumnWidth = function(vWidth)
+{
+ var vChildren = this.getChildren();
+ var vColumn = Math.ceil(vChildren.indexOf(this._resizeCell) / 2);
+
+ this.getParent().getPane().setColumnWidth(vColumn, vWidth);
+}
+
+qx.Proto._syncResizeLine = function()
+{
+ qx.ui.core.Widget.flushGlobalQueues();
+
+ var vParent = this.getParent();
+ var vLine = vParent.getResizeLine();
+ var vLeft = qx.dom.Location.getPageBoxLeft(this._resizeSeparator.getElement()) - qx.dom.Location.getPageInnerLeft(this.getElement());
+ var vTop = qx.dom.Dimension.getBoxHeight(vParent.getHeader().getElement());
+ var vHeight = qx.dom.Dimension.getBoxHeight(vParent.getElement()) - vTop;
+
+ vLine._applyRuntimeTop(vTop);
+ vLine._applyRuntimeHeight(vHeight);
+ vLine._applyRuntimeLeft(vLeft);
+
+ vLine.removeStyleProperty("visibility");
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._mshtml = qx.sys.Client.getInstance().isMshtml();
+
+qx.Proto._onmousemove = function(e)
+{
+ if (!this.getParent().getResizable()) {
+ return;
+ }
+
+ if (this._resizingActive)
+ {
+ // Slow down mshtml a bit
+ if (this._mshtml)
+ {
+ if ((new Date).valueOf() - this._last < 50) {
+ return;
+ }
+
+ this._last = (new Date).valueOf();
+ }
+
+ var vNewLeft = e.getPageX();
+ var vSizeDiff = vNewLeft - this._resizeStart;
+ var vCell = this._resizeCell;
+
+ vCell.setWidth(Math.max(4, vCell.getWidth() + vSizeDiff));
+ this._resizeStart = vNewLeft;
+
+ if (this.getParent().getLiveResize())
+ {
+ this._syncColumnWidth(vCell._computeBoxWidth());
+ }
+ else
+ {
+ this._syncResizeLine();
+ }
+ }
+ else
+ {
+ var vTarget = e.getTarget();
+ var vEventPos = e.getPageX();
+ var vTargetPosLeft = qx.dom.Location.getPageBoxLeft(vTarget.getElement());
+ var vTargetPosRight = vTargetPosLeft + qx.dom.Dimension.getBoxWidth(vTarget.getElement());
+
+ var vResizeCursor = false;
+ var vResizeSeparator = null;
+
+ if (vTarget instanceof qx.ui.listview.HeaderSeparator)
+ {
+ vResizeCursor = true;
+ vResizeSeparator = vTarget;
+ }
+ else if ((vEventPos - vTargetPosLeft) <= 10)
+ {
+ // Ignore first column
+ if (!vTarget.isFirstChild())
+ {
+ vResizeCursor = true;
+ vResizeSeparator = vTarget.getPreviousSibling();
+ }
+ }
+ else if ((vTargetPosRight - vEventPos) <= 10)
+ {
+ vResizeCursor = true;
+ vResizeSeparator = vTarget.getNextSibling();
+ }
+
+ if (!(vResizeSeparator instanceof qx.ui.listview.HeaderSeparator))
+ {
+ vResizeSeparator = vTarget = vResizeCursor = null;
+ }
+
+ // Check if child is marked as resizable
+ else if (vResizeSeparator)
+ {
+ var vResizeCell = vResizeSeparator.getPreviousSibling();
+
+ if (vResizeCell && (vResizeCell._computedWidthTypePercent || vResizeCell._config.resizable == false)) {
+ vResizeSeparator = vTarget = vResizeCursor = null;
+ }
+ }
+
+ // Apply global cursor
+ this.getTopLevelWidget().setGlobalCursor(vResizeCursor ? "e-resize" : null);
+
+ // Store data for mousedown
+ this._resizeSeparator = vResizeSeparator;
+ this._resizeTarget = vTarget;
+ }
+}
+
+qx.Proto._onmousedown = function(e)
+{
+ if (!this._resizeSeparator) {
+ return;
+ }
+
+ this._resizingActive = true;
+ this._resizeStart = e.getPageX();
+ this._resizeCell = this._resizeSeparator.getPreviousSibling();
+
+ if (!this.getParent().getLiveResize()) {
+ this._syncResizeLine();
+ }
+
+ this.setCapture(true);
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ if (!this._resizingActive) {
+ return;
+ }
+
+ this._syncColumnWidth(this._resizeCell.getBoxWidth());
+
+ this.setCapture(false);
+ this.getTopLevelWidget().setGlobalCursor(null);
+
+ // Remove hover effect
+ this._resizeTarget.removeState("over");
+
+ // Hide resize line
+ this.getParent().getResizeLine().setStyleProperty("visibility", "hidden");
+
+ this._cleanupResizing();
+}
+
+qx.Proto._onmouseout = function(e)
+{
+ if (!this.getCapture()) {
+ this.getTopLevelWidget().setGlobalCursor(null);
+ }
+}
+
+qx.Proto._cleanupResizing = function()
+{
+ delete this._resizingActive;
+
+ delete this._resizeSeparator;
+ delete this._resizeTarget;
+ delete this._resizeStart;
+ delete this._resizeCell;
+}
+
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this._cleanupResizing();
+
+ this.removeEventListener("mousemove", this._onmousemove);
+ this.removeEventListener("mousedown", this._onmousedown);
+ this.removeEventListener("mouseup", this._onmouseup);
+ this.removeEventListener("mouseout", this._onmouseout);
+
+ this._columns = null;
+
+ return qx.ui.layout.HorizontalBoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/HeaderCell.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/HeaderCell.js
new file mode 100644
index 0000000000..46e198b02b
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/HeaderCell.js
@@ -0,0 +1,255 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.listview.HeaderCell", qx.ui.basic.Atom,
+function(vConfig, vId)
+{
+ qx.ui.basic.Atom.call(this, vConfig.label, vConfig.icon, vConfig.iconWidth, vConfig.iconHeight, vConfig.flash);
+
+ // Text Overflow
+ this.setStyleProperty("textOverflow", "ellipsis");
+
+
+ // ************************************************************************
+ // STORE REFERENCE TO CONFIG ENTRY
+ // ************************************************************************
+ this._config = vConfig;
+ this._id = vId;
+
+
+ // ************************************************************************
+ // ARGUMENTS
+ // ************************************************************************
+ this.setWidth(typeof vConfig.width === "undefined" ? "auto" : vConfig.width);
+
+ if (qx.util.Validation.isValid(vConfig.minWidth)) {
+ this.setMinWidth(vConfig.minWidth);
+ }
+
+ if (qx.util.Validation.isValid(vConfig.maxWidth)) {
+ this.setMaxWidth(vConfig.maxWidth);
+ }
+
+
+ // ************************************************************************
+ // ADDITIONAL CHILDREN
+ // ************************************************************************
+
+ // Re-Enable flex support
+ this.getLayoutImpl().setEnableFlexSupport(true);
+
+ this._spacer = new qx.ui.basic.HorizontalSpacer;
+
+ this._arrowup = new qx.ui.basic.Image("widget/arrows/up.gif");
+ this._arrowup.setVerticalAlign("middle");
+ this._arrowup.setDisplay(false);
+
+ this._arrowdown = new qx.ui.basic.Image("widget/arrows/down.gif");
+ this._arrowdown.setVerticalAlign("middle");
+ this._arrowdown.setDisplay(false);
+
+ this.add(this._spacer, this._arrowup, this._arrowdown);
+
+
+ // ************************************************************************
+ // EVENTS
+ // ************************************************************************
+
+ this.addEventListener("mouseup", this._onmouseup);
+ this.addEventListener("mouseover", this._onmouseover);
+ this.addEventListener("mouseout", this._onmouseout);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list-view-header-cell" });
+qx.OO.addProperty({ name : "sortOrder", type : "string", allowNull : true, possibleValues : [ "ascending", "descending" ] });
+
+qx.Class.C_SORT_ASCENDING = "ascending";
+qx.Class.C_SORT_DESCENDING = "descending";
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getView = function() {
+ return this.getParent().getParent();
+}
+
+qx.Proto.getNextSortOrder = function()
+{
+ var vCurrentSortOrder = this.getSortOrder();
+
+ switch(vCurrentSortOrder)
+ {
+ case qx.ui.listview.HeaderCell.C_SORT_ASCENDING:
+ return qx.ui.listview.HeaderCell.C_SORT_DESCENDING;
+
+ default:
+ return qx.ui.listview.HeaderCell.C_SORT_ASCENDING;
+ }
+}
+
+qx.Proto.updateSort = function()
+{
+
+ var vListView = this.getView();
+ var vData = vListView.getData();
+ var vFieldId = this._id;
+ var vSortProp = this._config.sortProp || "text";
+ var vSortMethod = this._config.sortMethod || qx.util.Compare.byString;
+
+ vData.sort(function(a, b) {
+ return vSortMethod(a[vFieldId][vSortProp], b[vFieldId][vSortProp]);
+ });
+
+ if (this.getSortOrder() == qx.ui.listview.HeaderCell.C_SORT_DESCENDING) {
+ vData.reverse();
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifySortOrder = function(propValue, propOldValue, propData)
+{
+ var vListView = this.getView();
+
+ switch(propValue)
+ {
+ case qx.ui.listview.HeaderCell.C_SORT_ASCENDING:
+ this._arrowup.setDisplay(true);
+ this._arrowdown.setDisplay(false);
+
+ vListView.setSortBy(this._id);
+ break;
+
+ case qx.ui.listview.HeaderCell.C_SORT_DESCENDING:
+ this._arrowup.setDisplay(false);
+ this._arrowdown.setDisplay(true);
+
+ vListView.setSortBy(this._id);
+ break;
+
+ default:
+ this._arrowup.setDisplay(false);
+ this._arrowdown.setDisplay(false);
+
+ if (vListView.getSortBy() == this._id) {
+ vListView.setSortBy(null);
+ }
+ }
+
+ if (propValue)
+ {
+ this.updateSort();
+ vListView.update();
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmouseover = function(e) {
+ this.addState("over");
+}
+
+qx.Proto._onmouseout = function(e) {
+ this.removeState("over");
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ if (!this._config.sortable || this.getParent()._resizeSeparator) {
+ return;
+ }
+
+ this.setSortOrder(this.getNextSortOrder());
+ e.stopPropagation();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ delete this._config;
+
+ if (this._spacer)
+ {
+ this._spacer.dispose();
+ this._spacer = null;
+ }
+
+ if (this._arrowup)
+ {
+ this._arrowup.dispose();
+ this._arrowup = null;
+ }
+
+ if (this._arrowdown)
+ {
+ this._arrowdown.dispose();
+ this._arrowdown = null;
+ }
+
+ this.removeEventListener("mouseup", this._onmouseup);
+ this.removeEventListener("mouseover", this._onmouseover);
+ this.removeEventListener("mouseout", this._onmouseout);
+
+ return qx.ui.basic.Atom.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/HeaderSeparator.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/HeaderSeparator.js
new file mode 100644
index 0000000000..c2058db5d2
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/HeaderSeparator.js
@@ -0,0 +1,30 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.listview.HeaderSeparator", qx.ui.basic.Terminator,
+function() {
+ qx.ui.basic.Terminator.call(this);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list-view-header-separator" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ListView.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ListView.js
new file mode 100644
index 0000000000..567df4075e
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ListView.js
@@ -0,0 +1,373 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.listview.ListView", qx.ui.layout.VerticalBoxLayout,
+function(vData, vColumns)
+{
+ // ************************************************************************
+ // REFERENCES
+ // ************************************************************************
+
+ this._data = vData;
+ this._columns = vColumns;
+
+
+
+ // ************************************************************************
+ // OBJECTS
+ // ************************************************************************
+
+ this._header = new qx.ui.listview.Header(vColumns);
+ this._frame = new qx.ui.layout.HorizontalBoxLayout;
+ this._pane = new qx.ui.listview.ListViewPane(vData, vColumns);
+ this._scroll = new qx.ui.layout.CanvasLayout;
+ this._scrollContent = new qx.ui.basic.Terminator;
+ this._resizeLine = new qx.ui.basic.Terminator;
+
+
+
+ // ************************************************************************
+ // SUPERCLASS CONSTRUCTOR
+ // ************************************************************************
+
+ qx.ui.layout.VerticalBoxLayout.call(this);
+
+
+
+ // ************************************************************************
+ // HEADER
+ // ************************************************************************
+
+ this._header.setParent(this);
+
+
+
+ // ************************************************************************
+ // FRAME
+ // ************************************************************************
+
+ this._frame.setParent(this);
+ this._frame.setHeight("1*");
+ this._frame.setWidth(null);
+
+
+
+ // ************************************************************************
+ // PANE
+ // ************************************************************************
+
+ this._pane.setParent(this._frame);
+
+
+
+ // ************************************************************************
+ // SCROLL AREA
+ // ************************************************************************
+
+ this._scroll.setWidth("auto");
+ this._scroll.setOverflow("scrollY");
+ this._scroll.setParent(this._frame);
+ this._scroll.enableInlineEvent("scroll");
+ this._scroll.addEventListener("scroll", this._onscroll, this);
+
+
+
+ // ************************************************************************
+ // SCROLL CONTENT
+ // ************************************************************************
+
+ this._scrollContent.setWidth(1);
+ this._scrollContent.setParent(this._scroll);
+
+
+
+
+ // ************************************************************************
+ // RESIZE LINE
+ // ************************************************************************
+
+ this._resizeLine.setBackgroundColor("#D6D5D9");
+ this._resizeLine.setWidth(1);
+ this._resizeLine.setParent(this);
+
+
+
+ // ************************************************************************
+ // EVENTS
+ // ************************************************************************
+
+ this.addEventListener("mousedown", this._onmousedown);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list-view" });
+
+qx.OO.addProperty({ name : "resizable", type : "boolean", defaultValue : true });
+qx.OO.addProperty({ name : "liveResize", type : "boolean", defaultValue : false });
+qx.OO.addProperty({ name : "sortBy", type : "string" });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getData = function() {
+ return this._data;
+}
+
+qx.Proto.getColumns = function() {
+ return this._columns;
+}
+
+qx.Proto.getHeader = function() {
+ return this._header;
+}
+
+qx.Proto.getFrame = function() {
+ return this._frame;
+}
+
+qx.Proto.getPane = function() {
+ return this._pane;
+}
+
+qx.Proto.getScroll = function() {
+ return this._scroll;
+}
+
+qx.Proto.getScrollContent = function() {
+ return this._scrollContent;
+}
+
+qx.Proto.getResizeLine = function() {
+ return this._resizeLine;
+}
+
+qx.Proto.update = function()
+{
+ this.updateScrollBar();
+ this.updateContent();
+
+ // ignore updateLayout here, as it is mostly initially used
+}
+
+qx.Proto.updateScrollBar = function() {
+ this._scrollContent.setHeight((this._data.length * this._pane._rowHeight) + this._pane._rowHeight);
+}
+
+/*!
+ Bugfix for gecko 1.8 (the one released with firefox 1.5)
+ Overflow updates if content gets smaller are problematic
+ https://bugzilla.mozilla.org/show_bug.cgi?id=320106
+*/
+if (qx.sys.Client.getInstance().isGecko() && qx.sys.Client.getInstance().getVersion() >= 1.8)
+{
+ qx.Proto._updateScrollBar = qx.Proto.updateScrollBar;
+
+ qx.Proto.updateScrollBar = function()
+ {
+ this._updateScrollBar();
+
+ this._scroll.setStyleProperty("height", "0px");
+ this._scroll.forceHeight(0);
+ this._scroll.setHeight(null);
+ }
+}
+
+qx.Proto.updateContent = function() {
+ this.getPane()._updateRendering(true);
+}
+
+qx.Proto.updateLayout = function() {
+ this.getPane()._updateLayout();
+}
+
+qx.Proto.updateSort = function()
+{
+ var vSortBy = this.getSortBy();
+
+ if (!vSortBy) {
+ return;
+ }
+
+ var vCell = this._getHeaderCell(vSortBy);
+
+ if (vCell) {
+ vCell.updateSort();
+ }
+}
+
+qx.Proto._getHeaderCell = function(vCellId)
+{
+ var vNewEntry = this._columns[vCellId];
+ return vNewEntry ? vNewEntry.headerCell : null;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifySortBy = function(propValue, propOldValue, propData)
+{
+ if (propOldValue)
+ {
+ var vOldCell = this._getHeaderCell(propOldValue);
+
+ if (vOldCell) {
+ vOldCell.setSortOrder(null);
+ }
+ }
+
+ if (propValue)
+ {
+ var vNewCell = this._getHeaderCell(propValue);
+
+ if (vNewCell && vNewCell.getSortOrder() == null) {
+ vNewCell.setSortOrder(qx.ui.listview.HeaderCell.C_SORT_ASCENDING);
+ }
+ }
+
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onscroll = function(e) {
+ this._pane._onscroll(e);
+}
+
+qx.Proto._onmousedown = function(e) {
+ this.getFocusRoot().setActiveChild(this.getPane());
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPLAYBLE HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._handleDisplayableCustom = function(vDisplayable, vParent, vHint)
+{
+ qx.ui.layout.VerticalBoxLayout.prototype._handleDisplayableCustom.call(this, vDisplayable, vParent, vHint);
+
+ if (vDisplayable)
+ {
+ this.updateLayout();
+ this.updateScrollBar();
+ this.updateContent();
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (this._header)
+ {
+ this._header.dispose();
+ this._header = null;
+ }
+
+ if (this._frame)
+ {
+ this._frame.dispose();
+ this._frame = null;
+ }
+
+ if (this._pane)
+ {
+ this._pane.dispose();
+ this._pane = null;
+ }
+
+ if (this._scroll)
+ {
+ this._scroll.dispose();
+ this._scroll = null;
+ }
+
+ if (this._scrollContent)
+ {
+ this._scrollContent.dispose();
+ this._scrollContent = null;
+ }
+
+ if (this._resizeLine)
+ {
+ this._resizeLine.dispose();
+ this._resizeLine = null;
+ }
+
+ delete this._columns;
+ delete this._data;
+
+ this.removeEventListener("mousedown", this._onmousedown);
+
+ return qx.ui.layout.VerticalBoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ListViewPane.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ListViewPane.js
new file mode 100644
index 0000000000..89ae3c6fea
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ListViewPane.js
@@ -0,0 +1,556 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_listview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.listview.ListViewPane", qx.ui.layout.GridLayout,
+function(vData, vColumns)
+{
+ qx.ui.layout.GridLayout.call(this);
+
+ // ************************************************************************
+ // DATA
+ // ************************************************************************
+ // Add aliases for data tables
+ this._data = vData;
+ this._columns = vColumns;
+
+
+ // ************************************************************************
+ // INITIALIZE MANAGER
+ // ************************************************************************
+ this._manager = new qx.manager.selection.VirtualSelectionManager(this);
+
+
+ // ************************************************************************
+ // MOUSE EVENT LISTENER
+ // ************************************************************************
+ // Add handling for mouse wheel events
+ // Needed because the virtual scroll area does not fire browser
+ // understandable events above this pane.
+ this.addEventListener("mousewheel", this._onmousewheel);
+
+ this.addEventListener("mouseover", this._onmouseover);
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+ this.addEventListener("click", this._onclick);
+ this.addEventListener("dblclick", this._ondblclick);
+
+
+ // ************************************************************************
+ // KEY EVENT LISTENER
+ // ************************************************************************
+ this.addEventListener("keypress", this._onkeypress);
+});
+
+qx.OO.changeProperty({ name : "appearance",
+ type : "string",
+ defaultValue : "list-view-pane"
+ });
+
+qx.Proto._rowHeight = 16;
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getView = function() {
+ return this.getParent().getParent();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UPDATER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._lastRowCount = 0;
+
+qx.Proto._updateLayout = function(vUpdate)
+{
+ // this.debug("InnerHeight: " + this._computeInnerHeight());
+ // this.debug("BoxHeight: " + this._computeBoxHeight());
+ // return
+
+ var vColumns = this._columns;
+ var vRowCount = Math.ceil(this.getInnerHeight() / this._rowHeight);
+ var vData = this._data;
+ var vCell;
+
+ // this.debug("Row-Count: " + this._lastRowCount + " => " + vRowCount);
+
+ // Sync cells: Add new ones and configure them
+ if (vRowCount > this._lastRowCount)
+ {
+ for (var i=this._lastRowCount, j=0; i vRowCount)
+ {
+ var vChildren = this.getChildren();
+ var vChildrenLength = vChildren.length - 1;
+
+ for (var i=this._lastRowCount; i>vRowCount; i--)
+ {
+ for (var vCol in vColumns)
+ {
+ vCell = vChildren[vChildrenLength--];
+ this.remove(vCell);
+ vCell.dispose();
+ }
+ }
+ }
+
+ // Update row and column count
+ this.setRowCount(vRowCount);
+ if (!vUpdate) {
+ this.setColumnCount(qx.lang.Object.getLength(vColumns));
+ }
+
+ // Apply height to all rows
+ for (var i=0; i vParentHeight || vOffset < vParentScrollTop)
+ {
+ vNewScrollTop = vOffset;
+ }
+ else if ((vOffset + vHeight) > (vParentScrollTop + vParentHeight))
+ {
+ vNewScrollTop = vOffset + vHeight - vParentHeight;
+ }
+
+ if (vNewScrollTop != null) {
+ this.getView().getScroll().setScrollTop(vNewScrollTop);
+ }
+}
+
+qx.Proto.setScrollTop = function(vScrollTop)
+{
+ this.getView().getScroll().setScrollTop(vScrollTop);
+ this._updateRendering();
+}
+
+qx.Proto.getScrollTop = function() {
+ return this._currentScrollTop;
+}
+
+qx.Proto.setScrollLeft = function() {
+ this.error("Not implemented in qx.ui.listview.ListViewPane!");
+}
+
+qx.Proto.getScrollLeft = function() {
+ return 0;
+}
+
+qx.Proto.isItemVisible = function(vItem)
+{
+ var vIndex = this._data.indexOf(vItem);
+ var vRowStart = Math.floor(this._currentScrollTop / this._rowHeight);
+ var vRowLength = Math.ceil(this.getClientHeight() / this._rowHeight);
+
+ return vIndex >= vRowStart && vIndex <= (vRowStart + vRowLength);
+}
+
+qx.Proto.getRelativeItemPosition = function(vItem)
+{
+ var vIndex = this._data.indexOf(vItem);
+ var vRowStart = Math.floor(this._currentScrollTop / this._rowHeight);
+
+ return vIndex - vRowStart;
+}
+
+qx.Proto._updateItem = function(vItem)
+{
+ var vIndex = this._data.indexOf(vItem);
+ var vRowStart = Math.floor(this._currentScrollTop / this._rowHeight);
+ var vRowLength = Math.ceil(this.getClientHeight() / this._rowHeight);
+
+ if (vIndex < vRowStart || vIndex > (vRowStart + vRowLength)) {
+ return;
+ }
+
+ this._updateRow(vIndex - vRowStart);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+
+ // ************************************************************************
+ // MOUSE EVENT LISTENER
+ // ************************************************************************
+ this.removeEventListener("mousewheel", this._onmousewheel);
+ this.removeEventListener("mouseover", this._onmouseover);
+ this.removeEventListener("mousedown", this._onmousedown);
+ this.removeEventListener("mouseup", this._onmouseup);
+ this.removeEventListener("click", this._onclick);
+ this.removeEventListener("dblclick", this._ondblclick);
+
+
+ // ************************************************************************
+ // KEY EVENT LISTENER
+ // ************************************************************************
+ this.removeEventListener("keypress", this._onkeypress);
+
+
+ // ************************************************************************
+ // DATA
+ // ************************************************************************
+ delete this._data;
+ delete this._columns;
+
+
+ // ************************************************************************
+ // MANAGER
+ // ************************************************************************
+ if (this._manager)
+ {
+ this._manager.dispose();
+ this._manager = null;
+ }
+
+ return qx.ui.layout.GridLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Button.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Button.js
new file mode 100644
index 0000000000..569419b566
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Button.js
@@ -0,0 +1,354 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_menu)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.menu.Button", qx.ui.layout.HorizontalBoxLayout,
+function(vLabel, vIcon, vCommand, vMenu)
+{
+ qx.ui.layout.HorizontalBoxLayout.call(this);
+
+
+ // ************************************************************************
+ // LAYOUT
+ // ************************************************************************
+
+ var io = this._iconObject = new qx.ui.basic.Image;
+ io.setWidth(16);
+ io.setAnonymous(true);
+
+ var lo = this._labelObject = new qx.ui.basic.Label;
+ lo.setAnonymous(true);
+ lo.setSelectable(false);
+
+ var so = this._shortcutObject = new qx.ui.basic.Label;
+ so.setAnonymous(true);
+ so.setSelectable(false);
+
+ var ao = this._arrowObject = new qx.ui.basic.Image("widget/arrows/next.gif");
+ ao.setAnonymous(true);
+
+
+ // ************************************************************************
+ // INIT
+ // ************************************************************************
+
+ if (qx.util.Validation.isValidString(vLabel)) {
+ this.setLabel(vLabel);
+ }
+
+ if (qx.util.Validation.isValidString(vIcon)) {
+ this.setIcon(vIcon);
+ }
+
+ if (qx.util.Validation.isValid(vCommand)) {
+ this.setCommand(vCommand);
+ }
+
+ if (qx.util.Validation.isValid(vMenu)) {
+ this.setMenu(vMenu);
+ }
+
+
+ // ************************************************************************
+ // EVENTS
+ // ************************************************************************
+
+ this.addEventListener("mouseup", this._onmouseup);
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "menu-button" });
+
+qx.OO.addProperty({ name : "icon", type : "string" });
+qx.OO.addProperty({ name : "label", type : "string" });
+qx.OO.addProperty({ name : "menu", type : "object" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._hasIcon = false;
+qx.Proto._hasLabel = false;
+qx.Proto._hasShortcut = false;
+qx.Proto._hasMenu = false;
+
+qx.Proto.hasIcon = function() {
+ return this._hasIcon;
+}
+
+qx.Proto.hasLabel = function() {
+ return this._hasLabel;
+}
+
+qx.Proto.hasShortcut = function() {
+ return this._hasShortcut;
+}
+
+qx.Proto.hasMenu = function() {
+ return this._hasMenu;
+}
+
+qx.Proto.getIconObject = function() {
+ return this._iconObject;
+}
+
+qx.Proto.getLabelObject = function() {
+ return this._labelObject;
+}
+
+qx.Proto.getShortcutObject = function() {
+ return this._shortcutObject;
+}
+
+qx.Proto.getArrowObject = function() {
+ return this._arrowObject;
+}
+
+qx.Proto.getParentMenu = function()
+{
+ var vParent = this.getParent();
+ if (vParent)
+ {
+ vParent = vParent.getParent();
+
+ if (vParent && vParent instanceof qx.ui.menu.Menu) {
+ return vParent;
+ }
+ }
+
+ return null;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INIT LAYOUT IMPL
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This creates an new instance of the layout impl this widget uses
+*/
+qx.Proto._createLayoutImpl = function() {
+ return new qx.renderer.layout.MenuButtonLayoutImpl(this);
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyEnabled = function(propValue, propOldValue, propData)
+{
+ if (this._iconObject) {
+ this._iconObject.setEnabled(propValue);
+ }
+
+ if (this._labelObject) {
+ this._labelObject.setEnabled(propValue);
+ }
+
+ if (this._shortcutObject) {
+ this._shortcutObject.setEnabled(propValue);
+ }
+
+ return qx.ui.layout.HorizontalBoxLayout.prototype._modifyEnabled.call(this, propValue, propOldValue, propData);
+}
+
+qx.Proto._modifyIcon = function(propValue, propOldValue, propData)
+{
+ this._iconObject.setSource(propValue);
+
+ if (qx.util.Validation.isValidString(propValue))
+ {
+ this._hasIcon = true;
+
+ if (qx.util.Validation.isInvalidString(propOldValue)) {
+ this.addAtBegin(this._iconObject);
+ }
+ }
+ else
+ {
+ this._hasIcon = false;
+ this.remove(this._iconObject);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyLabel = function(propValue, propOldValue, propData)
+{
+ this._labelObject.setHtml(propValue);
+
+ if (qx.util.Validation.isValidString(propValue))
+ {
+ this._hasLabel = true;
+
+ if (qx.util.Validation.isInvalidString(propOldValue)) {
+ this.addAt(this._labelObject, this.getFirstChild() == this._iconObject ? 1 : 0);
+ }
+ }
+ else
+ {
+ this._hasLabel = false;
+ this.remove(this._labelObject);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyCommand = function(propValue, propOldValue, propData)
+{
+ var vHtml = propValue ? propValue.getShortcut() : "";
+
+ this._shortcutObject.setHtml(vHtml);
+
+ if (qx.util.Validation.isValidString(vHtml))
+ {
+ this._hasShortcut = true;
+
+ var vOldHtml = propOldValue ? propOldValue.getShortcut() : "";
+
+ if (qx.util.Validation.isInvalidString(vOldHtml))
+ {
+ if (this.getLastChild() == this._arrowObject)
+ {
+ this.addBefore(this._shortcutObject, this._arrowObject);
+ }
+ else
+ {
+ this.addAtEnd(this._shortcutObject);
+ }
+ }
+ }
+ else
+ {
+ this._hasShortcut = false;
+ this.remove(this._shortcutObject);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyMenu = function(propValue, propOldValue, propData)
+{
+ if (qx.util.Validation.isValidObject(propValue))
+ {
+ this._hasMenu = true;
+
+ if (qx.util.Validation.isInvalidObject(propOldValue)) {
+ this.addAtEnd(this._arrowObject);
+ }
+ }
+ else
+ {
+ this._hasMenu = false;
+ this.remove(this._arrowObject);
+ }
+
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmouseup = function(e) {
+ this.execute();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ // Dispose children
+ if (this._iconObject)
+ {
+ this._iconObject.dispose();
+ this._iconObject = null;
+ }
+
+ if (this._labelObject)
+ {
+ this._labelObject.dispose();
+ this._labelObject = null;
+ }
+
+ if (this._shortcutObject)
+ {
+ this._shortcutObject.dispose();
+ this._shortcutObject = null;
+ }
+
+ if (this._arrowObject)
+ {
+ this._arrowObject.dispose();
+ this._arrowObject = null;
+ }
+
+ // Remove event listeners
+ this.removeEventListener("mouseup", this._onmouseup);
+
+ return qx.ui.layout.HorizontalBoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/CheckBox.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/CheckBox.js
new file mode 100644
index 0000000000..a6380f8fd2
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/CheckBox.js
@@ -0,0 +1,85 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_menu)
+
+************************************************************************ */
+
+/*!
+ A checkbox for the menu system.
+*/
+qx.OO.defineClass("qx.ui.menu.CheckBox", qx.ui.menu.Button,
+function(vLabel, vCommand, vChecked)
+{
+ qx.ui.menu.Button.call(this, vLabel, "static/image/blank.gif", vCommand);
+
+ if (qx.util.Validation.isValidBoolean(vChecked)) {
+ this.setChecked(vChecked);
+ }
+
+ qx.manager.object.ImageManager.getInstance().preload("widget/menu/checkbox.gif");
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "menu-check-box" });
+qx.OO.addProperty({ name : "name", type : "string" });
+qx.OO.addProperty({ name : "value", type : "string" });
+qx.OO.addProperty({ name : "checked", type : "boolean", defaultValue : false, getAlias : "isChecked" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyChecked = function(propValue, propOldValue, propData)
+{
+ propValue ? this.addState("checked") : this.removeState("checked");
+ this.getIconObject().setSource(propValue ? "widget/menu/checkbox.gif" : "static/image/blank.gif");
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EXECUTE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.execute = function()
+{
+ this.setChecked(!this.getChecked());
+ qx.ui.menu.Button.prototype.execute.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Layout.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Layout.js
new file mode 100644
index 0000000000..3f06492782
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Layout.js
@@ -0,0 +1,56 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_menu)
+
+************************************************************************ */
+
+/*!
+ A small helper class to create a special layout handler for qx.ui.menu.Menus
+*/
+qx.OO.defineClass("qx.ui.menu.Layout", qx.ui.layout.VerticalBoxLayout,
+function()
+{
+ qx.ui.layout.VerticalBoxLayout.call(this);
+
+ this.setAnonymous(true);
+});
+
+
+/*!
+ Appearance of the widget
+*/
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "menu-layout" });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INIT LAYOUT IMPL
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This creates an new instance of the layout impl this widget uses
+*/
+qx.Proto._createLayoutImpl = function() {
+ return new qx.renderer.layout.MenuLayoutImpl(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Menu.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Menu.js
new file mode 100644
index 0000000000..7006c95336
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Menu.js
@@ -0,0 +1,907 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_menu)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.menu.Menu", qx.ui.popup.Popup,
+function()
+{
+ qx.ui.popup.Popup.call(this);
+
+
+ // ************************************************************************
+ // LAYOUT
+ // ************************************************************************
+
+ var l = this._layout = new qx.ui.menu.Layout;
+ this.add(l);
+
+
+ // ************************************************************************
+ // TIMER
+ // ************************************************************************
+ this._openTimer = new qx.client.Timer(this.getOpenInterval());
+ this._openTimer.addEventListener("interval", this._onopentimer, this);
+
+ this._closeTimer = new qx.client.Timer(this.getCloseInterval());
+ this._closeTimer.addEventListener("interval", this._onclosetimer, this);
+
+
+ // ************************************************************************
+ // EVENTS
+ // ************************************************************************
+
+ this.addEventListener("mouseover", this._onmouseover);
+ this.addEventListener("mousemove", this._onmouseover);
+ this.addEventListener("mouseout", this._onmouseout);
+
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keypress", this._onkeypress);
+
+
+ // ************************************************************************
+ // REMAPPING
+ // ************************************************************************
+
+ this.remapChildrenHandlingTo(this._layout);
+});
+
+qx.Proto._remappingChildTable = [ "add", "remove", "addAt", "addAtBegin", "addAtEnd", "removeAt", "addBefore", "addAfter", "removeAll", "getFirstChild", "getFirstActiveChild", "getLastChild", "getLastActiveChild" ];
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "menu" });
+
+qx.OO.addProperty({ name : "iconContentGap", type : "number", defaultValue : 4 });
+qx.OO.addProperty({ name : "labelShortcutGap", type : "number", defaultValue : 10 });
+qx.OO.addProperty({ name : "contentArrowGap", type : "number", defaultValue : 8 });
+qx.OO.addProperty({ name : "contentNonIconPadding", type : "number", defaultValue : 20 });
+qx.OO.addProperty({ name : "contentNonArrowPadding", type : "number", defaultValue : 8 });
+
+qx.OO.addProperty({ name : "hoverItem", type : "object" });
+qx.OO.addProperty({ name : "openItem", type : "object" });
+qx.OO.addProperty({ name : "opener", type : "object" });
+qx.OO.addProperty({ name : "parentMenu", type : "object" });
+
+qx.OO.addProperty({ name : "fastReopen", type : "boolean", defaultValue : false });
+qx.OO.addProperty({ name : "openInterval", type : "number", defaultValue : 250 });
+qx.OO.addProperty({ name : "closeInterval", type : "number", defaultValue : 250 });
+
+qx.OO.addProperty({ name : "subMenuHorizontalOffset", type : "number", defaultValue : -3 });
+qx.OO.addProperty({ name : "subMenuVerticalOffset", type : "number", defaultValue : -2 });
+
+qx.OO.addProperty({ name : "indentShortcuts", type : "boolean", defaultValue : true });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getLayout = function() {
+ return this._layout;
+}
+
+qx.Proto.isSubButton = function(vButton)
+{
+ if (vButton.getParent() === this._layout) {
+ return true;
+ }
+
+ for (var a=this._layout.getChildren(), l=a.length, i=0; i 0) {
+ vTemp += this.getLabelShortcutGap();
+ }
+
+ vSum = Math.max(lw, vTemp);
+ }
+ else
+ {
+ vSum = lw + sw;
+
+ if (lw > 0 && sw > 0) {
+ vSum += this.getLabelShortcutGap();
+ }
+ }
+
+ return vSum;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LOCATIONS AND DIMENSIONS OF CHILDRENS CHILDREN:
+ POSITION COMPUTERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computeIconPosition = function() {
+ return 0;
+}
+
+qx.Proto._computeLabelPosition = function()
+{
+ var v = this.getMaxIconWidth();
+ return v > 0 ? v + this.getIconContentGap() : this.getContentNonIconPadding();
+}
+
+qx.Proto._computeShortcutPosition = function() {
+ return this.getLabelPosition() + this.getMaxContentWidth() - this.getMaxShortcutWidth();
+}
+
+qx.Proto._computeArrowPosition = function()
+{
+ var v = this.getMaxContentWidth();
+ return this.getLabelPosition() + (v > 0 ? v + this.getContentArrowGap() : v);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LOCATIONS AND DIMENSIONS OF CHILDRENS CHILDREN:
+ INVALIDATION OF CACHE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._invalidateMaxIconWidth = function()
+{
+ this._cachedMaxIconWidth = null;
+
+ this._invalidateLabelPosition();
+ this._invalidateMenuButtonNeededWidth();
+}
+
+qx.Proto._invalidateMaxLabelWidth = function()
+{
+ this._cachedMaxLabelWidth = null;
+
+ this._invalidateShortcutPosition();
+ this._invalidateMaxLabelWidthIncShortcut();
+ this._invalidateMaxContentWidth();
+ this._invalidateMenuButtonNeededWidth();
+}
+
+qx.Proto._invalidateMaxShortcutWidth = function()
+{
+ this._cachedMaxShortcutWidth = null;
+
+ this._invalidateArrowPosition();
+ this._invalidateMaxContentWidth();
+ this._invalidateMenuButtonNeededWidth();
+}
+
+qx.Proto._invalidateMaxLabelWidth = function()
+{
+ this._cachedMaxArrowWidth = null;
+ this._invalidateMenuButtonNeededWidth();
+}
+
+qx.Proto._invalidateLabelPosition = function()
+{
+ this._cachedLabelPosition = null;
+ this._invalidateShortcutPosition();
+}
+
+qx.Proto._invalidateShortcutPosition = function()
+{
+ this._cachedShortcutPosition = null;
+ this._invalidateArrowPosition();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LOCATIONS AND DIMENSIONS OF CHILDRENS CHILDREN:
+ NEEDED WIDTH COMPUTERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computeMenuButtonNeededWidth = function()
+{
+ var vSum = 0;
+
+ var vMaxIcon = this.getMaxIconWidth();
+ var vMaxContent = this.getMaxContentWidth();
+ var vMaxArrow = this.getMaxArrowWidth();
+
+ if (vMaxIcon > 0)
+ {
+ vSum += vMaxIcon;
+ }
+ else
+ {
+ vSum += this.getContentNonIconPadding();
+ }
+
+ if (vMaxContent > 0)
+ {
+ if (vMaxIcon > 0) {
+ vSum += this.getIconContentGap();
+ }
+
+ vSum += vMaxContent;
+ }
+
+ if (vMaxArrow > 0)
+ {
+ if (vMaxIcon > 0 || vMaxContent > 0) {
+ vSum += this.getContentArrowGap();
+ }
+
+ vSum += vMaxArrow;
+ }
+ else
+ {
+ vSum += this.getContentNonArrowPadding();
+ }
+
+ return vSum;
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT-HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmouseover = function(e)
+{
+ /* ------------------------------
+ HANDLE PARENT MENU
+ ------------------------------ */
+
+ // look if we have a parent menu
+ // if so we need to stop the close event started there
+ var vParent = this.getParentMenu();
+
+ if (vParent)
+ {
+ // stop the close event
+ vParent._closeTimer.stop();
+
+ // look if we have a opener, too (normally this should be)
+ var vOpener = this.getOpener();
+
+ // then setup it to look hovered
+ if (vOpener) {
+ vParent.setHoverItem(vOpener);
+ }
+ }
+
+
+
+
+ /* ------------------------------
+ HANDLING FOR HOVERING MYSELF
+ ------------------------------ */
+
+ var t = e.getTarget();
+
+ if (t == this)
+ {
+ this._openTimer.stop();
+ this._closeTimer.start();
+
+ this.setHoverItem(null);
+
+ return;
+ }
+
+
+
+
+ /* ------------------------------
+ HANDLING FOR HOVERING ITEMS
+ ------------------------------ */
+
+ var vOpen = this.getOpenItem();
+
+ // if we have a open item
+ if (vOpen)
+ {
+ this.setHoverItem(t);
+ this._openTimer.stop();
+
+ // if the new one has also a sub menu
+ if (t.hasMenu())
+ {
+ // check if we should use fast reopen (this will open the menu instantly)
+ if (this.getFastReopen())
+ {
+ this.setOpenItem(t);
+ this._closeTimer.stop();
+ }
+
+ // otherwise we use the default timer interval
+ else
+ {
+ this._openTimer.start();
+ }
+ }
+
+ // otherwise start the close timer for the old menu
+ else
+ {
+ this._closeTimer.start();
+ }
+ }
+
+ // otherwise handle the mouseover and restart the timer
+ else
+ {
+ this.setHoverItem(t);
+
+ // stop timer for the last open request
+ this._openTimer.stop();
+
+ // and restart it if the new one has a menu, too
+ if (t.hasMenu()) {
+ this._openTimer.start();
+ }
+ }
+}
+
+qx.Proto._onmouseout = function(e)
+{
+ // stop the open timer (for any previous open requests)
+ this._openTimer.stop();
+
+ // start the close timer to hide a menu if needed
+ var t = e.getTarget();
+ if (t != this && t.hasMenu()) {
+ this._closeTimer.start();
+ }
+
+ // reset the current hover item
+ this.setHoverItem(null);
+}
+
+qx.Proto._onopentimer = function(e)
+{
+ // stop the open timer (we need only the first interval)
+ this._openTimer.stop();
+
+ // if we have a item which is currently hovered, open it
+ var vHover = this.getHoverItem();
+ if (vHover && vHover.hasMenu()) {
+ this.setOpenItem(vHover);
+ }
+}
+
+qx.Proto._onclosetimer = function(e)
+{
+ // stop the close timer (we need only the first interval)
+ this._closeTimer.stop();
+
+ // reset the current opened item
+ this.setOpenItem(null);
+}
+
+/*!
+ Wraps key events to target functions
+*/
+qx.Proto._onkeydown = function(e)
+{
+ if (e.getKeyIdentifier() == "Enter") {
+ this._onkeydown_enter(e);
+ }
+ e.preventDefault();
+};
+
+
+qx.Proto._onkeypress = function(e)
+{
+ switch(e.getKeyIdentifier())
+ {
+ case "Up":
+ this._onkeypress_up(e);
+ break;
+
+ case "Down":
+ this._onkeypress_down(e);
+ break;
+
+ case "Left":
+ this._onkeypress_left(e);
+ break;
+
+ case "Right":
+ this._onkeypress_right(e);
+ break;
+
+ default:
+ return;
+ }
+
+ // Stop all matching events
+ e.preventDefault();
+};
+
+
+qx.Proto._onkeypress_up = function(e)
+{
+ var vHover = this.getHoverItem();
+ var vPrev = vHover ? vHover.isFirstChild() ? this.getLastActiveChild() : vHover.getPreviousActiveSibling([qx.ui.menu.Separator]) : this.getLastActiveChild();
+
+ this.setHoverItem(vPrev);
+};
+
+qx.Proto._onkeypress_down = function(e)
+{
+ var vHover = this.getHoverItem();
+ var vNext = vHover ? vHover.isLastChild() ? this.getFirstActiveChild() : vHover.getNextActiveSibling([qx.ui.menu.Separator]) : this.getFirstActiveChild();
+
+ this.setHoverItem(vNext);
+};
+
+
+qx.Proto._onkeypress_left = function(e)
+{
+ var vOpener = this.getOpener();
+
+ // Jump to the "parent" qx.ui.menu.Menu
+ if (vOpener instanceof qx.ui.menu.Button)
+ {
+ var vOpenerParent = this.getOpener().getParentMenu();
+
+ vOpenerParent.setOpenItem(null);
+ vOpenerParent.setHoverItem(vOpener);
+
+ vOpenerParent._makeActive();
+ }
+
+ // Jump to the previous ToolBarMenuButton
+ else if (vOpener instanceof qx.ui.toolbar.MenuButton)
+ {
+ var vToolBar = vOpener.getParentToolBar();
+
+ // change active widget to new button
+ this.getFocusRoot().setActiveChild(vToolBar);
+
+ // execute toolbars keydown implementation
+ vToolBar._onkeypress(e);
+ }
+};
+
+
+qx.Proto._onkeypress_right = function(e)
+{
+ var vHover = this.getHoverItem();
+
+ if (vHover)
+ {
+ var vMenu = vHover.getMenu();
+
+ if (vMenu)
+ {
+ this.setOpenItem(vHover);
+
+ // mark first item in new submenu
+ vMenu.setHoverItem(vMenu.getFirstActiveChild());
+
+ return;
+ }
+ }
+ else if (!this.getOpenItem())
+ {
+ var vFirst = this.getLayout().getFirstActiveChild();
+
+ if (vFirst) {
+ vFirst.hasMenu() ? this.setOpenItem(vFirst) : this.setHoverItem(vFirst);
+ }
+ }
+
+ // Jump to the next ToolBarMenuButton
+ var vOpener = this.getOpener();
+
+ if (vOpener instanceof qx.ui.toolbar.MenuButton)
+ {
+ var vToolBar = vOpener.getParentToolBar();
+
+ // change active widget to new button
+ this.getFocusRoot().setActiveChild(vToolBar);
+
+ // execute toolbars keydown implementation
+ vToolBar._onkeypress(e);
+ }
+ else if (vOpener instanceof qx.ui.menu.Button && vHover)
+ {
+ // search for menubar if existing
+ // menu -> button -> menu -> button -> menu -> menubarbutton -> menubar
+
+ var vOpenerParent = vOpener.getParentMenu();
+
+ while (vOpenerParent && vOpenerParent instanceof qx.ui.menu.Menu)
+ {
+ vOpener = vOpenerParent.getOpener();
+
+ if (vOpener instanceof qx.ui.menu.Button)
+ {
+ vOpenerParent = vOpener.getParentMenu();
+ }
+ else
+ {
+ if (vOpener) {
+ vOpenerParent = vOpener.getParent();
+ }
+
+ break;
+ }
+ }
+
+ if (vOpenerParent instanceof qx.ui.toolbar.Part) {
+ vOpenerParent = vOpenerParent.getParent();
+ }
+
+ if (vOpenerParent instanceof qx.ui.toolbar.ToolBar)
+ {
+ // jump to next menubarbutton
+ this.getFocusRoot().setActiveChild(vOpenerParent);
+ vOpenerParent._onkeypress(e);
+ }
+ }
+}
+
+qx.Proto._onkeydown_enter = function(e)
+{
+ var vHover = this.getHoverItem();
+ if (vHover) {
+ vHover.execute();
+ }
+
+ qx.manager.object.MenuManager.getInstance().update();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (this._layout)
+ {
+ this._layout.dispose();
+ this._layout = null;
+ }
+
+ if (this._openTimer)
+ {
+ this._openTimer.dispose();
+ this._openTimer = null;
+ }
+
+ if (this._closeTimer)
+ {
+ this._closeTimer.dispose();
+ this._closeTimer = null;
+ }
+
+ // Remove event listeners
+ this.removeEventListener("mouseover", this._onmouseover);
+ this.removeEventListener("mousemove", this._onmouseover);
+ this.removeEventListener("mouseout", this._onmouseout);
+
+ this.removeEventListener("keydown", this._onkeydown);
+ this.removeEventListener("keypress", this._onkeypress);
+
+
+ return qx.ui.popup.Popup.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/RadioButton.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/RadioButton.js
new file mode 100644
index 0000000000..b8ff7f975f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/RadioButton.js
@@ -0,0 +1,118 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_menu)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.menu.RadioButton", qx.ui.menu.CheckBox,
+function(vLabel, vCommand, vChecked)
+{
+ qx.ui.menu.CheckBox.call(this, vLabel, vCommand, vChecked);
+
+ qx.manager.object.ImageManager.getInstance().preload("widget/menu/radiobutton.gif");
+});
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "menu-radio-button" });
+
+/*!
+ The assigned qx.manager.selection.RadioManager which handles the switching between registered buttons
+*/
+qx.OO.addProperty({ name : "manager", type : "object", instance : "qx.manager.selection.RadioManager", allowNull : true });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyChecked = function(propValue, propOldValue, propData)
+{
+ var vManager = this.getManager();
+
+ if (vManager)
+ {
+ if (propValue)
+ {
+ vManager.setSelected(this);
+ }
+ else if (vManager.getSelected() == this)
+ {
+ vManager.setSelected(null);
+ }
+ }
+
+ propValue ? this.addState("checked") : this.removeState("checked");
+ this.getIconObject().setSource(propValue ? "widget/menu/radiobutton.gif" : "static/image/blank.gif");
+
+ return true;
+}
+
+qx.Proto._modifyManager = function(propValue, propOldValue, propData)
+{
+ if (propOldValue) {
+ propOldValue.remove(this);
+ }
+
+ if (propValue) {
+ propValue.add(this);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyName = function(propValue, propOldValue, propData)
+{
+ if (this.getManager()) {
+ this.getManager().setName(propValue);
+ }
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EXECUTE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.execute = function()
+{
+ this.setChecked(true);
+
+ // Intentionally bypass superclass and call super.super.execute
+ qx.ui.menu.Button.prototype.execute.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Separator.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Separator.js
new file mode 100644
index 0000000000..a7bce89c33
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Separator.js
@@ -0,0 +1,76 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_menu)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.menu.Separator", qx.ui.layout.CanvasLayout,
+function()
+{
+ qx.ui.layout.CanvasLayout.call(this);
+
+ // Fix IE Styling Issues
+ this.setStyleProperty("fontSize", "0");
+ this.setStyleProperty("lineHeight", "0");
+
+ // ************************************************************************
+ // LINE
+ // ************************************************************************
+
+ this._line = new qx.ui.basic.Terminator;
+ this._line.setAnonymous(true);
+ this._line.setAppearance("menu-separator-line");
+ this.add(this._line);
+
+
+ // ************************************************************************
+ // EVENTS
+ // ************************************************************************
+
+ // needed to stop the event, and keep the menu showing
+ this.addEventListener("mousedown", this._onmousedown);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "menu-separator" });
+
+qx.Proto.hasIcon = qx.util.Return.returnFalse;
+qx.Proto.hasLabel = qx.util.Return.returnFalse;
+qx.Proto.hasShortcut = qx.util.Return.returnFalse;
+qx.Proto.hasMenu = qx.util.Return.returnFalse;
+
+qx.Proto._onmousedown = function(e) {
+ e.stopPropagation();
+}
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._line)
+ {
+ this._line.dispose();
+ this._line = null;
+ }
+
+ return qx.ui.layout.CanvasLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menubar/Button.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menubar/Button.js
new file mode 100644
index 0000000000..9d13967fe6
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menubar/Button.js
@@ -0,0 +1,28 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_menu)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.menubar.Button", qx.ui.toolbar.MenuButton,
+function(vText, vMenu, vIcon, vIconWidth, vIconHeight, vFlash) {
+ qx.ui.toolbar.MenuButton.call(this, vText, vMenu, vIcon, vIconWidth, vIconHeight, vFlash);
+});
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menubar/MenuBar.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menubar/MenuBar.js
new file mode 100644
index 0000000000..858f1fea4f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menubar/MenuBar.js
@@ -0,0 +1,28 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_menu)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.menubar.MenuBar", qx.ui.toolbar.ToolBar,
+function() {
+ qx.ui.toolbar.ToolBar.call(this);
+});
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractBar.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractBar.js
new file mode 100755
index 0000000000..1c10e5680b
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractBar.js
@@ -0,0 +1,129 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.AbstractBar", qx.ui.layout.BoxLayout,
+function()
+{
+ qx.ui.layout.BoxLayout.call(this);
+
+ this._manager = new qx.manager.selection.RadioManager;
+
+ this.addEventListener("mousewheel", this._onmousewheel);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITY
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getManager = function() {
+ return this._manager;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._lastDate = (new Date(0)).valueOf();
+
+qx.Proto._onmousewheel = function(e)
+{
+ // Make it a bit lazier than it could be
+ // Hopefully this is a better behaviour for fast scrolling users
+ var vDate = (new Date).valueOf();
+
+ if ((vDate - 50) < this._lastDate) {
+ return;
+ }
+
+ this._lastDate = vDate;
+
+ var vManager = this.getManager();
+ var vItems = vManager.getItems();
+ var vPos = vItems.indexOf(vManager.getSelected());
+
+ if (this.getWheelDelta(e) > 0)
+ {
+ var vNext = vItems[vPos+1];
+
+ if (!vNext) {
+ vNext = vItems[0];
+ }
+ }
+ else if (vPos > 0)
+ {
+ var vNext = vItems[vPos-1];
+
+ if (!vNext) {
+ vNext = vItems[0];
+ }
+ }
+ else
+ {
+ vNext = vItems[vItems.length-1];
+ }
+
+ vManager.setSelected(vNext);
+}
+
+qx.Proto.getWheelDelta = function(e) {
+ return e.getWheelDelta();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (this._manager)
+ {
+ this._manager.dispose();
+ this._manager = null;
+ }
+
+ this.removeEventListener("mousewheel", this._onmousewheel);
+
+ return qx.ui.layout.BoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractButton.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractButton.js
new file mode 100755
index 0000000000..da590a286d
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractButton.js
@@ -0,0 +1,219 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+ ************************************************************************ */
+
+/* ************************************************************************
+
+
+ ************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.AbstractButton", qx.ui.basic.Atom,
+function(vText, vIcon, vIconWidth, vIconHeight, vFlash) {
+ qx.ui.basic.Atom.call(this, vText, vIcon, vIconWidth, vIconHeight, vFlash);
+
+ this.setTabIndex(1);
+
+ // ************************************************************************
+ // MOUSE EVENTS
+ // ************************************************************************
+ this.addEventListener("mouseover", this._onmouseover);
+ this.addEventListener("mouseout", this._onmouseout);
+ this.addEventListener("mousedown", this._onmousedown);
+
+ // ************************************************************************
+ // KEY EVENTS
+ // ************************************************************************
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keypress", this._onkeypress);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+ */
+
+/*!
+ If this tab is the currently selected/active one
+ */
+qx.OO.addProperty({ name : "checked", type : "boolean", defaultValue : false });
+
+/*!
+ The attached page of this tab
+ */
+qx.OO.addProperty({ name : "page", type : "object" });
+
+/*!
+ The assigned qx.manager.selection.RadioManager which handles the switching between registered buttons
+ */
+qx.OO.addProperty({ name : "manager", type : "object", instance : "qx.manager.selection.RadioManager", allowNull : true });
+
+/*!
+ The name of the radio group. All the radio elements in a group (registered by the same manager)
+ have the same name (and could have a different value).
+ */
+qx.OO.addProperty({ name : "name", type : "string" });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+ */
+
+qx.Proto.getView = function() {
+ return this.getParent().getParent();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+ */
+
+qx.Proto._modifyManager = function(propValue, propOldValue, propData) {
+ if (propOldValue) {
+ propOldValue.remove(this);
+ }
+
+ if (propValue) {
+ propValue.add(this);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyParent = function(propValue, propOldValue, propData) {
+ if (propOldValue) {
+ propOldValue.getManager().remove(this);
+ }
+
+ if (propValue) {
+ propValue.getManager().add(this);
+ }
+
+ return qx.ui.basic.Atom.prototype._modifyParent.call(this, propValue, propOldValue, propData);
+}
+
+qx.Proto._modifyPage = function(propValue, propOldValue, propData) {
+ if (propOldValue) {
+ propOldValue.setButton(null);
+ }
+
+ if (propValue) {
+ propValue.setButton(this);
+ this.getChecked() ? propValue.show() : propValue.hide();
+ }
+
+ return true;
+}
+
+qx.Proto._modifyChecked = function(propValue, propOldValue, propData) {
+ if (this._hasParent) {
+ var vManager = this.getManager();
+ if (vManager) {
+ vManager.handleItemChecked(this, propValue);
+ }
+ }
+
+ propValue ? this.addState("checked") : this.removeState("checked");
+
+ var vPage = this.getPage();
+ if (vPage) {
+ this.getChecked() ? vPage.show() : vPage.hide();
+ }
+
+ return true;
+}
+
+qx.Proto._modifyName = function(propValue, propOldValue, propData) {
+ if (this.getManager()) {
+ this.getManager().setName(propValue);
+ }
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+ */
+
+qx.Proto._onmousedown = function(e) {
+ this.setChecked(true);
+}
+
+qx.Proto._onmouseover = function(e) {
+ this.addState("over");
+}
+
+qx.Proto._onmouseout = function(e) {
+ this.removeState("over");
+}
+
+qx.Proto._onkeydown = function(e) {}
+qx.Proto._onkeypress = function(e) {}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+ */
+
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return;
+ }
+
+
+ // ************************************************************************
+ // MOUSE EVENTS
+ // ************************************************************************
+ this.removeEventListener("mouseover", this._onmouseover);
+ this.removeEventListener("mouseout", this._onmouseout);
+ this.removeEventListener("mousedown", this._onmousedown);
+
+
+ // ************************************************************************
+ // KEY EVENTS
+ // ************************************************************************
+ this.removeEventListener("keydown", this._onkeydown);
+ this.removeEventListener("keypress", this._onkeypress);
+
+
+ return qx.ui.basic.Atom.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPage.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPage.js
new file mode 100755
index 0000000000..3eed9d20b4
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPage.js
@@ -0,0 +1,75 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.AbstractPage", qx.ui.layout.CanvasLayout,
+function(vButton)
+{
+ qx.ui.layout.CanvasLayout.call(this);
+
+ if (qx.util.Validation.isValid(vButton)) {
+ this.setButton(vButton);
+ }
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ The attached tab of this page.
+*/
+qx.OO.addProperty({ name : "button", type : "object" });
+
+/*!
+ Make element displayed (if switched to true the widget will be created, if needed, too).
+ Instead of qx.ui.core.Widget, the default is false here.
+*/
+qx.OO.changeProperty({ name : "display", type : "boolean", defaultValue : false });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyButton = function(propValue, propOldValue, propData)
+{
+ if (propOldValue) {
+ propOldValue.setPage(null);
+ }
+
+ if (propValue) {
+ propValue.setPage(this);
+ }
+
+ return true;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPageView.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPageView.js
new file mode 100755
index 0000000000..786bc88145
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPageView.js
@@ -0,0 +1,84 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.AbstractPageView", qx.ui.layout.BoxLayout,
+function(vBarClass, vPaneClass)
+{
+ qx.ui.layout.BoxLayout.call(this);
+
+ this._bar = new vBarClass;
+ this._pane = new vPaneClass;
+
+ this.add(this._bar, this._pane);
+ this.setOrientation("vertical");
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITY
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getPane = function() {
+ return this._pane;
+}
+
+qx.Proto.getBar = function() {
+ return this._bar;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._bar)
+ {
+ this._bar.dispose();
+ this._bar = null;
+ }
+
+ if (this._pane)
+ {
+ this._pane.dispose();
+ this._pane = null;
+ }
+
+ return qx.ui.layout.BoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPane.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPane.js
new file mode 100755
index 0000000000..a026e0401e
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPane.js
@@ -0,0 +1,27 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.AbstractPane", qx.ui.layout.CanvasLayout,
+function() {
+ qx.ui.layout.CanvasLayout.call(this);
+});
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Bar.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Bar.js
new file mode 100644
index 0000000000..43ed8c1f85
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Bar.js
@@ -0,0 +1,75 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_buttonview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.buttonview.Bar", qx.ui.pageview.AbstractBar,
+function() {
+ qx.ui.pageview.AbstractBar.call(this);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "bar-view-bar" });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getWheelDelta = function(e)
+{
+ var vWheelDelta = e.getWheelDelta();
+
+ switch(this.getParent().getBarPosition())
+ {
+ case "left":
+ case "right":
+ vWheelDelta *= -1;
+ }
+
+ return vWheelDelta;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEARANCE ADDITIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyStateAppearance = function()
+{
+ var vPos = this.getParent().getBarPosition();
+
+ this._states.barLeft = vPos === "left";
+ this._states.barRight = vPos === "right";
+ this._states.barTop = vPos === "top";
+ this._states.barBottom = vPos === "bottom";
+
+ qx.ui.pageview.AbstractButton.prototype._applyStateAppearance.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Button.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Button.js
new file mode 100644
index 0000000000..2ea00867a9
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Button.js
@@ -0,0 +1,120 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_buttonview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.buttonview.Button", qx.ui.pageview.AbstractButton,
+function(vText, vIcon, vIconWidth, vIconHeight, vFlash) {
+ qx.ui.pageview.AbstractButton.call(this, vText, vIcon, vIconWidth, vIconHeight, vFlash);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "bar-view-button" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeypress = function(e)
+{
+ switch(this.getView().getBarPosition())
+ {
+ case "top":
+ case "bottom":
+ switch(e.getKeyIdentifier())
+ {
+ case "Left":
+ var vPrevious = true;
+ break;
+
+ case "Right":
+ var vPrevious = false;
+ break;
+
+ default:
+ return;
+ }
+
+ break;
+
+ case "left":
+ case "right":
+ switch(e.getKeyIdentifier())
+ {
+ case "Up":
+ var vPrevious = true;
+ break;
+
+ case "Down":
+ var vPrevious = false;
+ break;
+
+ default:
+ return;
+ }
+
+ break;
+
+ default:
+ return;
+ }
+
+ var vChild = vPrevious ? this.isFirstChild() ? this.getParent().getLastChild() : this.getPreviousSibling() : this.isLastChild() ? this.getParent().getFirstChild() : this.getNextSibling();
+
+ // focus next/previous button
+ vChild.setFocused(true);
+
+ // and naturally also check it
+ vChild.setChecked(true);
+}
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEARANCE ADDITIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyStateAppearance = function()
+{
+ var vPos = this.getView().getBarPosition();
+
+ this._states.barLeft = vPos === "left";
+ this._states.barRight = vPos === "right";
+ this._states.barTop = vPos === "top";
+ this._states.barBottom = vPos === "bottom";
+
+ qx.ui.pageview.AbstractButton.prototype._applyStateAppearance.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/ButtonView.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/ButtonView.js
new file mode 100644
index 0000000000..7521b67683
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/ButtonView.js
@@ -0,0 +1,98 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_buttonview)
+
+************************************************************************ */
+
+/*!
+ One of the widgets which could be used to structurize the interface.
+
+ qx.ui.pageview.buttonview.ButtonView creates the typical apple-like tabview-replacements which could also
+ be found in more modern versions of the settings dialog in Mozilla Firefox.
+*/
+qx.OO.defineClass("qx.ui.pageview.buttonview.ButtonView", qx.ui.pageview.AbstractPageView,
+function()
+{
+ qx.ui.pageview.AbstractPageView.call(this, qx.ui.pageview.buttonview.Bar, qx.ui.pageview.buttonview.Pane);
+
+ this.setOrientation("vertical");
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "barPosition", type : "string", defaultValue : "top", possibleValues : [ "top", "right", "bottom", "left" ] });
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "bar-view" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyBarPosition = function(propValue, propOldValue, propData)
+{
+ var vBar = this._bar;
+
+ // move bar around and change orientation
+ switch(propValue)
+ {
+ case "top":
+ vBar.moveSelfToBegin();
+ this.setOrientation("vertical");
+ break;
+
+ case "bottom":
+ vBar.moveSelfToEnd();
+ this.setOrientation("vertical");
+ break;
+
+ case "left":
+ vBar.moveSelfToBegin();
+ this.setOrientation("horizontal");
+ break;
+
+ case "right":
+ vBar.moveSelfToEnd();
+ this.setOrientation("horizontal");
+ break;
+ }
+
+ // force re-apply of states for bar and pane
+ this._addChildrenToStateQueue();
+
+ // force re-apply of states for all tabs
+ vBar._addChildrenToStateQueue();
+
+ return true;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Page.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Page.js
new file mode 100644
index 0000000000..d5d4b15d4f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Page.js
@@ -0,0 +1,30 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_buttonview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.buttonview.Page", qx.ui.pageview.AbstractPage,
+function(vButton) {
+ qx.ui.pageview.AbstractPage.call(this, vButton);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "bar-view-page" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Pane.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Pane.js
new file mode 100644
index 0000000000..6f8aabebc4
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Pane.js
@@ -0,0 +1,51 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_buttonview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.buttonview.Pane", qx.ui.pageview.AbstractPane,
+function() {
+ qx.ui.pageview.AbstractPane.call(this);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "bar-view-pane" });
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEARANCE ADDITIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyStateAppearance = function()
+{
+ var vPos = this.getParent().getBarPosition();
+
+ this._states.barHorizontal = vPos === "top" || vPos === "bottom";
+
+ qx.ui.pageview.AbstractButton.prototype._applyStateAppearance.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Bar.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Bar.js
new file mode 100644
index 0000000000..22f429dd96
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Bar.js
@@ -0,0 +1,33 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_tabview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.tabview.Bar", qx.ui.pageview.AbstractBar,
+function()
+{
+ qx.ui.pageview.AbstractBar.call(this);
+
+ this.setZIndex(2);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "tab-view-bar" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Button.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Button.js
new file mode 100644
index 0000000000..9566bb2a51
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Button.js
@@ -0,0 +1,189 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_tabview)
+
+************************************************************************ */
+
+/**
+ * @event closetab {qx.event.type.DataEvent}
+ */
+qx.OO.defineClass("qx.ui.pageview.tabview.Button", qx.ui.pageview.AbstractButton,
+function(vText, vIcon, vIconWidth, vIconHeight, vFlash) {
+ qx.ui.pageview.AbstractButton.call(this, vText, vIcon, vIconWidth, vIconHeight, vFlash);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "tab-view-button" });
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+ */
+
+/*!
+ default Close Tab Button
+ */
+qx.OO.addProperty({ name : "showCloseButton", type : "boolean", defaultValue : false });
+
+/*!
+ Close Tab Icon
+ */
+qx.OO.addProperty({ name : "closeButtonImage", type : "string", defaultValue : "icon/16/cancel.png"});
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeydown = function(e)
+{
+ var identifier = e.getKeyIdentifier();
+ if (identifier == "Enter" || identifier == "Space") {
+ // there is no toggeling, just make it checked
+ this.setChecked(true);
+ }
+};
+
+
+qx.Proto._onkeypress = function(e)
+{
+ switch(e.getKeyIdentifier())
+ {
+ case "Left":
+ var vPrev = this.getPreviousSibling() || this.getParent().getLastChild();
+ if (vPrev && vPrev != this)
+ {
+ // we want to enable the outline border, because
+ // the user used the keyboard for activation
+ delete qx.event.handler.FocusHandler.mouseFocus;
+
+ // focus previous tab
+ vPrev.setFocused(true);
+
+ // and naturally make it also checked
+ vPrev.setChecked(true);
+ }
+ break;
+
+ case "Right":
+ var vNext = this.getNextSibling() || this.getParent().getFirstVisibleChild();
+ if (vNext && vNext != this)
+ {
+ // we want to enable the outline border, because
+ // the user used the keyboard for activation
+ delete qx.event.handler.FocusHandler.mouseFocus;
+
+ // focus next tab
+ vNext.setFocused(true);
+
+ // and naturally make it also checked
+ vNext.setChecked(true);
+ }
+ break;
+ }
+};
+
+
+qx.Proto._ontabclose = function(e){
+ this.createDispatchDataEvent("closetab", this);
+}
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+ */
+
+qx.Proto._modifyShowCloseButton = function(propValue, propOldValue, propData) {
+
+ // if no image exists, then create one
+ if (!this._closeButtonImage) {
+ this._closeButtonImage = new qx.ui.basic.Image(this.getCloseButtonImage());
+ }
+ if (propValue) {
+ this._closeButtonImage.addEventListener("click", this._ontabclose, this);
+ this.add(this._closeButtonImage);
+ } else {
+ this.remove(this._closeButtonImage);
+ this._closeButtonImage.removeEventListener("click", this._ontabclose);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyCloseButtonImage = function(propValue, propOldValue, propData) {
+ if (this._closeButtonImage) {
+ this._closeButtonImage.setSource(propValue);
+ }
+
+ return true;
+}
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEARANCE ADDITIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyStateAppearance = function()
+{
+ this._states.firstChild = this.isFirstVisibleChild();
+ this._states.lastChild = this.isLastVisibleChild();
+ this._states.alignLeft = this.getView().getAlignTabsToLeft();
+ this._states.barTop = this.getView().getPlaceBarOnTop();
+
+ qx.ui.pageview.AbstractButton.prototype._applyStateAppearance.call(this);
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+ */
+
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if(this._closeButtonImage){
+ this._closeButtonImage.dispose();
+ this._closeButtonImage = null;
+ }
+
+ return qx.ui.pageview.AbstractButton.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Page.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Page.js
new file mode 100644
index 0000000000..8f1f654ed4
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Page.js
@@ -0,0 +1,30 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_tabview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.tabview.Page", qx.ui.pageview.AbstractPage,
+function(vButton) {
+ qx.ui.pageview.AbstractPage.call(this, vButton);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "tab-view-page" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Pane.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Pane.js
new file mode 100644
index 0000000000..d31d4ee0ae
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Pane.js
@@ -0,0 +1,33 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_tabview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.tabview.Pane", qx.ui.pageview.AbstractPane,
+function()
+{
+ qx.ui.pageview.AbstractPane.call(this);
+
+ this.setZIndex(1);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "tab-view-pane" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/TabView.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/TabView.js
new file mode 100644
index 0000000000..b1cfe9c2b8
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/TabView.js
@@ -0,0 +1,86 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_tabview)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.pageview.tabview.TabView", qx.ui.pageview.AbstractPageView,
+function() {
+ qx.ui.pageview.AbstractPageView.call(this, qx.ui.pageview.tabview.Bar, qx.ui.pageview.tabview.Pane);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "tab-view" });
+
+qx.OO.addProperty({ name : "alignTabsToLeft", type : "boolean", defaultValue : true });
+qx.OO.addProperty({ name : "placeBarOnTop", type : "boolean", defaultValue : true });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyAlignTabsToLeft = function(propValue, propOldValue, propData)
+{
+ var vBar = this._bar;
+
+ vBar.setHorizontalChildrenAlign(propValue ? "left" : "right");
+
+ // force re-apply of states for all tabs
+ vBar._addChildrenToStateQueue();
+
+ return true;
+}
+
+qx.Proto._modifyPlaceBarOnTop = function(propValue, propOldValue, propData)
+{
+ // This does not work if we use flexible zones
+ // this.setReverseChildrenOrder(!propValue);
+
+ var vBar = this._bar;
+
+ // move bar around
+ if (propValue) {
+ vBar.moveSelfToBegin();
+ } else {
+ vBar.moveSelfToEnd();
+ }
+
+ // force re-apply of states for all tabs
+ vBar._addChildrenToStateQueue();
+
+ return true;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/Popup.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/Popup.js
new file mode 100644
index 0000000000..171016d658
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/Popup.js
@@ -0,0 +1,329 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_popup)
+#optional(qx.manager.object.MenuManager)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.popup.Popup", qx.ui.layout.CanvasLayout,
+function()
+{
+ qx.ui.layout.CanvasLayout.call(this);
+
+ this.setZIndex(this._minZIndex);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "popup" });
+
+/*!
+ Whether to let the system decide when to hide the popup. Setting
+ this to false gives you better control but it also requires you
+ to handle the closing of the popup.
+*/
+qx.OO.addProperty({ name : "autoHide", type : "boolean", defaultValue : true });
+
+/*!
+ Make element displayed (if switched to true the widget will be created, if needed, too).
+ Instead of qx.ui.core.Widget, the default is false here.
+*/
+qx.OO.changeProperty({ name : "display", type : "boolean", defaultValue : false });
+
+/*!
+ Center the popup on open
+*/
+qx.OO.addProperty({ name : "centered", type : "boolean", defaultValue : false });
+
+/**
+ * Whether the popup should be restricted to the visible area of the page when opened.
+ */
+qx.OO.addProperty({ name : "restrictToPageOnOpen", type : "boolean", defaultValue : true });
+
+
+qx.Proto._showTimeStamp = (new Date(0)).valueOf();
+qx.Proto._hideTimeStamp = (new Date(0)).valueOf();
+
+
+/**
+ * The minimum offset to the left of the page too keep when
+ * {@link #restrictToPageOnOpen} is true (in pixels).
+ */
+qx.Settings.setDefault("restrictToPageLeft", "5");
+
+/**
+ * The minimum offset to the right of the page too keep when
+ * {@link #restrictToPageOnOpen} is true (in pixels).
+ */
+qx.Settings.setDefault("restrictToPageRight", "5");
+
+/**
+ * The minimum offset to the top of the page too keep when
+ * {@link #restrictToPageOnOpen} is true (in pixels).
+ */
+qx.Settings.setDefault("restrictToPageTop", "5");
+
+/**
+ * The minimum offset to the bottom of the page too keep when
+ * {@link #restrictToPageOnOpen} is true (in pixels).
+ */
+qx.Settings.setDefault("restrictToPageBottom", "5");
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEAR/DISAPPEAR
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._beforeAppear = function()
+{
+ qx.ui.layout.CanvasLayout.prototype._beforeAppear.call(this);
+
+ if (this.getRestrictToPageOnOpen()) {
+ this._wantedLeft = this.getLeft();
+
+ if (this._wantedLeft != null) {
+ // Move the popup out of the view so its size could be calculated before
+ // it is positioned.
+ this.setLeft(10000);
+ if (this.getElement() != null) {
+ // The popup was already visible once before
+ // -> Move it immediately before it gets visible again
+ this.getElement().style.left = 10000;
+ }
+ }
+ }
+
+ qx.manager.object.PopupManager.getInstance().add(this);
+ qx.manager.object.PopupManager.getInstance().update(this);
+
+ this._showTimeStamp = (new Date).valueOf();
+ this.bringToFront();
+}
+
+qx.Proto._beforeDisappear = function()
+{
+ qx.ui.layout.CanvasLayout.prototype._beforeDisappear.call(this);
+
+ qx.manager.object.PopupManager.getInstance().remove(this);
+
+ this._hideTimeStamp = (new Date).valueOf();
+}
+
+qx.Proto._afterAppear = function() {
+ qx.ui.layout.CanvasLayout.prototype._afterAppear.call(this);
+
+ if (this.getRestrictToPageOnOpen()) {
+ var doc = qx.ui.core.ClientDocument.getInstance();
+ var docWidth = doc.getClientWidth();
+ var docHeight = doc.getClientHeight();
+ var restrictToPageLeft = parseInt(qx.Settings.getValueOfClass("qx.ui.popup.Popup", "restrictToPageLeft"));
+ var restrictToPageRight = parseInt(qx.Settings.getValueOfClass("qx.ui.popup.Popup", "restrictToPageRight"));
+ var restrictToPageTop = parseInt(qx.Settings.getValueOfClass("qx.ui.popup.Popup", "restrictToPageTop"));
+ var restrictToPageBottom = parseInt(qx.Settings.getValueOfClass("qx.ui.popup.Popup", "restrictToPageBottom"));
+ var left = (this._wantedLeft == null) ? this.getLeft() : this._wantedLeft;
+ var top = this.getTop();
+ var width = this.getBoxWidth();
+ var height = this.getBoxHeight();
+
+ var oldLeft = this.getLeft();
+ var oldTop = top;
+
+ // NOTE: We check right and bottom first, because top and left should have
+ // priority, when both sides are violated.
+ if (left + width > docWidth - restrictToPageRight) {
+ left = docWidth - restrictToPageRight - width;
+ }
+ if (top + height > docHeight - restrictToPageBottom) {
+ top = docHeight - restrictToPageBottom - height;
+ }
+ if (left < restrictToPageLeft) {
+ left = restrictToPageLeft;
+ }
+ if (top < restrictToPageTop) {
+ top = restrictToPageTop;
+ }
+
+ if (left != oldLeft || top != oldTop) {
+ var self = this;
+ window.setTimeout(function() {
+ self.setLeft(left);
+ self.setTop(top);
+ qx.ui.core.Widget.flushGlobalQueues();
+ }, 0);
+ }
+ }
+};
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ACTIVE/INACTIVE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._makeActive = function() {
+ this.getFocusRoot().setActiveChild(this);
+}
+
+qx.Proto._makeInactive = function()
+{
+ var vRoot = this.getFocusRoot();
+ var vCurrent = vRoot.getActiveChild();
+
+ if (vCurrent == this) {
+ vRoot.setActiveChild(vRoot);
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ FOCUS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.isFocusable = function() {
+ return false;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ZIndex Positioning
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._minZIndex = 1e6;
+
+qx.Proto.bringToFront = function()
+{
+ this.forceZIndex(Infinity);
+ this._sendTo();
+}
+
+qx.Proto.sendToBack = function()
+{
+ this.forceZIndex(-Infinity);
+ this._sendTo();
+}
+
+qx.Proto._sendTo = function()
+{
+ var vPopups = qx.lang.Object.getValues(qx.manager.object.PopupManager.getInstance().getAll());
+ var vMenus = qx.lang.Object.getValues(qx.manager.object.MenuManager.getInstance().getAll());
+
+ var vAll = vPopups.concat(vMenus).sort(qx.util.Compare.byZIndex);
+ var vLength = vAll.length;
+ var vIndex = this._minZIndex;
+
+ for (var i=0; i (p - 5) && e < (p + 5);
+}
+
+qx.Proto._onmousemove = function(e)
+{
+ var s = this._resizeSession;
+
+ if (s)
+ {
+ if (this._resizeWest)
+ {
+ s.lastWidth = qx.lang.Number.limit(s.boxWidth + s.boxLeft - Math.max(e.getPageX(), s.parentAreaOffsetLeft), s.minWidth, s.maxWidth);
+ s.lastLeft = s.boxRight - s.lastWidth - s.parentAreaOffsetLeft;
+ }
+ else if (this._resizeEast)
+ {
+ s.lastWidth = qx.lang.Number.limit(Math.min(e.getPageX(), s.parentAreaOffsetRight) - s.boxLeft, s.minWidth, s.maxWidth);
+ }
+
+ if (this._resizeNorth)
+ {
+ s.lastHeight = qx.lang.Number.limit(s.boxHeight + s.boxTop - Math.max(e.getPageY(), s.parentAreaOffsetTop), s.minHeight, s.maxHeight);
+ s.lastTop = s.boxBottom - s.lastHeight - s.parentAreaOffsetTop;
+ }
+ else if (this._resizeSouth)
+ {
+ s.lastHeight = qx.lang.Number.limit(Math.min(e.getPageY(), s.parentAreaOffsetBottom) - s.boxTop, s.minHeight, s.maxHeight);
+ }
+
+ switch(this.getResizeMethod())
+ {
+ case "opaque":
+ case "translucent":
+ if (this._resizeWest || this._resizeEast)
+ {
+ this.setWidth(s.lastWidth);
+
+ if (this._resizeWest) {
+ this.setLeft(s.lastLeft);
+ }
+ }
+
+ if (this._resizeNorth || this._resizeSouth)
+ {
+ this.setHeight(s.lastHeight);
+
+ if (this._resizeNorth) {
+ this.setTop(s.lastTop);
+ }
+ }
+
+ break;
+
+ default:
+ var o = this.getResizeMethod() == "frame" ? this._frame : this;
+
+ if (this._resizeWest || this._resizeEast)
+ {
+ o._applyRuntimeWidth(s.lastWidth);
+
+ if (this._resizeWest) {
+ o._applyRuntimeLeft(s.lastLeft);
+ }
+ }
+
+ if (this._resizeNorth || this._resizeSouth)
+ {
+ o._applyRuntimeHeight(s.lastHeight);
+
+ if (this._resizeNorth) {
+ o._applyRuntimeTop(s.lastTop);
+ }
+ }
+ }
+ }
+ else
+ {
+ var resizeMode = "";
+ var el = this.getElement();
+
+ this._resizeNorth = this._resizeSouth = this._resizeWest = this._resizeEast = false;
+
+ if (this._near(qx.dom.Location.getPageBoxTop(el), e.getPageY()))
+ {
+ if (this.getResizeableNorth()) {
+ resizeMode = "n";
+ this._resizeNorth = true;
+ }
+ }
+ else if (this._near(qx.dom.Location.getPageBoxBottom(el), e.getPageY()))
+ {
+ if (this.getResizeableSouth()) {
+ resizeMode = "s";
+ this._resizeSouth = true;
+ }
+ }
+
+ if (this._near(qx.dom.Location.getPageBoxLeft(el), e.getPageX()))
+ {
+ if (this.getResizeableWest()) {
+ resizeMode += "w";
+ this._resizeWest = true;
+ }
+ }
+ else if (this._near(qx.dom.Location.getPageBoxRight(el), e.getPageX()))
+ {
+ if (this.getResizeableEast()) {
+ resizeMode += "e";
+ this._resizeEast = true;
+ }
+ }
+
+ if (this._resizeNorth || this._resizeSouth || this._resizeWest || this._resizeEast)
+ {
+ this.setCursor(resizeMode + "-resize");
+ }
+ else
+ {
+ this.setCursor(null);
+ }
+ }
+
+ // stop event
+ e.stopPropagation();
+}
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._frame)
+ {
+ this._frame.dispose();
+ this._frame = null;
+ }
+
+ return qx.ui.layout.CanvasLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/HorizontalSplitPane.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/HorizontalSplitPane.js
new file mode 100644
index 0000000000..898ce097e4
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/HorizontalSplitPane.js
@@ -0,0 +1,58 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Volker Pauli
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_splitpane)
+
+************************************************************************ */
+
+/**
+ *
+ * Creates a new instance of a horizontal SplitPane.
+ *
+ * new qx.ui.splitpane.HorizontalSplitPane()
+ * new qx.ui.splitpane.HorizontalSplitPane(firstSize, secondSize)
+ *
+ * @param firstSize {string} The size of the left pane. Allowed values are any by {@see qx.ui.core.Widget} supported unit.
+ * @param secondSize {string} The size of the right pane. Allowed values are any by {@see qx.ui.core.Widget} supported unit.
+ */
+qx.OO.defineClass("qx.ui.splitpane.HorizontalSplitPane", qx.ui.splitpane.SplitPane,
+function(firstSize, secondSize) {
+ qx.ui.splitpane.SplitPane.call(this, "horizontal", firstSize, secondSize);
+});
+
+
+
+
+
+/*
+------------------------------------------------------------------------------------
+ DISPOSER
+------------------------------------------------------------------------------------
+ */
+
+/**
+ * Garbage collection
+ */
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ return qx.ui.splitpane.SplitPane.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/SplitPane.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/SplitPane.js
new file mode 100644
index 0000000000..b0b817f8ac
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/SplitPane.js
@@ -0,0 +1,759 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Volker Pauli (vpauli)
+ * Sebastian Werner (wpbasti)
+ * Carsten Lergenmueller (carstenL)
+
+ ************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_splitpane)
+
+ ************************************************************************ */
+
+
+/**
+ * Creates a new instance of a SplitPane. It allows the user to dynamically resize
+ * the areas dropping the border between.
+ *
+ * new qx.ui.splitpane.SplitPane(orientation)
+ * new qx.ui.splitpane.SplitPane(orientation, firstSize, secondSize)
+ *
+ * @param orientation {string} The orientation of the splitpane control. Allowed values are "horizontal" (default) and "vertical". This is the same type as used in {@link qx.ui.layout.BoxLayout#orientation}.
+ * @param firstSize {string} The size of the left (top) pane. Allowed values are any by {@link qx.ui.core.Widget} supported unit.
+ * @param secondSize {string} The size of the right (bottom) pane. Allowed values are any by {@link qx.ui.core.Widget} supported unit.
+ */
+qx.OO.defineClass("qx.ui.splitpane.SplitPane", qx.ui.layout.CanvasLayout,
+function(orientation, firstSize, secondSize)
+{
+ qx.ui.layout.CanvasLayout.call(this);
+
+ // CREATE INNER BOX LAYOUT
+ var box = this._box = new qx.ui.layout.BoxLayout;
+ box.setEdge(0);
+ this.add(box);
+
+ /*
+
+ the splitpane itself is a boxlayout resides on top of a canvas for easier computing of positional values
+
+ ---------------------------------------------------------------------------------------
+ | canvas |
+ | ----------------------------------------------------------------------------------- |
+ | | box | |
+ | | --------------------------- --- ----------------------------------------------- | |
+ | | | | | | | | | |
+ | | | firstArea | |s| | secondArea | | |
+ | | | | |p| | | | |
+ | | | | |l| | | | |
+ | | | | |i| | | | |
+ | | | | |t| | | | |
+ | | | | |t| | | | |
+ | | | | |e| | | | |
+ | | | | |r| | | | |
+ | | | | | | | | | |
+ | | --------------------------- --- ----------------------------------------------- | |
+ | ----------------------------------------------------------------------------------- |
+ | |
+ ---------------------------------------------------------------------------------------
+
+ */
+
+ // CREATE SLIDER
+ this._slider = new qx.ui.layout.CanvasLayout;
+ this._slider.setAppearance("splitpane-slider");
+ this._slider.setStyleProperty("fontSize", "0px");
+ this._slider.setStyleProperty("lineHeight", "0px");
+ this._slider.hide();
+ this._slider._pane = this;
+ this.add(this._slider);
+
+ // CREATE SPLITTER
+ this._splitter = new qx.ui.layout.CanvasLayout;
+ this._splitter.setStyleProperty("fontSize", "0px");
+ this._splitter.setStyleProperty("lineHeight", "0px");
+ this._splitter.setAppearance("splitpane-splitter");
+ this._splitter._pane = this;
+
+ // PATCH METHODS
+ this._slider._applyRuntimeLeft = this._splitter._applyRuntimeLeft = this._applyRuntimeLeftWrapper;
+ this._slider._applyRuntimeTop = this._splitter._applyRuntimeTop = this._applyRuntimeTopWrapper;
+
+ // CREATE KNOB
+ this._knob = new qx.ui.basic.Image;
+ this._knob.setAppearance("splitpane-knob");
+ this._knob.setVisibility(false);
+ this.add(this._knob);
+
+ // CREATE AREAS
+ this._firstArea = new qx.ui.layout.CanvasLayout;
+ this._secondArea = new qx.ui.layout.CanvasLayout;
+
+ // FILL BOX
+ box.add(this._firstArea, this._splitter, this._secondArea);
+
+ // APPLY DIMENSIONS
+ this.setFirstSize(firstSize || "1*");
+ this.setSecondSize(secondSize || "1*");
+
+ // APPLY ORIENTATION
+ this.setOrientation(orientation || "horizontal");
+});
+
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+ */
+
+/**
+ * Appearance change
+ */
+qx.OO.changeProperty({ name : "appearance", defaultValue : "splitpane" });
+
+/**
+ * Show the knob
+ */
+qx.OO.addProperty({ name : "showKnob", type : "boolean", allowNull : false, defaultValue : false });
+
+/**
+ * The layout method for the splitpane. If true, the content will updated immediatly.
+ */
+qx.OO.addProperty({ name : "liveResize", type : "boolean", allowNull : false, defaultValue : false, getAlias : "isLiveResize"});
+
+/**
+ * The orientation of the splitpane control. Allowed values are "horizontal" (default) and "vertical".
+ */
+qx.OO.addProperty({ name : "orientation", type : "string", possibleValues : [ "horizontal", "vertical" ] });
+
+/**
+ * The size of the first (left/top) area.
+ */
+qx.OO.addProperty({ name : "firstSize" });
+
+/**
+ * The size of the second (right/bottom) area.
+ */
+qx.OO.addProperty({ name : "secondSize" });
+
+/**
+ * Size of the splitter
+ */
+qx.OO.addProperty({ name : "splitterSize", defaultValue : 4 });
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PUBLIC METHODS
+---------------------------------------------------------------------------
+*/
+
+
+/**
+ * adds one or more widget(s) to the left pane
+ *
+ *@param widget (qx.ui.core.Parent)
+ */
+qx.Proto.addLeft = function() {
+ var c = this.getFirstArea();
+ return c.add.apply(c, arguments);
+}
+
+/**
+ * adds one or more widget(s) to the top pane
+ *
+ *@param widget (qx.ui.core.Parent)
+ */
+qx.Proto.addTop = function() {
+ var c = this.getFirstArea();
+ return c.add.apply(c, arguments);
+}
+
+/**
+ * adds one or more widget(s) to the right pane
+ *
+ *@param widget (qx.ui.core.Parent)
+ */
+qx.Proto.addRight = function() {
+ var c = this.getSecondArea();
+ return c.add.apply(c, arguments);
+}
+
+/**
+ * adds one or more widget(s) to the bottom pane
+ *
+ *@param widget (qx.ui.core.Parent)
+ */
+qx.Proto.addBottom = function() {
+ var c = this.getSecondArea();
+ return c.add.apply(c, arguments);
+}
+
+/**
+ * Returns the splitter.
+ *
+ * @return {qx.ui.core.Widget} The splitter.
+ */
+qx.Proto.getSplitter = function() {
+ return this._splitter;
+}
+
+/**
+ * Returns the knob.
+ *
+ * @return {qx.ui.core.Widget} The knob.
+ */
+qx.Proto.getKnob = function() {
+ return this._knob;
+}
+
+
+
+
+
+
+/**
+ * Returns the left area (CanvasLayout)
+ *
+ * @return {qx.ui.layout.CanvasLayout}
+ */
+qx.Proto.getLeftArea = function() {
+ return this.getFirstArea();
+}
+
+/**
+ * Returns the top area (CanvasLayout)
+ *
+ * @return {qx.ui.layout.CanvasLayout}
+ */
+qx.Proto.getTopArea = function() {
+ return this.getFirstArea();
+}
+
+/**
+ * Returns the right area (CanvasLayout)
+ *
+ * @return {qx.ui.layout.CanvasLayout}
+ */
+qx.Proto.getRightArea = function() {
+ return this.getSecondArea();
+}
+
+/**
+ * Returns the bottom area (CanvasLayout)
+ *
+ * @return {qx.ui.layout.CanvasLayout}
+ */
+qx.Proto.getBottomArea = function() {
+ return this.getSecondArea();
+}
+
+/**
+ * Returns the first area (CanvasLayout)
+ *
+ * @return {qx.ui.layout.CanvasLayout}
+ */
+qx.Proto.getFirstArea = function() {
+ return this._firstArea;
+}
+
+/**
+ * Returns the second area (CanvasLayout)
+ *
+ * @return {qx.ui.layout.CanvasLayout}
+ */
+qx.Proto.getSecondArea = function() {
+ return this._secondArea;
+}
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyShowKnob = function(propValue, propOldValue, propData)
+{
+ this._knob.setVisibility(propValue);
+ return true;
+}
+
+qx.Proto._modifyOrientation = function(propValue, propOldValue, propData)
+{
+ // sync orientation to layout
+ this._box.setOrientation(propValue);
+
+ switch(propOldValue)
+ {
+ case "horizontal":
+ // remove old listeners
+ this._splitter.removeEventListener("mousedown", this._onSplitterMouseDownX, this);
+ this._splitter.removeEventListener("mousemove", this._onSplitterMouseMoveX, this);
+ this._splitter.removeEventListener("mouseup", this._onSplitterMouseUpX, this);
+ this._knob.removeEventListener("mousedown", this._onSplitterMouseDownX, this);
+ this._knob.removeEventListener("mousemove", this._onSplitterMouseMoveX, this);
+ this._knob.removeEventListener("mouseup", this._onSplitterMouseUpX, this);
+
+ // reconfigure states
+ this._splitter.removeState("horizontal");
+ this._knob.removeState("horizontal");
+
+ // reset old dimensions
+ this._firstArea.setWidth(null);
+ this._secondArea.setWidth(null);
+ this._splitter.setWidth(null);
+
+ break;
+
+ case "vertical":
+ // remove old listeners
+ this._splitter.removeEventListener("mousedown", this._onSplitterMouseDownY, this);
+ this._splitter.removeEventListener("mousemove", this._onSplitterMouseMoveY, this);
+ this._splitter.removeEventListener("mouseup", this._onSplitterMouseUpY, this);
+ this._knob.removeEventListener("mousedown", this._onSplitterMouseDownY, this);
+ this._knob.removeEventListener("mousemove", this._onSplitterMouseMoveY, this);
+ this._knob.removeEventListener("mouseup", this._onSplitterMouseUpY, this);
+
+ // reconfigure states
+ this._splitter.removeState("vertical");
+ this._knob.removeState("vertical");
+
+ // reset old dimensions
+ this._firstArea.setHeight(null);
+ this._secondArea.setHeight(null);
+ this._splitter.setHeight(null);
+
+ break;
+ }
+
+ switch(propValue)
+ {
+ case "horizontal":
+ // add new listeners
+ this._splitter.addEventListener("mousemove", this._onSplitterMouseMoveX, this);
+ this._splitter.addEventListener("mousedown", this._onSplitterMouseDownX, this);
+ this._splitter.addEventListener("mouseup", this._onSplitterMouseUpX, this);
+ this._knob.addEventListener("mousemove", this._onSplitterMouseMoveX, this);
+ this._knob.addEventListener("mousedown", this._onSplitterMouseDownX, this);
+ this._knob.addEventListener("mouseup", this._onSplitterMouseUpX, this);
+
+ // reconfigure states
+ this._splitter.addState("horizontal");
+ this._knob.addState("horizontal");
+
+ // apply images
+ this._knob.setSource("widget/splitpane/knob-horizontal.png");
+
+ break;
+
+ case "vertical":
+ // add new listeners
+ this._splitter.addEventListener("mousedown", this._onSplitterMouseDownY, this);
+ this._splitter.addEventListener("mousemove", this._onSplitterMouseMoveY, this);
+ this._splitter.addEventListener("mouseup", this._onSplitterMouseUpY, this);
+ this._knob.addEventListener("mousedown", this._onSplitterMouseDownY, this);
+ this._knob.addEventListener("mousemove", this._onSplitterMouseMoveY, this);
+ this._knob.addEventListener("mouseup", this._onSplitterMouseUpY, this);
+
+ // reconfigure states
+ this._splitter.addState("vertical");
+ this._knob.addState("vertical");
+
+ // apply images
+ this._knob.setSource("widget/splitpane/knob-vertical.png");
+
+ break;
+ }
+
+ // apply new dimensions
+ this._syncFirstSize();
+ this._syncSecondSize();
+ this._syncSplitterSize();
+
+ return true;
+};
+
+qx.Proto._modifyFirstSize = function(propValue, propOldValue, propData)
+{
+ this._syncFirstSize();
+ return true;
+}
+
+qx.Proto._modifySecondSize = function(propValue, propOldValue, propData)
+{
+ this._syncSecondSize();
+ return true;
+}
+
+qx.Proto._modifySplitterSize = function(propValue, propOldValue, propData)
+{
+ this._syncSplitterSize();
+ return true;
+}
+
+qx.Proto._syncFirstSize = function()
+{
+ switch(this.getOrientation())
+ {
+ case "horizontal":
+ this._firstArea.setWidth(this.getFirstSize());
+ break;
+
+ case "vertical":
+ this._firstArea.setHeight(this.getFirstSize());
+ break;
+ }
+}
+
+qx.Proto._syncSecondSize = function()
+{
+ switch(this.getOrientation())
+ {
+ case "horizontal":
+ this._secondArea.setWidth(this.getSecondSize());
+ break;
+
+ case "vertical":
+ this._secondArea.setHeight(this.getSecondSize());
+ break;
+ }
+}
+
+qx.Proto._syncSplitterSize = function()
+{
+ switch(this.getOrientation())
+ {
+ case "horizontal":
+ this._splitter.setWidth(this.getSplitterSize());
+ break;
+
+ case "vertical":
+ this._splitter.setHeight(this.getSplitterSize());
+ break;
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Initializes drag session in case of a mousedown event on splitter in a horizontal splitpane.
+ *
+ * @param e {qx.event.MouseEvent} The event itself.
+ */
+qx.Proto._onSplitterMouseDownX = function(e)
+{
+ if (!e.isLeftButtonPressed()) {
+ return;
+ }
+
+ this._commonMouseDown();
+
+ // activate global cursor
+ this.getTopLevelWidget().setGlobalCursor("col-resize");
+ this._slider.addState("dragging");
+ this._knob.addState("dragging");
+
+ // initialize the drag session
+ this._dragMin = qx.dom.Location.getPageInnerLeft(this._box.getElement());
+ this._dragMax = this._dragMin + this._box.getInnerWidth() - this._splitter.getBoxWidth();
+ this._dragOffset = e.getPageX() - qx.dom.Location.getPageBoxLeft(this._splitter.getElement());
+}
+
+/**
+ * Initializes drag session in case of a mousedown event on splitter in a vertical splitpane.
+ *
+ * @param e {qx.event.MouseEvent} The event itself.
+ */
+qx.Proto._onSplitterMouseDownY = function(e)
+{
+ if (!e.isLeftButtonPressed()) {
+ return;
+ }
+
+ this._commonMouseDown();
+
+ // activate global cursor
+ this.getTopLevelWidget().setGlobalCursor("row-resize");
+ this._slider.addState("dragging");
+ this._knob.addState("dragging");
+
+ // initialize the drag session
+ // dragStart = position of layout + mouse offset on splitter
+ this._dragMin = qx.dom.Location.getPageInnerTop(this._box.getElement());
+ this._dragMax = this._dragMin + this._box.getInnerHeight() - this._splitter.getBoxHeight();
+ this._dragOffset = e.getPageY() - qx.dom.Location.getPageBoxTop(this._splitter.getElement());
+}
+
+qx.Proto._commonMouseDown = function()
+{
+ // enable capturing
+ this._splitter.setCapture(true);
+
+ // initialize the slider
+ if(!this.isLiveResize())
+ {
+ this._slider.setLeft(this._splitter.getOffsetLeft());
+ this._slider.setTop(this._splitter.getOffsetTop());
+ this._slider.setWidth(this._splitter.getBoxWidth());
+ this._slider.setHeight(this._splitter.getBoxHeight());
+
+ this._slider.show();
+ }
+}
+
+
+
+
+
+
+
+
+/**
+ * Move the splitter in case of a mousemove event on splitter in a horizontal splitpane.
+ *
+ * @param e {qx.event.MouseEvent} The event itself.
+ */
+qx.Proto._onSplitterMouseMoveX = function(e)
+{
+ if (!this._splitter.getCapture()) {
+ return;
+ }
+
+ this.isLiveResize() ? this._syncX(e) : this._slider._applyRuntimeLeft(this._normalizeX(e));
+ e.preventDefault();
+}
+
+/**
+ * Move the splitter in case of a mousemove event on splitter in a vertical splitpane.
+ *
+ * @param e {qx.event.MouseEvent} The event itself.
+ */
+qx.Proto._onSplitterMouseMoveY = function(e)
+{
+ if (!this._splitter.getCapture()) {
+ return;
+ }
+
+ this.isLiveResize() ? this._syncY(e) : this._slider._applyRuntimeTop(this._normalizeY(e));
+ e.preventDefault();
+}
+
+
+
+
+
+
+
+/**
+ * Ends the drag session and computes the new dimensions of panes in case of a mouseup event on splitter in a horizontal splitpane.
+ *
+ * @param e {qx.event.MouseEvent} The event itself.
+ */
+qx.Proto._onSplitterMouseUpX = function(e)
+{
+ if (!this._splitter.getCapture()) {
+ return;
+ }
+
+ if(!this.isLiveResize()) {
+ this._syncX(e);
+ }
+
+ this._commonMouseUp();
+}
+
+/**
+ * Ends the drag session and computes the new dimensions of panes in case of a mouseup event on splitter in a vertical splitpane.
+ *
+ * @param e {qx.event.MouseEvent} The event itself.
+ */
+qx.Proto._onSplitterMouseUpY = function(e)
+{
+ if (!this._splitter.getCapture()) {
+ return;
+ }
+
+ if(!this.isLiveResize()) {
+ this._syncY(e);
+ }
+
+ this._commonMouseUp();
+}
+
+qx.Proto._commonMouseUp = function()
+{
+ // hide helpers
+ this._slider.hide();
+
+ // disable capturing
+ this._splitter.setCapture(false);
+
+ // reset the global cursor
+ this.getTopLevelWidget().setGlobalCursor(null);
+
+ // cleanup dragsession
+ this._slider.removeState("dragging");
+ this._knob.removeState("dragging");
+}
+
+qx.Proto._syncX = function(e)
+{
+ var first = this._normalizeX(e);
+ var second = this._box.getInnerWidth() - this._splitter.getBoxWidth() - first;
+
+ this._syncCommon(first, second);
+}
+
+qx.Proto._syncY = function(e)
+{
+ var first = this._normalizeY(e);
+ var second = this._box.getInnerHeight() - this._splitter.getBoxHeight() - first;
+
+ this._syncCommon(first, second);
+}
+
+qx.Proto._syncCommon = function(first, second)
+{
+ this.setFirstSize(first + "*");
+ this.setSecondSize(second + "*");
+}
+
+qx.Proto._normalizeX = function(e) {
+ return qx.lang.Number.limit(e.getPageX() - this._dragOffset, this._dragMin, this._dragMax) - this._dragMin;
+}
+
+qx.Proto._normalizeY = function(e) {
+ return qx.lang.Number.limit(e.getPageY() - this._dragOffset, this._dragMin, this._dragMax) - this._dragMin;
+}
+
+qx.Proto._applyRuntimeLeftWrapper = function(v)
+{
+ if (this._pane.getOrientation() == "horizontal") {
+ this._pane._knob._applyRuntimeLeft(v);
+ }
+
+ return this.constructor.prototype._applyRuntimeLeft.call(this, v);
+}
+
+qx.Proto._applyRuntimeTopWrapper = function(v)
+{
+ if (this._pane.getOrientation() == "vertical") {
+ this._pane._knob._applyRuntimeTop(v);
+ }
+
+ return this.constructor.prototype._applyRuntimeTop.call(this, v);
+}
+
+
+
+
+
+/*
+------------------------------------------------------------------------------------
+ DISPOSER
+------------------------------------------------------------------------------------
+ */
+
+/**
+ * Garbage collection
+ */
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if(this._firstArea)
+ {
+ this._firstArea.dispose();
+ this._firstArea = null;
+ }
+
+ if(this._secondArea)
+ {
+ this._secondArea.dispose();
+ this._secondArea = null;
+ }
+
+ if (this._splitter)
+ {
+ this._splitter.removeEventListener("mousedown", this._onSplitterMouseDownX, this);
+ this._splitter.removeEventListener("mouseup", this._onSplitterMouseMoveX, this);
+ this._splitter.removeEventListener("mousemove", this._onSplitterMouseUpX, this);
+
+ this._splitter.removeEventListener("mousedown", this._onSplitterMouseDownY, this);
+ this._splitter.removeEventListener("mouseup", this._onSplitterMouseMoveY, this);
+ this._splitter.removeEventListener("mousemove", this._onSplitterMouseUpY, this);
+
+ this._splitter.dispose();
+ this._splitter._pane = null;
+ this._splitter = null;
+ }
+
+ if (this._slider)
+ {
+ this._slider.dispose();
+ this._slider._pane = null;
+ this._slider = null;
+ }
+
+ if (this._knob)
+ {
+ this._knob.removeEventListener("mousedown", this._onSplitterMouseDownX, this);
+ this._knob.removeEventListener("mouseup", this._onSplitterMouseMoveX, this);
+ this._knob.removeEventListener("mousemove", this._onSplitterMouseUpX, this);
+
+ this._knob.removeEventListener("mousedown", this._onSplitterMouseDownY, this);
+ this._knob.removeEventListener("mouseup", this._onSplitterMouseMoveY, this);
+ this._knob.removeEventListener("mousemove", this._onSplitterMouseUpY, this);
+
+ this._knob.dispose();
+ this._knob = null;
+ }
+
+ return qx.ui.layout.BoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/VerticalSplitPane.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/VerticalSplitPane.js
new file mode 100644
index 0000000000..76201484a3
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/VerticalSplitPane.js
@@ -0,0 +1,58 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Volker Pauli
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_splitpane)
+
+************************************************************************ */
+
+/**
+ *
+ * Creates a new instance of a vertical SplitPane.
+ *
+ * new qx.ui.splitpane.VerticalSplitPane()
+ * new qx.ui.splitpane.VerticalSplitPane(firstSize, secondSize)
+ *
+ * @param firstSize {string} The size of the top pane. Allowed values are any by {@see qx.ui.core.Widget} supported unit.
+ * @param secondSize {string} The size of the bottom pane. Allowed values are any by {@see qx.ui.core.Widget} supported unit.
+ */
+qx.OO.defineClass("qx.ui.splitpane.VerticalSplitPane", qx.ui.splitpane.SplitPane,
+function(firstSize, secondSize) {
+ qx.ui.splitpane.SplitPane.call(this, "vertical", firstSize, secondSize);
+});
+
+
+
+
+
+/*
+------------------------------------------------------------------------------------
+ DISPOSER
+------------------------------------------------------------------------------------
+ */
+
+/**
+ * Garbage collection
+ */
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ return qx.ui.splitpane.SplitPane.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/AbstractDataCellRenderer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/AbstractDataCellRenderer.js
new file mode 100644
index 0000000000..d3d7950bd5
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/AbstractDataCellRenderer.js
@@ -0,0 +1,127 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * An abstract data cell renderer that does the basic coloring
+ * (borders, selected look, ...).
+ */
+qx.OO.defineClass("qx.ui.table.AbstractDataCellRenderer", qx.ui.table.DataCellRenderer,
+function() {
+ qx.ui.table.DataCellRenderer.call(this);
+});
+
+
+// overridden
+qx.Proto.createDataCellHtml = function(cellInfo) {
+ var AbstractDataCellRenderer = qx.ui.table.AbstractDataCellRenderer;
+ return AbstractDataCellRenderer.MAIN_DIV_START + this._getCellStyle(cellInfo)
+ + AbstractDataCellRenderer.MAIN_DIV_START_END
+ + this._getContentHtml(cellInfo) + AbstractDataCellRenderer.MAIN_DIV_END;
+}
+
+
+// overridden
+qx.Proto.updateDataCellElement = function(cellInfo, cellElement) {
+ cellElement.innerHTML = this._getContentHtml(cellInfo);
+}
+
+
+/**
+ * Returns the CSS styles that should be applied to the main div of this cell.
+ *
+ * @param cellInfo {Map} The information about the cell.
+ * See {@link #createDataCellHtml}.
+ * @return the CSS styles of the main div.
+ */
+qx.Proto._getCellStyle = function(cellInfo) {
+ return cellInfo.style + qx.ui.table.AbstractDataCellRenderer.MAIN_DIV_STYLE;
+}
+
+
+/**
+ * Returns the HTML that should be used inside the main div of this cell.
+ *
+ * @param cellInfo {Map} The information about the cell.
+ * See {@link #createDataCellHtml}.
+ * @return {string} the inner HTML of the main div.
+ */
+qx.Proto._getContentHtml = function(cellInfo) {
+ return cellInfo.value;
+}
+
+
+qx.Proto.createDataCellHtml_array_join = function(cellInfo, htmlArr) {
+ var AbstractDataCellRenderer = qx.ui.table.AbstractDataCellRenderer;
+
+ if (qx.ui.table.TablePane.USE_TABLE) {
+ htmlArr.push(AbstractDataCellRenderer.TABLE_TD);
+ htmlArr.push(cellInfo.styleHeight);
+ htmlArr.push("px");
+ } else {
+ htmlArr.push(AbstractDataCellRenderer.ARRAY_JOIN_MAIN_DIV_LEFT);
+ htmlArr.push(cellInfo.styleLeft);
+ htmlArr.push(AbstractDataCellRenderer.ARRAY_JOIN_MAIN_DIV_WIDTH);
+ htmlArr.push(cellInfo.styleWidth);
+ htmlArr.push(AbstractDataCellRenderer.ARRAY_JOIN_MAIN_DIV_HEIGHT);
+ htmlArr.push(cellInfo.styleHeight);
+ htmlArr.push("px");
+ }
+
+ this._createCellStyle_array_join(cellInfo, htmlArr);
+
+ htmlArr.push(AbstractDataCellRenderer.ARRAY_JOIN_MAIN_DIV_START_END);
+
+ this._createContentHtml_array_join(cellInfo, htmlArr);
+
+ if (qx.ui.table.TablePane.USE_TABLE) {
+ htmlArr.push(AbstractDataCellRenderer.TABLE_TD_END);
+ } else {
+ htmlArr.push(AbstractDataCellRenderer.ARRAY_JOIN_MAIN_DIV_END);
+ }
+}
+
+
+qx.Proto._createCellStyle_array_join = function(cellInfo, htmlArr) {
+ htmlArr.push(qx.ui.table.AbstractDataCellRenderer.MAIN_DIV_STYLE);
+}
+
+
+qx.Proto._createContentHtml_array_join = function(cellInfo, htmlArr) {
+ htmlArr.push(cellInfo.value);
+}
+
+
+qx.Class.MAIN_DIV_START = '';
+qx.Class.MAIN_DIV_END = '
';
+qx.Class.MAIN_DIV_STYLE = ';overflow:hidden;white-space:nowrap;border-right:1px solid #eeeeee;border-bottom:1px solid #eeeeee;padding-left:2px;padding-right:2px;cursor:default'
+ + (qx.sys.Client.getInstance().isMshtml() ? '' : ';-moz-user-select:none;');
+
+qx.Class.ARRAY_JOIN_MAIN_DIV_LEFT = '';
+qx.Class.ARRAY_JOIN_MAIN_DIV_END = '
';
+
+qx.Class.TABLE_TD = '
+ * Note: This will clear previously set column names.
+ *
+ *
+ * @param columnIdArr {string[]} the IDs of the columns.
+ * @see #setColumns
+ */
+qx.Proto.setColumnIds = function(columnIdArr) {
+ this._columnIdArr = columnIdArr;
+
+ // Create the reverse map
+ this._columnIndexMap = {};
+ for (var i = 0; i < columnIdArr.length; i++) {
+ this._columnIndexMap[columnIdArr[i]] = i;
+ }
+ this._columnNameArr = new Array(columnIdArr.length);
+
+ // Inform the listeners
+ if (!this._internalChange) {
+ this.createDispatchEvent(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED);
+ }
+}
+
+
+/**
+ * Sets the column names. These names will be shown to the user.
+ *
+ * Note: The column IDs have to be defined before.
+ *
+ *
+ * @param columnNameArr {string[]} the names of the columns.
+ * @see #setColumnIds
+ */
+qx.Proto.setColumnNamesByIndex = function(columnNameArr) {
+ if (this._columnIdArr.length != columnNameArr.length) {
+ throw new Error("this._columnIdArr and columnNameArr have different length: "
+ + this._columnIdArr.length + " != " + columnNameArr.length);
+ }
+ this._columnNameArr = columnNameArr;
+
+ // Inform the listeners
+ this.createDispatchEvent(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED);
+}
+
+
+/**
+ * Sets the column names. These names will be shown to the user.
+ *
+ * Note: The column IDs have to be defined before.
+ *
+ *
+ * @param columnNameMap {Map} a map containing the column IDs as keys and the
+ * column name as values.
+ * @see #setColumnIds
+ */
+qx.Proto.setColumnNamesById = function(columnNameMap) {
+ this._columnNameArr = new Array(this._columnIdArr.length);
+ for (var i = 0; i < this._columnIdArr.length; ++i) {
+ this._columnNameArr[i] = columnNameMap[this._columnIdArr[i]];
+ }
+}
+
+
+/**
+ * Sets the columns.
+ *
+ * @param columnNameArr {string[]} The column names. These names will be shown to
+ * the user.
+ * @param columnIdArr {string[] ? null} The column IDs. These IDs may be used
+ * internally to identify a column. If null, the column names are used as
+ * IDs.
+ */
+qx.Proto.setColumns = function(columnNameArr, columnIdArr) {
+ if (columnIdArr == null) {
+ columnIdArr = columnNameArr;
+ }
+
+ if (columnIdArr.length != columnNameArr.length) {
+ throw new Error("columnIdArr and columnNameArr have different length: "
+ + columnIdArr.length + " != " + columnNameArr.length);
+ }
+
+ this._internalChange = true;
+ this.setColumnIds(columnIdArr);
+ this._internalChange = false;
+ this.setColumnNamesByIndex(columnNameArr);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/BooleanDataCellRenderer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/BooleanDataCellRenderer.js
new file mode 100644
index 0000000000..13df2cd2f4
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/BooleanDataCellRenderer.js
@@ -0,0 +1,48 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+ * Carsten Lergenmueller (carstenl)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A data cell renderer for boolean values.
+ */
+qx.OO.defineClass("qx.ui.table.BooleanDataCellRenderer", qx.ui.table.IconDataCellRenderer,
+function() {
+ qx.ui.table.IconDataCellRenderer.call(this);
+
+ this._iconUrlTrue = qx.manager.object.AliasManager.getInstance().resolvePath("widget/table/boolean-true.png");
+ this._iconUrlFalse = qx.manager.object.AliasManager.getInstance().resolvePath("widget/table/boolean-false.png");
+ this._iconUrlNull = qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif");
+
+});
+
+//overridden
+qx.Proto._identifyImage = function(cellInfo) {
+ var IconDataCellRenderer = qx.ui.table.IconDataCellRenderer;
+ var imageHints = { imageWidth:11, imageHeight:11 };
+ switch (cellInfo.value) {
+ case true: imageHints.url = this._iconUrlTrue; break;
+ case false: imageHints.url = this._iconUrlFalse; break;
+ default: imageHints.url = this._iconUrlNull; break;
+ }
+ return imageHints;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/CellEditorFactory.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/CellEditorFactory.js
new file mode 100644
index 0000000000..817954f40f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/CellEditorFactory.js
@@ -0,0 +1,62 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A factory creating widgets to use for editing table cells.
+ */
+qx.OO.defineClass("qx.ui.table.CellEditorFactory", qx.core.Object,
+function() {
+ qx.core.Object.call(this);
+});
+
+
+/**
+ * Creates a cell editor.
+ *
+ * The cellInfo map contains the following properties:
+ *
+ * value (var): the cell's value.
+ * row (int): the model index of the row the cell belongs to.
+ * col (int): the model index of the column the cell belongs to.
+ * xPos (int): the x position of the cell in the table pane.
+ *
+ *
+ * @param cellInfo {Map} A map containing the information about the cell to
+ * create.
+ * @return {qx.ui.core.Widget} the widget that should be used as cell editor.
+ */
+qx.Proto.createCellEditor = function(cellInfo) {
+ throw new Error("createCellEditor is abstract");
+}
+
+
+/**
+ * Returns the current value of a cell editor.
+ *
+ * @param cellEditor {qx.ui.core.Widget} The cell editor formally created by
+ * {@link #createCellEditor}.
+ * @return {var} the current value from the editor.
+ */
+qx.Proto.getCellEditorValue = function(cellEditor) {
+ throw new Error("getCellEditorValue is abstract");
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/CheckBoxCellEditorFactory.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/CheckBoxCellEditorFactory.js
new file mode 100644
index 0000000000..d5609a4b77
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/CheckBoxCellEditorFactory.js
@@ -0,0 +1,43 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by David Perez
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * David Perez (david-perez)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * For editing boolean data in a checkbox. It is advisable to use this in conjuntion with BooleanDataCellRenderer.
+ */
+qx.OO.defineClass("qx.ui.table.CheckBoxCellEditorFactory", qx.ui.table.CellEditorFactory, function() {
+ qx.ui.table.CellEditorFactory.call(this);
+});
+
+// overridden
+qx.Proto.createCellEditor = function(cellInfo) {
+ var editor = new qx.ui.form.CheckBox;
+ with (editor) {
+ setChecked(cellInfo.value);
+ }
+ return editor;
+}
+
+// overridden
+qx.Proto.getCellEditorValue = function(cellEditor) {
+ return cellEditor.getChecked();
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DataCellRenderer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DataCellRenderer.js
new file mode 100644
index 0000000000..46f808df32
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DataCellRenderer.js
@@ -0,0 +1,80 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A cell renderer for data cells.
+ */
+qx.OO.defineClass("qx.ui.table.DataCellRenderer", qx.core.Object,
+function() {
+ qx.core.Object.call(this);
+});
+
+
+/**
+ * Creates the HTML for a data cell.
+ *
+ * The cellInfo map contains the following properties:
+ *
+ * value (var): the cell's value.
+ * rowData (var): contains the row data for the row, the cell belongs to.
+ * The kind of this object depends on the table model, see
+ * {@link TableModel#getRowData()}
+ * row (int): the model index of the row the cell belongs to.
+ * col (int): the model index of the column the cell belongs to.
+ * table (qx.ui.table.Table): the table the cell belongs to.
+ * xPos (int): the x position of the cell in the table pane.
+ * selected (boolean): whether the cell is selected.
+ * focusedCol (boolean): whether the cell is in the same column as the
+ * focused cell.
+ * focusedRow (boolean): whether the cell is in the same row as the
+ * focused cell.
+ * editable (boolean): whether the cell is editable.
+ * style (string): The CSS styles that should be applied to the outer HTML
+ * element.
+ *
+ *
+ * @param cellInfo {Map} A map containing the information about the cell to
+ * create.
+ * @return {string} the HTML of the data cell.
+ */
+qx.Proto.createDataCellHtml = function(cellInfo) {
+ throw new Error("createDataCellHtml is abstract");
+}
+
+
+/**
+ * Updates a data cell.
+ *
+ * @param cellInfo {Map} A map containing the information about the cell to
+ * create. This map has the same structure as in {@link #createDataCell}.
+ * @param cellElement {element} the DOM element that renders the data cell. This
+ * is the same element formally created by the HTML from {@link #createDataCell}.
+ */
+qx.Proto.updateDataCellElement = function(cellInfo, cellElement) {
+ throw new Error("updateDataCellElement is abstract");
+}
+
+
+qx.Proto.createDataCellHtml_array_join = function(cellInfo, htmlArr) {
+ throw new Error("createDataCellHtml_array_join is abstract");
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DataRowRenderer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DataRowRenderer.js
new file mode 100644
index 0000000000..9cd4c86961
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DataRowRenderer.js
@@ -0,0 +1,54 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A cell renderer for data rows.
+ */
+qx.OO.defineClass("qx.ui.table.DataRowRenderer", qx.core.Object,
+function() {
+ qx.core.Object.call(this);
+});
+
+
+/**
+ * Updates a data row.
+ *
+ * The rowInfo map contains the following properties:
+ *
+ * rowData (var): contains the row data for the row.
+ * The kind of this object depends on the table model, see
+ * {@link TableModel#getRowData()}
+ * row (int): the model index of the row.
+ * selected (boolean): whether a cell in this row is selected.
+ * focusedRow (boolean): whether the focused cell is in this row.
+ * table (qx.ui.table.Table): the table the row belongs to.
+ *
+ *
+ * @param rowInfo {Map} A map containing the information about the row to
+ * update. This map has the same structure as in {@link #createDataCell}.
+ * @param cellElement {element} the DOM element that renders the data rot. This
+ * is the same element formally created by the HTML from {@link #createDataCell}.
+ */
+qx.Proto.updateDataRowElement = function(rowInfo, rowElement) {
+ throw new Error("updateDataRowElement is abstract");
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultDataCellRenderer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultDataCellRenderer.js
new file mode 100644
index 0000000000..4de4341037
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultDataCellRenderer.js
@@ -0,0 +1,189 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+// This is needed because of the instantiation at the end of this file.
+// I don't think this is a good idea. (wpbasti)
+#require(qx.util.format.NumberFormat)
+
+************************************************************************ */
+
+/**
+ * The default data cell renderer.
+ */
+qx.OO.defineClass("qx.ui.table.DefaultDataCellRenderer", qx.ui.table.AbstractDataCellRenderer,
+function() {
+ qx.ui.table.AbstractDataCellRenderer.call(this);
+});
+
+
+/**
+ * Whether the alignment should automatically be set according to the cell value.
+ * If true numbers will be right-aligned.
+ */
+qx.OO.addProperty({ name:"useAutoAlign", type:"boolean", defaultValue:true, allowNull:false });
+
+
+// overridden
+qx.Proto._getCellStyle = function(cellInfo) {
+ var style = qx.ui.table.AbstractDataCellRenderer.prototype._getCellStyle(cellInfo);
+
+ var stylesToApply = this._getStyleFlags(cellInfo);
+ if (stylesToApply & qx.ui.table.DefaultDataCellRenderer.STYLEFLAG_ALIGN_RIGHT){
+ style += ";text-align:right";
+ }
+ if (stylesToApply & qx.ui.table.DefaultDataCellRenderer.STYLEFLAG_BOLD){
+ style += ";font-weight:bold";
+ }
+ if (stylesToApply & qx.ui.table.DefaultDataCellRenderer.STYLEFLAG_ITALIC){
+ style += ";font-style:italic";
+ }
+
+ return style;
+}
+
+/**
+ * Determines the styles to apply to the cell
+ *
+ * @param cellInfo {Object} cellInfo of the cell
+ * @return the sum of any of the STYLEFLAGS defined below
+ */
+qx.Proto._getStyleFlags = function(cellInfo) {
+ if (this.getUseAutoAlign()) {
+ if (typeof cellInfo.value == "number") {
+ return qx.ui.table.DefaultDataCellRenderer.STYLEFLAG_ALIGN_RIGHT;
+ }
+ }
+}
+
+
+// overridden
+qx.Proto._getContentHtml = function(cellInfo) {
+ return qx.ui.table.DefaultDataCellRenderer.escapeHtml(this._formatValue(cellInfo));
+}
+
+
+// overridden
+qx.Proto.updateDataCellElement = function(cellInfo, cellElement) {
+ var style = qx.ui.table.AbstractDataCellRenderer.prototype._getCellStyle(cellInfo);
+
+ var stylesToApply = this._getStyleFlags(cellInfo);
+ if (stylesToApply & qx.ui.table.DefaultDataCellRenderer.STYLEFLAG_ALIGN_RIGHT){
+ cellElement.style.textAlign = "right";
+ } else {
+ cellElement.style.textAlign = "";
+ }
+
+ if (stylesToApply & qx.ui.table.DefaultDataCellRenderer.STYLEFLAG_BOLD){
+ cellElement.style.fontWeight = "bold";
+ } else {
+ cellElement.style.fontWeight = "";
+ }
+
+ if (stylesToApply & qx.ui.table.DefaultDataCellRenderer.STYLEFLAG_ITALIC){
+ cellElement.style.fontStyle = "ital";
+ } else {
+ cellElement.style.fontStyle = "";
+ }
+
+ var textNode = cellElement.firstChild;
+ if (textNode != null) {
+ textNode.nodeValue = this._formatValue(cellInfo);
+ } else {
+ cellElement.innerHTML = qx.ui.table.DefaultDataCellRenderer.escapeHtml(this._formatValue(cellInfo));
+ }
+}
+
+
+/**
+ * Formats a value.
+ *
+ * @param cellInfo {Map} A map containing the information about the cell to
+ * create. This map has the same structure as in
+ * {@link DataCellRenderer#createDataCell}.
+ * @return {string} the formatted value.
+ */
+qx.Proto._formatValue = function(cellInfo) {
+ var value = cellInfo.value;
+ if (value == null) {
+ return "";
+ } else if (typeof value == "number") {
+ return qx.ui.table.DefaultDataCellRenderer._numberFormat.format(value);
+ } else if (value instanceof Date) {
+ return qx.util.format.DateFormat.getDateInstance().format(value);
+ } else {
+ return value;
+ }
+}
+
+
+qx.Proto._createCellStyle_array_join = function(cellInfo, htmlArr) {
+ qx.ui.table.AbstractDataCellRenderer.prototype._createCellStyle_array_join(cellInfo, htmlArr);
+
+ var stylesToApply = this._getStyleFlags(cellInfo);
+ if (stylesToApply & qx.ui.table.DefaultDataCellRenderer.STYLEFLAG_ALIGN_RIGHT){
+ htmlArr.push(";text-align:right");
+ }
+ if (stylesToApply & qx.ui.table.DefaultDataCellRenderer.STYLEFLAG_BOLD){
+ htmlArr.push(";font-weight:bold");
+ }
+ if (stylesToApply & qx.ui.table.DefaultDataCellRenderer.STYLEFLAG_ITALIC){
+ htmlArr.push(";font-style:italic");
+ }
+}
+
+
+qx.Proto._createContentHtml_array_join = function(cellInfo, htmlArr) {
+ htmlArr.push(qx.ui.table.DefaultDataCellRenderer.escapeHtml(this._formatValue(cellInfo)));
+}
+
+
+/**
+ * Escapes special HTML characters by their entities.
+ *
+ * @param html {string} The HTML to escape.
+ * @return {string} The escaped string showing HTML code as plain text.
+ */
+qx.Class.escapeHtml = function(html) {
+ return html.replace(/[<>&]/gi, qx.ui.table.DefaultDataCellRenderer._escapeHtmlReplacer);
+}
+
+
+/**
+ * Helper method for {@link #escapeHtml}.
+ */
+qx.Class._escapeHtmlReplacer = function(str) {
+ switch(str) {
+ case "<": return "<";
+ case ">": return ">";
+ case "&": return "&";
+ }
+}
+
+
+qx.Class._numberFormat = new qx.util.format.NumberFormat();
+qx.Class._numberFormat.setMaximumFractionDigits(2);
+
+qx.Class.STYLEFLAG_ALIGN_RIGHT = 1;
+qx.Class.STYLEFLAG_BOLD = 2;
+qx.Class.STYLEFLAG_ITALIC = 4;
+
+
+
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultDataRowRenderer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultDataRowRenderer.js
new file mode 100644
index 0000000000..8fd2198cd4
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultDataRowRenderer.js
@@ -0,0 +1,106 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * The default data row renderer.
+ */
+qx.OO.defineClass("qx.ui.table.DefaultDataRowRenderer", qx.ui.table.DataRowRenderer,
+function() {
+ qx.ui.table.DataRowRenderer.call(this);
+});
+
+
+/** Whether the focused row should be highlighted. */
+qx.OO.addProperty({ name:"highlightFocusRow", type:"boolean", allowNull:false, defaultValue:true});
+
+/**
+ * Whether the focused row and the selection should be grayed out when the table
+ * hasn't the focus.
+ */
+qx.OO.addProperty({ name:"visualizeFocusedState", type:"boolean", allowNull:false, defaultValue:true});
+
+
+// overridden
+qx.Proto.updateDataRowElement = function(rowInfo, rowElem) {
+ var clazz = qx.ui.table.DefaultDataRowRenderer;
+
+ if (rowInfo.focusedRow && this.getHighlightFocusRow()) {
+ if (rowInfo.table.getFocused() || !this.getVisualizeFocusedState()) {
+ rowElem.style.backgroundColor = rowInfo.selected ? clazz.BGCOL_FOCUSED_SELECTED : clazz.BGCOL_FOCUSED;
+ } else {
+ rowElem.style.backgroundColor = rowInfo.selected ? clazz.BGCOL_FOCUSED_SELECTED_BLUR : clazz.BGCOL_FOCUSED_BLUR;
+ }
+ } else {
+ if (rowInfo.selected) {
+ if (rowInfo.table.getFocused() || !this.getVisualizeFocusedState()) {
+ rowElem.style.backgroundColor = clazz.BGCOL_SELECTED;
+ } else {
+ rowElem.style.backgroundColor = clazz.BGCOL_SELECTED_BLUR;
+ }
+ } else {
+ rowElem.style.backgroundColor = (rowInfo.row % 2 == 0) ? clazz.BGCOL_EVEN : clazz.BGCOL_ODD;
+ }
+ }
+ rowElem.style.color = rowInfo.selected ? clazz.COL_SELECTED : clazz.COL_NORMAL;
+}
+
+
+qx.Proto._createRowStyle_array_join = function(rowInfo, htmlArr) {
+ var clazz = qx.ui.table.DefaultDataRowRenderer;
+
+ htmlArr.push(clazz.ARRAY_JOIN_BG_COLOR);
+ if (rowInfo.focusedRow && this.getHighlightFocusRow()) {
+ if (rowInfo.table.getFocused() || !this.getVisualizeFocusedState()) {
+ htmlArr.push(rowInfo.selected ? clazz.BGCOL_FOCUSED_SELECTED : clazz.BGCOL_FOCUSED);
+ } else {
+ htmlArr.push(rowInfo.selected ? clazz.BGCOL_FOCUSED_SELECTED_BLUR : clazz.BGCOL_FOCUSED_BLUR);
+ }
+ } else {
+ if (rowInfo.selected) {
+ if (rowInfo.table.getFocused() || !this.getVisualizeFocusedState()) {
+ htmlArr.push(clazz.BGCOL_SELECTED);
+ } else {
+ htmlArr.push(clazz.BGCOL_SELECTED_BLUR);
+ }
+ } else {
+ htmlArr.push((rowInfo.row % 2 == 0) ? clazz.BGCOL_EVEN : clazz.BGCOL_ODD);
+ }
+ }
+ htmlArr.push(clazz.ARRAY_JOIN_COLOR);
+ htmlArr.push(rowInfo.selected ? clazz.COL_SELECTED : clazz.COL);
+}
+
+
+qx.Class.BGCOL_FOCUSED_SELECTED = "#5a8ad3";
+qx.Class.BGCOL_FOCUSED_SELECTED_BLUR = "#b3bac6";
+qx.Class.BGCOL_FOCUSED = "#ddeeff";
+qx.Class.BGCOL_FOCUSED_BLUR = "#dae0e7";
+qx.Class.BGCOL_SELECTED = "#335ea8";
+qx.Class.BGCOL_SELECTED_BLUR = "#989ea8";
+qx.Class.BGCOL_EVEN = "#faf8f3";
+qx.Class.BGCOL_ODD = "white";
+qx.Class.COL_SELECTED = "white";
+qx.Class.COL_NORMAL = "black";
+
+qx.Class.ARRAY_JOIN_BG_COLOR = ";background-color:";
+qx.Class.ARRAY_JOIN_COLOR = ';color:';
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultHeaderCellRenderer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultHeaderCellRenderer.js
new file mode 100644
index 0000000000..060b095a14
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultHeaderCellRenderer.js
@@ -0,0 +1,63 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * The default header cell renderer.
+ */
+qx.OO.defineClass("qx.ui.table.DefaultHeaderCellRenderer", qx.ui.table.HeaderCellRenderer,
+function() {
+ qx.ui.table.HeaderCellRenderer.call(this);
+});
+
+
+// overridden
+qx.Proto.createHeaderCell = function(cellInfo) {
+ var widget = new qx.ui.basic.Atom();
+ widget.setAppearance("table-header-cell");
+
+ this.updateHeaderCell(cellInfo, widget);
+
+ return widget;
+}
+
+
+// overridden
+qx.Proto.updateHeaderCell = function(cellInfo, cellWidget) {
+ var DefaultHeaderCellRenderer = qx.ui.table.DefaultHeaderCellRenderer;
+
+ cellWidget.setLabel(cellInfo.name);
+
+ cellWidget.setIcon(cellInfo.sorted ? (cellInfo.sortedAscending ? "widget/table/ascending.png" : "widget/table/descending.png") : null);
+ cellWidget.setState(DefaultHeaderCellRenderer.STATE_SORTED, cellInfo.sorted);
+ cellWidget.setState(DefaultHeaderCellRenderer.STATE_SORTED_ASCENDING, cellInfo.sortedAscending);
+}
+
+/**
+ * (string) The state which will be set for header cells of sorted columns.
+ */
+qx.Class.STATE_SORTED = "sorted";
+
+/**
+ * (string) The state which will be set when sorting is ascending.
+ */
+qx.Class.STATE_SORTED_ASCENDING = "sortedAscending";
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/HeaderCellRenderer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/HeaderCellRenderer.js
new file mode 100644
index 0000000000..2108778efb
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/HeaderCellRenderer.js
@@ -0,0 +1,69 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A cell renderer for header cells.
+ */
+qx.OO.defineClass("qx.ui.table.HeaderCellRenderer", qx.core.Object,
+function() {
+ qx.core.Object.call(this);
+});
+
+
+/**
+ * Creates a header cell.
+ *
+ * The cellInfo map contains the following properties:
+ *
+ * col (int): the model index of the column.
+ * xPos (int): the x position of the column in the table pane.
+ * name (string): the name of the column.
+ * editable (boolean): whether the column is editable.
+ * sorted (boolean): whether the column is sorted.
+ * sortedAscending (boolean): whether sorting is ascending.
+ *
+ *
+ * @param cellInfo {Map} A map containing the information about the cell to
+ * create.
+ * @return {qx.ui.core.Widget} the widget that renders the header cell.
+ */
+qx.Proto.createHeaderCell = function(cellInfo) {
+ throw new Error("createHeaderCell is abstract");
+}
+
+
+/**
+ * Updates a header cell.
+ *
+ * @param cellInfo {Map} A map containing the information about the cell to
+ * create. This map has the same structure as in {@link #createHeaderCell}.
+ * @param cellWidget {qx.ui.core.Widget} the widget that renders the header cell. This is
+ * the same widget formally created by {@link #createHeaderCell}.
+ */
+qx.Proto.updateHeaderCell = function(cellInfo, cellWidget) {
+ throw new Error("updateHeaderCell is abstract");
+}
+
+
+/** The preferred height of cells created by this header renderer. */
+qx.OO.addProperty({ name:"prefferedCellHeight", type:"number", defaultValue:16, allowNull:false });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/IconDataCellRenderer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/IconDataCellRenderer.js
new file mode 100644
index 0000000000..b4a717527b
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/IconDataCellRenderer.js
@@ -0,0 +1,182 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+ * Carsten Lergenmueller (carstenl)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A data cell renderer for boolean values.
+ */
+qx.OO.defineClass("qx.ui.table.IconDataCellRenderer", qx.ui.table.AbstractDataCellRenderer,
+function() {
+ qx.ui.table.AbstractDataCellRenderer.call(this);
+ this.IMG_BLANK_URL = qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif");
+});
+
+
+/**
+ * Identifies the Image to show.
+ *
+ * @param cellInfo {Map} The information about the cell.
+ * See {@link #createDataCellHtml}.
+ * @return {Map} A map having the following attributes:
+ *
+ * "url": (type string) must be the URL of the image to show.
+ * "imageWidth": (type int) the width of the image in pixels.
+ * "imageHeight": (type int) the height of the image in pixels.
+ * "tooltip": (type string) must be the image tooltip text.
+ *
+ */
+qx.Proto._identifyImage = function(cellInfo) {
+ throw new Error("_identifyImage is abstract");
+}
+
+
+/**
+ * Retrieves the image infos.
+ *
+ * @param cellInfo {Map} The information about the cell.
+ * See {@link #createDataCellHtml}.
+ * @return {Map} Map with an "url" attribute (type string)
+ * holding the URL of the image to show
+ * and a "tooltip" attribute
+ * (type string) being the tooltip text (or null if none was specified)
+ *
+ */
+qx.Proto._getImageInfos= function(cellInfo) {
+ // Query the subclass about image and tooltip
+ var urlAndTooltipMap = this._identifyImage(cellInfo);
+
+ // If subclass refuses to give map, construct it
+ if (urlAndTooltipMap == null || typeof urlAndTooltipMap == "string"){
+ urlAndTooltipMap = {url:urlAndTooltipMap, tooltip:null};
+ }
+
+ // If subclass gave null as url, replace with url to empty image
+ if (urlAndTooltipMap.url == null){
+ urlAndTooltipMap.url = this.IMG_BLANK_URL;
+ }
+
+ return urlAndTooltipMap;
+}
+
+// overridden
+qx.Proto._getCellStyle = function(cellInfo) {
+ var style = qx.ui.table.AbstractDataCellRenderer.prototype._getCellStyle(cellInfo);
+ style += qx.ui.table.IconDataCellRenderer.MAIN_DIV_STYLE;
+ return style;
+}
+
+
+// overridden
+qx.Proto._getContentHtml = function(cellInfo) {
+ var IconDataCellRenderer = qx.ui.table.IconDataCellRenderer;
+
+ var urlAndToolTip = this._getImageInfos(cellInfo);
+ var html = IconDataCellRenderer.IMG_START;
+ if (qx.sys.Client.getInstance().isMshtml() && /\.png$/i.test(urlAndToolTip.url)) {
+ html += qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif")
+ + '" style="filter:' + "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + urlAndToolTip.url + "',sizingMethod='scale')";
+ } else {
+ html += urlAndToolTip.url + '" style="';
+ }
+
+ if (urlAndToolTip.imageWidth && urlAndToolTip.imageHeight) {
+ html += ';width:' + urlAndToolTip.imageWidth + 'px'
+ + ';height:' + urlAndToolTip.imageHeight + 'px';
+ }
+
+ var tooltip = urlAndToolTip.tooltip;
+ if (tooltip != null){
+ html += IconDataCellRenderer.IMG_TITLE_START + tooltip;
+ }
+ html += IconDataCellRenderer.IMG_END;
+ return html;
+}
+
+
+// overridden
+qx.Proto.updateDataCellElement = function(cellInfo, cellElement) {
+ // Set image and tooltip text
+ var urlAndToolTip = this._getImageInfos(cellInfo);
+ var img = cellElement.firstChild;
+ if (qx.sys.Client.getInstance().isMshtml()) {
+ if (/\.png$/i.test(urlAndToolTip.url)) {
+ img.src = qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif");
+ img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + urlAndToolTip.url + "',sizingMethod='scale')";
+ } else {
+ img.src = urlAndToolTip.url;
+ img.style.filter = "";
+ }
+ } else {
+ img.src = urlAndToolTip.url;
+ }
+
+ if (urlAndToolTip.imageWidth && urlAndToolTip.imageHeight) {
+ img.style.width = urlAndToolTip.imageWidth + "px";
+ img.style.height = urlAndToolTip.imageHeight + "px";
+ }
+
+ if (urlAndToolTip.tooltip != null){
+ img.text = urlAndToolTip.tooltip;
+ }
+}
+
+
+// overridden
+qx.Proto._createCellStyle_array_join = function(cellInfo, htmlArr) {
+ qx.ui.table.AbstractDataCellRenderer.prototype._createCellStyle_array_join(cellInfo, htmlArr);
+
+ htmlArr.push(qx.ui.table.IconDataCellRenderer.MAIN_DIV_STYLE);
+}
+
+qx.Proto._createContentHtml_array_join = function(cellInfo, htmlArr) {
+ var IconDataCellRenderer = qx.ui.table.IconDataCellRenderer;
+
+ if (qx.ui.table.TablePane.USE_TABLE) {
+ htmlArr.push(IconDataCellRenderer.TABLE_DIV);
+ htmlArr.push(cellInfo.styleHeight - 2); // -1 for the border, -1 for the padding
+ htmlArr.push(IconDataCellRenderer.TABLE_DIV_CLOSE);
+ }
+
+ htmlArr.push(IconDataCellRenderer.IMG_START);
+ var urlAndToolTip = this._getImageInfos(cellInfo);
+ htmlArr.push(urlAndToolTip.url);
+ var tooltip = urlAndToolTip.tooltip;
+ if (tooltip != null){
+ IconDataCellRenderer.IMG_TITLE_START;
+ htmlArr.push(tooltip);
+ }
+ htmlArr.push(IconDataCellRenderer.IMG_END);
+
+ if (qx.ui.table.TablePane.USE_TABLE) {
+ htmlArr.push(IconDataCellRenderer.TABLE_DIV_END);
+ }
+}
+
+qx.Class.MAIN_DIV_STYLE = ';text-align:center;padding-top:1px;';
+qx.Class.IMG_START = ' ';
+qx.Class.IMG_TITLE_START = '" title="';
+qx.Class.TABLE_DIV = '';
+qx.Class.TABLE_DIV_END = '
';
+
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/IconHeaderCellRenderer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/IconHeaderCellRenderer.js
new file mode 100644
index 0000000000..51e653f5c4
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/IconHeaderCellRenderer.js
@@ -0,0 +1,84 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+ * Carsten Lergenmueller (carstenl)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A header cell renderer which renders an icon (only). The icon cannot be combined
+ * with text.
+ *
+ * @param iconUrl {string} URL to the icon to show
+ * @param tooltip {string ? ""} Text of the tooltip to show if the mouse hovers over the
+ * icon
+ *
+ */
+qx.OO.defineClass("qx.ui.table.IconHeaderCellRenderer", qx.ui.table.DefaultHeaderCellRenderer,
+function(iconUrl, tooltip) {
+ qx.ui.table.DefaultHeaderCellRenderer.call(this);
+ if (iconUrl == null){
+ iconUrl = "";
+ }
+ this.setIconUrl(iconUrl);
+ this.setToolTip(tooltip);
+});
+
+/**
+ * URL of the icon to show
+ */
+qx.OO.addProperty({ name:"iconUrl", type:"string", defaultValue:"", allowNull:false });
+
+/**
+ * ToolTip to show if the mouse hovers of the icon
+ */
+qx.OO.addProperty({ name:"toolTip", type:"string", defaultValue:null, allowNull:true });
+
+// overridden
+qx.Proto.updateHeaderCell = function(cellInfo, cellWidget) {
+ qx.ui.table.DefaultHeaderCellRenderer.prototype.updateHeaderCell.call(this, cellInfo, cellWidget);
+
+ // Set URL to icon
+ var img = cellWidget.getUserData("qx_ui_table_IconHeaderCellRenderer_icon");
+ if (img == null){
+ img = new qx.ui.basic.Image();
+ cellWidget.setUserData("qx_ui_table_IconHeaderCellRenderer_icon", img);
+ cellWidget.addAtBegin(img);
+ }
+ img.setSource(this.getIconUrl());
+
+ // Set image tooltip if given
+ var widgetToolTip = cellWidget.getToolTip();
+ if (this.getToolTip() != null){
+
+ //Create tooltip if necessary
+ if (true || widgetToolTip == null ){
+ widgetToolTip = new qx.ui.popup.ToolTip(this.getToolTip());
+ cellWidget.setToolTip(widgetToolTip);
+ //this.debug("Creating tooltip");
+ }
+
+ //Set tooltip text
+ widgetToolTip.getAtom().setLabel(this.getToolTip());
+ //this.debug("Setting tooltip text " + this.getToolTip());
+ }
+
+}
+
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/RemoteTableModel.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/RemoteTableModel.js
new file mode 100644
index 0000000000..ebd1be8f53
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/RemoteTableModel.js
@@ -0,0 +1,435 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A table model that loads its data from a backend.
+ *
+ * Only those rows are loaded that are near the area the user is currently
+ * viewing. If the user scrolls, the rows he will see soon are loaded
+ * asynchroniously in the background. All loaded data is managed in a cache that
+ * automatically removes the last resently used rows when it gets full.
+ *
+ * This class is abstract: The actual loading of row data must be done by
+ * subclasses.
+ */
+qx.OO.defineClass("qx.ui.table.RemoteTableModel", qx.ui.table.AbstractTableModel,
+function() {
+ qx.ui.table.AbstractTableModel.call(this);
+
+ this._sortColumnIndex = -1;
+ this._sortAscending = true;
+ this._rowCount = -1;
+
+ this._lruCounter = 0;
+ this._firstLoadingBlock = -1;
+ this._firstRowToLoad = -1;
+ this._lastRowToLoad = -1;
+ this._ignoreCurrentRequest = false;
+
+ this._rowBlockCache = {};
+ this._rowBlockCount = 0;
+});
+
+
+/** The number of rows that are stored in one cache block. */
+qx.OO.addProperty({ name:"blockSize", type:"number", defaultValue:50, allowNull:false });
+
+/** The maximum number of row blocks kept in the cache. */
+qx.OO.addProperty({ name:"maxCachedBlockCount", type:"number", defaultValue:15, allowNull:false });
+
+/**
+ * Whether to clear the cache when some rows are removed.
+ * If false the rows are removed locally in the cache.
+ */
+qx.OO.addProperty({ name:"clearCacheOnRemove", type:"boolean", defaultValue:false, allowNull:false });
+
+
+// overridden
+qx.Proto.getRowCount = function() {
+ if (this._rowCount == -1) {
+ this._loadRowCount();
+
+ // NOTE: _loadRowCount may set this._rowCount
+ return (this._rowCount == -1) ? 0 : this._rowCount;
+ } else {
+ return this._rowCount;
+ }
+}
+
+
+/**
+ * Loads the row count from the server.
+ *
+ * Implementing classes have to call {@link _onRowDataLoaded()} when the server
+ * response arrived. That method has to be called! Even when there was an error.
+ */
+qx.Proto._loadRowCount = function() {
+ throw new Error("_loadRowCount is abstract");
+};
+
+
+/**
+ * Sets the row count.
+ *
+ * Has to be called by {@link _loadRowCount()}.
+ *
+ * @param rowCount {int} the number of rows in this model or null if loading.
+ */
+qx.Proto._onRowCountLoaded = function(rowCount) {
+ this.debug("row count loaded: " + rowCount);
+ if (rowCount == null) {
+ rowCount = 0;
+ }
+ this._rowCount = rowCount;
+
+ // Inform the listeners
+ var data = { firstRow:0, lastRow:rowCount - 1, firstColumn:0, lastColumn:this.getColumnCount() - 1 };
+ this.dispatchEvent(new qx.event.type.DataEvent(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, data), true);
+};
+
+
+/**
+ * Reloads the model and clears the local cache.
+ */
+qx.Proto.reloadData = function() {
+ this.clearCache();
+
+ // If there is currently a request on its way, then this request will bring
+ // obsolete data -> Ignore it
+ if (this._firstLoadingBlock != -1) {
+ this._ignoreCurrentRequest = true;
+ }
+
+ // NOTE: This will inform the listeners as soon as the new row count is known
+ this._loadRowCount();
+};
+
+
+/**
+ * Clears the cache.
+ */
+qx.Proto.clearCache = function() {
+ this._rowBlockCache = {};
+ this._rowBlockCount = 0;
+};
+
+
+// overridden
+qx.Proto.prefetchRows = function(firstRowIndex, lastRowIndex) {
+ // this.debug("Prefetch wanted: " + firstRowIndex + ".." + lastRowIndex);
+ if (this._firstLoadingBlock == -1) {
+ var blockSize = this.getBlockSize();
+ var totalBlockCount = Math.ceil(this._rowCount / blockSize);
+
+ // There is currently no request running -> Start a new one
+ // NOTE: We load one more block above and below to have a smooth
+ // scrolling into the next block without blank cells
+ var firstBlock = parseInt(firstRowIndex / blockSize) - 1;
+ if (firstBlock < 0) {
+ firstBlock = 0;
+ }
+ var lastBlock = parseInt(lastRowIndex / blockSize) + 1;
+ if (lastBlock >= totalBlockCount) {
+ lastBlock = totalBlockCount - 1;
+ }
+
+ // Check which blocks we have to load
+ var firstBlockToLoad = -1;
+ var lastBlockToLoad = -1;
+ for (var block = firstBlock; block <= lastBlock; block++) {
+ if (this._rowBlockCache[block] == null || this._rowBlockCache[block].isDirty) {
+ // We don't have this block
+ if (firstBlockToLoad == -1) {
+ firstBlockToLoad = block;
+ }
+ lastBlockToLoad = block;
+ }
+ }
+
+ // Load the blocks
+ if (firstBlockToLoad != -1) {
+ this._firstRowToLoad = -1;
+ this._lastRowToLoad = -1;
+
+ this._firstLoadingBlock = firstBlockToLoad;
+
+ this.debug("Starting server request. rows: " + firstRowIndex + ".." + lastRowIndex + ", blocks: " + firstBlockToLoad + ".." + lastBlockToLoad);
+ this._loadRowData(firstBlockToLoad * blockSize, (lastBlockToLoad + 1) * blockSize - 1);
+ }
+ } else {
+ // There is already a request running -> Remember this request
+ // so it can be executed after the current one is finished.
+ this._firstRowToLoad = firstRowIndex;
+ this._lastRowToLoad = lastRowIndex;
+ }
+};
+
+
+/**
+ * Loads some row data from the server.
+ *
+ * Implementing classes have to call {@link _onRowDataLoaded()} when the server
+ * response arrived. That method has to be called! Even when there was an error.
+ *
+ * @param firstRow {int} The index of the first row to load.
+ * @param lastRow {int} The index of the last row to load.
+ */
+qx.Proto._loadRowData = function(firstRow, lastRow) {
+ throw new Error("_loadRowCount is abstract");
+};
+
+
+/**
+ * Sets row data.
+ *
+ * Has to be called by {@link _loadRowData()}.
+ *
+ * @param rowDataArr {Map[]} the loaded row data or null if there was an error.
+ */
+qx.Proto._onRowDataLoaded = function(rowDataArr) {
+ if (rowDataArr != null && ! this._ignoreCurrentRequest) {
+ var blockSize = this.getBlockSize();
+ var blockCount = Math.ceil(rowDataArr.length / blockSize);
+ if (blockCount == 1) {
+ // We got one block -> Use the rowData directly
+ this._setRowBlockData(this._firstLoadingBlock, rowDataArr);
+ } else {
+ // We got more than one block -> We've to split the rowData
+ for (var i = 0; i < blockCount; i++) {
+ var rowOffset = i * blockSize;
+ var blockRowData = [];
+ var mailCount = Math.min(blockSize, rowDataArr.length - rowOffset);
+ for (var row = 0; row < mailCount; row++) {
+ blockRowData.push(rowDataArr[rowOffset + row]);
+ }
+
+ this._setRowBlockData(this._firstLoadingBlock + i, blockRowData);
+ }
+ }
+ this.debug("Got server answer. blocks: " + this._firstLoadingBlock + ".." + (this._firstLoadingBlock + blockCount - 1) + ". mail count: " + rowDataArr.length + " block count:" + blockCount);
+
+ // Inform the listeners
+ var data = {
+ firstRow:this._firstLoadingBlock * blockSize,
+ lastRow:(this._firstLoadingBlock + blockCount + 1) * blockSize - 1,
+ firstColumn:0,
+ lastColumn:this.getColumnCount() - 1
+ };
+ this.dispatchEvent(new qx.event.type.DataEvent(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, data), true);
+ }
+
+ // We're not loading any blocks any more
+ this._firstLoadingBlock = -1;
+ this._ignoreCurrentRequest = false;
+
+ // Check whether we have to start a new request
+ if (this._firstRowToLoad != -1) {
+ this.prefetchRows(this._firstRowToLoad, this._lastRowToLoad);
+ }
+};
+
+
+/**
+ * Sets the data of one block.
+ *
+ * @param block {int} the index of the block.
+ * @param rowDataArr {var[][]} the data to set.
+ */
+qx.Proto._setRowBlockData = function(block, rowDataArr) {
+ if (this._rowBlockCache[block] == null) {
+ // This is a new block -> Check whether we have to remove another block first
+ this._rowBlockCount++;
+
+ while (this._rowBlockCount > this.getMaxCachedBlockCount()) {
+ // Find the last recently used block
+ // NOTE: We never remove block 0 and 1
+ var lruBlock;
+ var minLru = this._lruCounter;
+ for (var currBlock in this._rowBlockCache) {
+ var currLru = this._rowBlockCache[currBlock].lru;
+ if (currLru < minLru && currBlock > 1) {
+ minLru = currLru;
+ lruBlock = currBlock;
+ }
+ }
+
+ // Remove that block
+ this.debug("Removing block: " + lruBlock + ". current LRU: " + this._lruCounter);
+ delete this._rowBlockCache[lruBlock];
+ this._rowBlockCount--;
+ }
+ }
+
+ this._rowBlockCache[block] = { lru:++this._lruCounter, rowDataArr:rowDataArr };
+};
+
+
+/**
+ * Removes a rows from the model.
+ *
+ * @param rowIndex {int} the index of the row to remove.
+ */
+qx.Proto.removeRow = function(rowIndex) {
+ if (this.getClearCacheOnRemove()) {
+ this.clearCache();
+
+ // Inform the listeners
+ var data = { firstRow:0, lastRow:rowCount - 1, firstColumn:0, lastColumn:this.getColumnCount() - 1 };
+ this.dispatchEvent(new qx.event.type.DataEvent(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, data), true);
+ } else {
+ var blockSize = this.getBlockSize();
+ var blockCount = Math.ceil(this.getRowCount() / blockSize);
+ var startBlock = parseInt(rowIndex / blockSize);
+
+ // Remove the row and move the rows of all following blocks
+ for (var block = startBlock; block <= blockCount; block++) {
+ var blockData = this._rowBlockCache[block];
+ if (blockData != null) {
+ // Remove the row in the start block
+ // NOTE: In the other blocks the first row is removed
+ // (This is the row that was)
+ var removeIndex = 0;
+ if (block == startBlock) {
+ removeIndex = rowIndex - block * blockSize;
+ }
+ blockData.rowDataArr.splice(removeIndex, 1);
+
+ if (block == blockCount - 1) {
+ // This is the last block
+ if (blockData.rowDataArr.length == 0) {
+ // It is empty now -> Remove it
+ delete this._rowBlockCache[block];
+ }
+ } else {
+ // Try to copy the first row of the next block to the end of this block
+ // so this block can stays clean
+ var nextBlockData = this._rowBlockCache[block + 1];
+ if (nextBlockData != null) {
+ blockData.rowDataArr.push(nextBlockData.rowDataArr[0]);
+ } else {
+ // There is no row to move -> Mark this block as dirty
+ blockData.isDirty = true;
+ }
+ }
+ }
+ }
+
+ if (this._rowCount != -1) {
+ this._rowCount--;
+ }
+
+ // Inform the listeners
+ if (this.hasEventListeners(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED)) {
+ var data = { firstRow:rowIndex, lastRow:this.getRowCount() - 1, firstColumn:0, lastColumn:this.getColumnCount() - 1 };
+ this.dispatchEvent(new qx.event.type.DataEvent(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, data), true);
+ }
+ }
+};
+
+
+/**
+ *
See overridden method for details.
+ *
+ * @param rowIndex {int} the model index of the row.
+ * @return {Object} Map containing a value for each column.
+ */
+qx.Proto.getRowData = function(rowIndex) {
+ var blockSize = this.getBlockSize();
+ var block = parseInt(rowIndex / blockSize);
+ var blockData = this._rowBlockCache[block];
+ if (blockData == null) {
+ // This block is not (yet) loaded
+ return null;
+ } else {
+ var rowData = blockData.rowDataArr[rowIndex - (block * blockSize)];
+
+ // Update the last recently used counter
+ if (blockData.lru != this._lruCounter) {
+ blockData.lru = ++this._lruCounter;
+ }
+
+ return rowData;
+ }
+};
+
+
+// overridden
+qx.Proto.getValue = function(columnIndex, rowIndex) {
+ var rowData = this.getRowData(rowIndex);
+ if (rowData == null) {
+ return null;
+ } else {
+ var columnId = this.getColumnId(columnIndex);
+ return rowData[columnId];
+ }
+};
+
+
+/**
+ * Sets whether a column is sortable.
+ *
+ * @param columnIndex {int} the column of which to set the sortable state.
+ * @param sortable {boolean} whether the column should be sortable.
+ */
+qx.Proto.setColumnSortable = function(columnIndex, sortable) {
+ if (sortable != this.isColumnSortable(columnIndex)) {
+ if (this._sortableColArr == null) {
+ this._sortableColArr = [];
+ }
+ this._sortableColArr[columnIndex] = sortable;
+
+ this.createDispatchEvent(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED);
+ }
+}
+
+
+// overridden
+qx.Proto.isColumnSortable = function(columnIndex) {
+ return this._sortableColArr ? (this._sortableColArr[columnIndex] == true) : false;
+}
+
+
+// overridden
+qx.Proto.sortByColumn = function(columnIndex, ascending) {
+ if (this._sortColumnIndex != columnIndex || this._sortAscending != ascending) {
+ this._sortColumnIndex = columnIndex;
+ this._sortAscending = ascending;
+
+ this.clearCache();
+
+ // Inform the listeners
+ this.createDispatchEvent(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED);
+ }
+};
+
+
+// overridden
+qx.Proto.getSortColumnIndex = function() {
+ return this._sortColumnIndex;
+}
+
+
+// overridden
+qx.Proto.isSortAscending = function() {
+ return this._sortAscending;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SelectionManager.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SelectionManager.js
new file mode 100644
index 0000000000..715b0d9d96
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SelectionManager.js
@@ -0,0 +1,163 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A selection manager. This is a helper class that handles all selection
+ * related events and updates a SelectionModel.
+ *
+ * Widgets that support selection should use this manager. This way the only
+ * thing the widget has to do is mapping mouse or key events to indexes and
+ * call the corresponding handler method.
+ *
+ * @see SelectionModel
+ */
+qx.OO.defineClass("qx.ui.table.SelectionManager", qx.core.Object,
+function() {
+ qx.core.Object.call(this);
+});
+
+
+/**
+ * The selection model where to set the selection changes.
+ */
+qx.OO.addProperty({ name:"selectionModel", type:"object", instance:"qx.ui.table.SelectionModel" });
+
+
+/**
+ * Handles the mouse down event.
+ *
+ * @param index {int} the index the mouse is pointing at.
+ * @param evt {Map} the mouse event.
+ */
+qx.Proto.handleMouseDown = function(index, evt) {
+ if (evt.isLeftButtonPressed()) {
+ var selectionModel = this.getSelectionModel();
+ if (!selectionModel.isSelectedIndex(index)) {
+ // This index is not selected -> We react when the mouse is pressed (because of drag and drop)
+ this._handleSelectEvent(index, evt);
+ this._lastMouseDownHandled = true;
+ } else {
+ // This index is already selected -> We react when the mouse is released (because of drag and drop)
+ this._lastMouseDownHandled = false;
+ }
+ } else if (evt.isRightButtonPressed() && evt.getModifiers() == 0) {
+ var selectionModel = this.getSelectionModel();
+ if (!selectionModel.isSelectedIndex(index)) {
+ // This index is not selected -> Set the selection to this index
+ selectionModel.setSelectionInterval(index, index);
+ }
+ }
+}
+
+
+/**
+ * Handles the mouse up event.
+ *
+ * @param index {int} the index the mouse is pointing at.
+ * @param evt {Map} the mouse event.
+ */
+qx.Proto.handleMouseUp = function(index, evt) {
+ if (evt.isLeftButtonPressed() && !this._lastMouseDownHandled) {
+ this._handleSelectEvent(index, evt);
+ }
+}
+
+
+/**
+ * Handles the mouse click event.
+ *
+ * @param index {int} the index the mouse is pointing at.
+ * @param evt {Map} the mouse event.
+ */
+qx.Proto.handleClick = function(index, evt) {
+}
+
+
+/**
+ * Handles the key down event that is used as replacement for mouse clicks
+ * (Normally space).
+ *
+ * @param index {int} the index that is currently focused.
+ * @param evt {Map} the key event.
+ */
+qx.Proto.handleSelectKeyDown = function(index, evt) {
+ this._handleSelectEvent(index, evt);
+};
+
+
+/**
+ * Handles a key down event that moved the focus (E.g. up, down, home, end, ...).
+ *
+ * @param index {int} the index that is currently focused.
+ * @param evt {Map} the key event.
+ */
+qx.Proto.handleMoveKeyDown = function(index, evt) {
+ var selectionModel = this.getSelectionModel();
+ switch (evt.getModifiers()) {
+ case 0:
+ selectionModel.setSelectionInterval(index, index);
+ break;
+ case qx.event.type.DomEvent.SHIFT_MASK:
+ var anchor = selectionModel.getAnchorSelectionIndex();
+ if (anchor == -1) {
+ selectionModel.setSelectionInterval(index, index);
+ } else {
+ selectionModel.setSelectionInterval(anchor, index);
+ }
+ break;
+ }
+}
+
+
+/**
+ * Handles a select event.
+ *
+ * @param index {int} the index the event is pointing at.
+ * @param evt {Map} the mouse event.
+ */
+qx.Proto._handleSelectEvent = function(index, evt) {
+ var selectionModel = this.getSelectionModel();
+ if (evt.getShiftKey()) {
+ var leadIndex = selectionModel.getLeadSelectionIndex();
+ if (index != leadIndex || selectionModel.isSelectionEmpty()) {
+ // The lead selection index was changed
+ var anchorIndex = selectionModel.getAnchorSelectionIndex();
+ if (anchorIndex == -1) {
+ anchorIndex = index;
+ }
+ if (evt.isCtrlOrCommandPressed()) {
+ selectionModel.addSelectionInterval(anchorIndex, index);
+ } else {
+ selectionModel.setSelectionInterval(anchorIndex, index);
+ }
+ }
+ } else if (evt.isCtrlOrCommandPressed()) {
+ if (selectionModel.isSelectedIndex(index)) {
+ selectionModel.removeSelectionInterval(index, index);
+ } else {
+ selectionModel.addSelectionInterval(index, index);
+ }
+ } else {
+ selectionModel.setSelectionInterval(index, index);
+ }
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SelectionModel.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SelectionModel.js
new file mode 100644
index 0000000000..fb0f6b7317
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SelectionModel.js
@@ -0,0 +1,427 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A selection model.
+ *
+ * @event changeSelection {qx.event.type.Event} Fired when the selection has
+ * changed.
+ */
+qx.OO.defineClass("qx.ui.table.SelectionModel", qx.core.Target,
+function() {
+ qx.core.Target.call(this);
+
+ this._selectedRangeArr = [];
+ this._anchorSelectionIndex = -1;
+ this._leadSelectionIndex = -1;
+ this.hasBatchModeRefCount = 0;
+ this._hadChangeEventInBatchMode = false;
+});
+
+
+/** {int} The selection mode "none". Nothing can ever be selected. */
+qx.Class.NO_SELECTION = 1;
+
+/** {int} The selection mode "single". This mode only allows one selected item. */
+qx.Class.SINGLE_SELECTION = 2;
+
+/**
+ * (int) The selection mode "single interval". This mode only allows one
+ * continuous interval of selected items.
+ */
+qx.Class.SINGLE_INTERVAL_SELECTION = 3;
+
+/**
+ * (int) The selection mode "multiple interval". This mode only allows any
+ * selection.
+ */
+qx.Class.MULTIPLE_INTERVAL_SELECTION = 4;
+
+
+/**
+ * (int) the selection mode.
+ */
+qx.OO.addProperty({ name:"selectionMode", type:"number",
+ defaultValue:qx.Class.SINGLE_SELECTION,
+ allowNull:false,
+ possibleValues:[ qx.Class.NO_SELECTION,
+ qx.Class.SINGLE_SELECTION,
+ qx.Class.SINGLE_INTERVAL_SELECTION,
+ qx.Class.MULTIPLE_INTERVAL_SELECTION ] });
+
+// selectionMode property modifier
+qx.Proto._modifySelectionMode = function(selectionMode) {
+ if (selectionMode == qx.ui.table.SelectionModel.NO_SELECTION) {
+ this.clearSelection();
+ }
+ return true;
+}
+
+
+/**
+ *
Activates / Deactivates batch mode. In batch mode, no change events will be thrown but
+ * will be collected instead. When batch mode is turned off again and any events have
+ * been collected, one event is thrown to inform the listeners.
+ *
+ * This method supports nested calling, i. e. batch mode can be turned more than once.
+ * In this case, batch mode will not end until it has been turned off once for each
+ * turning on.
+ *
+ * @param batchMode {boolean} true to activate batch mode, false to deactivate
+ * @return {boolean} true if batch mode is active, false otherwise
+ * @throws Error if batch mode is turned off once more than it has been turned on
+ */
+qx.Proto.setBatchMode = function(batchMode) {
+ if (batchMode){
+ this.hasBatchModeRefCount += 1;
+ } else {
+ if (this.hasBatchModeRefCount == 0){
+ throw new Error("Try to turn off batch mode althoug it was not turned on.")
+ }
+ this.hasBatchModeRefCount -= 1;
+ if (this._hadChangeEventInBatchMode){
+ this._hadChangeEventInBatchMode = false;
+ this._fireChangeSelection();
+ }
+ }
+ return this.hasBatchMode();
+}
+
+
+/**
+ * Returns whether batch mode is active. See setter for a description of batch mode.
+ *
+ * @return {boolean} true if batch mode is active, false otherwise
+ */
+qx.Proto.hasBatchMode = function() {
+ return this.hasBatchModeRefCount > 0;
+}
+
+
+/**
+ * Returns the first argument of the last call to {@link #setSelectionInterval()},
+ * {@link #addSelectionInterval()} or {@link #removeSelectionInterval()}.
+ *
+ * @return {int} the ancor selection index.
+ */
+qx.Proto.getAnchorSelectionIndex = function() {
+ return this._anchorSelectionIndex;
+}
+
+
+/**
+ * Returns the second argument of the last call to {@link #setSelectionInterval()},
+ * {@link #addSelectionInterval()} or {@link #removeSelectionInterval()}.
+ *
+ * @return {int} the lead selection index.
+ */
+qx.Proto.getLeadSelectionIndex = function() {
+ return this._leadSelectionIndex;
+}
+
+
+/**
+ * Clears the selection.
+ */
+qx.Proto.clearSelection = function() {
+ if (! this.isSelectionEmpty()) {
+ this._clearSelection();
+ this._fireChangeSelection();
+ }
+}
+
+
+/**
+ * Returns whether the selection is empty.
+ *
+ * @return {boolean} whether the selection is empty.
+ */
+qx.Proto.isSelectionEmpty = function() {
+ return this._selectedRangeArr.length == 0;
+}
+
+
+/**
+ * Returns the number of selected items.
+ *
+ * @return {int} the number of selected items.
+ */
+qx.Proto.getSelectedCount = function() {
+ var selectedCount = 0;
+ for (var i = 0; i < this._selectedRangeArr.length; i++) {
+ var range = this._selectedRangeArr[i];
+ selectedCount += range.maxIndex - range.minIndex + 1;
+ }
+
+ return selectedCount;
+}
+
+
+/**
+ * Returns whether a index is selected.
+ *
+ * @param index {int} the index to check.
+ * @return {boolean} whether the index is selected.
+ */
+qx.Proto.isSelectedIndex = function(index) {
+ for (var i = 0; i < this._selectedRangeArr.length; i++) {
+ var range = this._selectedRangeArr[i];
+
+ if (index >= range.minIndex && index <= range.maxIndex) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+/**
+ * Returns the selected ranges as an array. Each array element has a
+ * minIndex
and a maxIndex
property.
+ *
+ * @return {Map[]} the selected ranges.
+ */
+qx.Proto.getSelectedRanges = function() {
+ // clone the selection array and the individual elements - this prevents the
+ // caller from messing with the internal model
+ var retVal = [];
+ for (var i = 0; i < this._selectedRangeArr.length; i++) {
+ retVal.push({minIndex: this._selectedRangeArr[i].minIndex,
+ maxIndex: this._selectedRangeArr[i].maxIndex});
+ }
+ return retVal;
+}
+
+
+/**
+ * Calls a iterator function for each selected index.
+ *
+ * Usage Example:
+ *
+ * var selectedRowData = [];
+ * mySelectionModel.iterateSelection(function(index) {
+ * selectedRowData.push(myTableModel.getRowData(index));
+ * });
+ *
+ *
+ * @param iterator {Function} the function to call for each selected index.
+ * Gets the current index as parameter.
+ * @param object {var ? null} the object to use when calling the handler.
+ * (this object will be available via "this" in the iterator)
+ */
+qx.Proto.iterateSelection = function(iterator, object) {
+ for (var i = 0; i < this._selectedRangeArr.length; i++) {
+ for (var j = this._selectedRangeArr[i].minIndex; j <= this._selectedRangeArr[i].maxIndex; j++) {
+ iterator.call(object, j);
+ }
+ }
+};
+
+
+/**
+ * Sets the selected interval. This will clear the former selection.
+ *
+ * @param fromIndex {int} the first index of the selection (including).
+ * @param toIndex {int} the last index of the selection (including).
+ */
+qx.Proto.setSelectionInterval = function(fromIndex, toIndex) {
+ var SelectionModel = qx.ui.table.SelectionModel;
+
+ switch(this.getSelectionMode()) {
+ case SelectionModel.NO_SELECTION:
+ return;
+ case SelectionModel.SINGLE_SELECTION:
+ fromIndex = toIndex;
+ break;
+ }
+
+ this._clearSelection();
+ this._addSelectionInterval(fromIndex, toIndex);
+
+ this._fireChangeSelection();
+}
+
+
+/**
+ * Adds a selection interval to the current selection.
+ *
+ * @param fromIndex {int} the first index of the selection (including).
+ * @param toIndex {int} the last index of the selection (including).
+ */
+qx.Proto.addSelectionInterval = function(fromIndex, toIndex) {
+ var SelectionModel = qx.ui.table.SelectionModel;
+ switch (this.getSelectionMode()) {
+ case SelectionModel.NO_SELECTION:
+ return;
+ case SelectionModel.MULTIPLE_INTERVAL_SELECTION:
+ this._addSelectionInterval(fromIndex, toIndex);
+ this._fireChangeSelection();
+ break;
+ default:
+ this.setSelectionInterval(fromIndex, toIndex);
+ break;
+ }
+}
+
+
+/**
+ * Removes a interval from the current selection.
+ *
+ * @param fromIndex {int} the first index of the interval (including).
+ * @param toIndex {int} the last index of the interval (including).
+ */
+qx.Proto.removeSelectionInterval = function(fromIndex, toIndex) {
+ this._anchorSelectionIndex = fromIndex;
+ this._leadSelectionIndex = toIndex;
+
+ var minIndex = Math.min(fromIndex, toIndex);
+ var maxIndex = Math.max(fromIndex, toIndex);
+
+ // Crop the affected ranges
+ for (var i = 0; i < this._selectedRangeArr.length; i++) {
+ var range = this._selectedRangeArr[i];
+
+ if (range.minIndex > maxIndex) {
+ // We are done
+ break;
+ } else if (range.maxIndex >= minIndex) {
+ // This range is affected
+ var minIsIn = (range.minIndex >= minIndex) && (range.minIndex <= maxIndex);
+ var maxIsIn = (range.maxIndex >= minIndex) && (range.maxIndex <= maxIndex);
+
+ if (minIsIn && maxIsIn) {
+ // This range is removed completely
+ this._selectedRangeArr.splice(i, 1);
+
+ // Check this index another time
+ i--;
+ } else if (minIsIn) {
+ // The range is cropped from the left
+ range.minIndex = maxIndex + 1;
+ } else if (maxIsIn) {
+ // The range is cropped from the right
+ range.maxIndex = minIndex - 1;
+ } else {
+ // The range is split
+ var newRange = { minIndex:maxIndex + 1, maxIndex:range.maxIndex }
+ this._selectedRangeArr.splice(i + 1, 0, newRange);
+
+ range.maxIndex = minIndex - 1;
+
+ // We are done
+ break;
+ }
+ }
+ }
+
+ //this._dumpRanges();
+
+ this._fireChangeSelection();
+}
+
+
+/**
+ * Clears the selection, but doesn't inform the listeners.
+ */
+qx.Proto._clearSelection = function() {
+ this._selectedRangeArr = [];
+}
+
+
+/**
+ * Adds a selection interval to the current selection, but doesn't inform
+ * the listeners.
+ *
+ * @param fromIndex {int} the first index of the selection (including).
+ * @param toIndex {int} the last index of the selection (including).
+ */
+qx.Proto._addSelectionInterval = function(fromIndex, toIndex) {
+ this._anchorSelectionIndex = fromIndex;
+ this._leadSelectionIndex = toIndex;
+
+ var minIndex = Math.min(fromIndex, toIndex);
+ var maxIndex = Math.max(fromIndex, toIndex);
+
+ // Find the index where the new range should be inserted
+ var newRangeIndex = 0;
+ for (; newRangeIndex < this._selectedRangeArr.length; newRangeIndex++) {
+ var range = this._selectedRangeArr[newRangeIndex];
+ if (range.minIndex > minIndex) {
+ break;
+ }
+ }
+
+ // Add the new range
+ this._selectedRangeArr.splice(newRangeIndex, 0, { minIndex:minIndex, maxIndex:maxIndex });
+
+ // Merge overlapping ranges
+ var lastRange = this._selectedRangeArr[0];
+ for (var i = 1; i < this._selectedRangeArr.length; i++) {
+ var range = this._selectedRangeArr[i];
+
+ if (lastRange.maxIndex + 1 >= range.minIndex) {
+ // The ranges are overlapping -> merge them
+ lastRange.maxIndex = Math.max(lastRange.maxIndex, range.maxIndex);
+
+ // Remove the current range
+ this._selectedRangeArr.splice(i, 1);
+
+ // Check this index another time
+ i--;
+ } else {
+ lastRange = range;
+ }
+ }
+
+ //this._dumpRanges();
+}
+
+
+/**
+ * Logs the current ranges for debug perposes.
+ */
+qx.Proto._dumpRanges = function() {
+ var text = "Ranges:";
+ for (var i = 0; i < this._selectedRangeArr.length; i++) {
+ var range = this._selectedRangeArr[i];
+ text += " [" + range.minIndex + ".." + range.maxIndex + "]";
+ }
+ this.debug(text);
+}
+
+
+/**
+ * Fires the "changeSelection" event to all registered listeners. If the selection model
+ * currently is in batch mode, only one event will be thrown when batch mode is ended.
+ */
+qx.Proto._fireChangeSelection = function() {
+ //In batch mode, remember event but do not throw (yet)
+ if (this.hasBatchMode()){
+ this._hadChangeEventInBatchMode = true;
+
+ //If not in batch mode, throw event
+ } else if (this.hasEventListeners("changeSelection")) {
+ this.dispatchEvent(new qx.event.type.Event("changeSelection"), true);
+ }
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SimpleTableModel.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SimpleTableModel.js
new file mode 100644
index 0000000000..ef6ef2fecc
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SimpleTableModel.js
@@ -0,0 +1,335 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A simple table model that provides an API for changing the model data.
+ */
+qx.OO.defineClass("qx.ui.table.SimpleTableModel", qx.ui.table.AbstractTableModel,
+function() {
+ qx.ui.table.AbstractTableModel.call(this);
+
+ this._rowArr = [];
+ this._sortColumnIndex = -1;
+ this._sortAscending;
+
+ this._editableColArr = null;
+});
+
+
+/**
+ * See overridden method for details.
+ *
+ * @param rowIndex {int} the model index of the row.
+ * @return {Array} Array containing a value for each column.
+ */
+qx.Proto.getRowData = function(rowIndex) {
+ return this._rowArr[rowIndex];
+};
+
+
+/**
+ * Returns the data of one row as map containing the column IDs as key and the
+ * cell values as value.
+ *
+ * @param rowIndex {int} the model index of the row.
+ * @return {Map} a Map containing the column values.
+ */
+qx.Proto.getRowDataAsMap = function(rowIndex) {
+ var columnArr = this._rowArr[rowIndex];
+ var map = {};
+ for (var col = 0; col < this.getColumnCount(); col++) {
+ map[this.getColumnId(col)] = columnArr[col];
+ }
+ return map;
+};
+
+
+/**
+ * Sets all columns editable or not editable.
+ *
+ * @param editable {boolean} whether all columns are editable.
+ */
+qx.Proto.setEditable = function(editable) {
+ this._editableColArr = [];
+ for (var col = 0; col < this.getColumnCount(); col++) {
+ this._editableColArr[col] = editable;
+ }
+
+ this.createDispatchEvent(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED);
+}
+
+
+/**
+ * Sets whether a column is editable.
+ *
+ * @param columnIndex {int} the column of which to set the editable state.
+ * @param editable {boolean} whether the column should be editable.
+ */
+qx.Proto.setColumnEditable = function(columnIndex, editable) {
+ if (editable != this.isColumnEditable(columnIndex)) {
+ if (this._editableColArr == null) {
+ this._editableColArr = [];
+ }
+ this._editableColArr[columnIndex] = editable;
+
+ this.createDispatchEvent(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED);
+ }
+}
+
+
+// overridden
+qx.Proto.isColumnEditable = function(columnIndex) {
+ return this._editableColArr ? (this._editableColArr[columnIndex] == true) : false;
+}
+
+
+// overridden
+qx.Proto.isColumnSortable = function(columnIndex) {
+ return true;
+}
+
+
+// overridden
+qx.Proto.sortByColumn = function(columnIndex, ascending) {
+ // NOTE: We use different comperators for ascending and descending,
+ // because comperators should be really fast.
+ var comperator;
+ if (ascending) {
+ comperator = function(row1, row2) {
+ var obj1 = row1[columnIndex];
+ var obj2 = row2[columnIndex];
+ return (obj1 > obj2) ? 1 : ((obj1 == obj2) ? 0 : -1);
+ }
+ } else {
+ comperator = function(row1, row2) {
+ var obj1 = row1[columnIndex];
+ var obj2 = row2[columnIndex];
+ return (obj1 < obj2) ? 1 : ((obj1 == obj2) ? 0 : -1);
+ }
+ }
+
+ this._rowArr.sort(comperator);
+
+ this._sortColumnIndex = columnIndex;
+ this._sortAscending = ascending;
+
+ this.createDispatchEvent(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED);
+}
+
+
+/**
+ * Clears the sorting.
+ */
+qx.Proto._clearSorting = function() {
+ if (this._sortColumnIndex != -1) {
+ this._sortColumnIndex = -1;
+ this._sortAscending = true;
+
+ this.createDispatchEvent(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED);
+ }
+}
+
+
+// overridden
+qx.Proto.getSortColumnIndex = function() {
+ return this._sortColumnIndex;
+}
+
+
+// overridden
+qx.Proto.isSortAscending = function() {
+ return this._sortAscending;
+}
+
+
+// overridden
+qx.Proto.getRowCount = function() {
+ return this._rowArr.length;
+}
+
+
+// overridden
+qx.Proto.getValue = function(columnIndex, rowIndex) {
+ if (rowIndex < 0 || rowIndex >= this._rowArr.length) {
+ throw new Error("this._rowArr out of bounds: " + rowIndex + " (0.." + this._rowArr.length + ")");
+ }
+
+ return this._rowArr[rowIndex][columnIndex];
+}
+
+
+// overridden
+qx.Proto.setValue = function(columnIndex, rowIndex, value) {
+ if (this._rowArr[rowIndex][columnIndex] != value) {
+ this._rowArr[rowIndex][columnIndex] = value;
+
+ // Inform the listeners
+ if (this.hasEventListeners(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED)) {
+ var data = { firstRow:rowIndex, lastRow:rowIndex,
+ firstColumn:columnIndex, lastColumn:columnIndex }
+ this.dispatchEvent(new qx.event.type.DataEvent(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, data), true);
+ }
+
+ if (columnIndex == this._sortColumnIndex) {
+ this._clearSorting();
+ }
+ }
+}
+
+
+/**
+ * Sets the whole data in a bulk.
+ *
+ * @param rowArr {var[][]} An array containing an array for each row. Each
+ * row-array contains the values in that row in the order of the columns
+ * in this model.
+ */
+qx.Proto.setData = function(rowArr) {
+ this._rowArr = rowArr;
+
+ // Inform the listeners
+ if (this.hasEventListeners(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED)) {
+ this.createDispatchEvent(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED);
+ }
+
+ this._clearSorting();
+}
+
+
+/**
+ * Returns the data of this model.
+ *
+ * Warning: Do not alter this array! If you want to change the data use
+ * {@link #setData}, {@link #setDataAsMapArray} or {@link #setValue} instead.
+ *
+ * @return {var[][]} An array containing an array for each row. Each
+ * row-array contains the values in that row in the order of the columns
+ * in this model.
+ */
+qx.Proto.getData = function() {
+ return this._rowArr;
+};
+
+
+/**
+ * Sets the whole data in a bulk.
+ *
+ * @param mapArr {Map[]} An array containing a map for each row. Each
+ * row-map contains the column IDs as key and the cell values as value.
+ */
+qx.Proto.setDataAsMapArray = function(mapArr) {
+ this.setData(this._mapArray2RowArr(mapArr));
+};
+
+
+/**
+ * Adds some rows to the model.
+ *
+ * Warning: The given array will be altered!
+ *
+ * @param rowArr {var[][]} An array containing an array for each row. Each
+ * row-array contains the values in that row in the order of the columns
+ * in this model.
+ * @param startIndex {int ? null} The index where to insert the new rows. If null,
+ * the rows are appended to the end.
+ */
+qx.Proto.addRows = function(rowArr, startIndex) {
+ if (startIndex == null) {
+ startIndex = this._rowArr.length;
+ }
+
+ // Prepare the rowArr so it can be used for apply
+ rowArr.splice(0, 0, startIndex, 0);
+
+ // Insert the new rows
+ Array.prototype.splice.apply(this._rowArr, rowArr);
+
+ // Inform the listeners
+ if (this.hasEventListeners(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED)) {
+ var data = { firstRow:startIndex, lastRow:this._rowArr.length - 1, firstColumn:0, lastColumn:this.getColumnCount() - 1 };
+ this.dispatchEvent(new qx.event.type.DataEvent(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, data), true);
+ }
+
+ this._clearSorting();
+};
+
+
+/**
+ * Adds some rows to the model.
+ *
+ * Warning: The given array (mapArr) will be altered!
+ *
+ * @param mapArr {Map[]} An array containing a map for each row. Each
+ * row-map contains the column IDs as key and the cell values as value.
+ * @param startIndex {int ? null} The index where to insert the new rows. If null,
+ * the rows are appended to the end.
+ */
+qx.Proto.addRowsAsMapArray = function(mapArr, startIndex) {
+ this.addRows(this._mapArray2RowArr(mapArr), startIndex);
+};
+
+
+/**
+ * Removes some rows from the model.
+ *
+ * @param startIndex {int} the index of the first row to remove.
+ * @param howMany {int} the number of rows to remove.
+ */
+qx.Proto.removeRows = function(startIndex, howMany) {
+ this._rowArr.splice(startIndex, howMany);
+
+ // Inform the listeners
+ if (this.hasEventListeners(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED)) {
+ var data = { firstRow:startIndex, lastRow:this._rowArr.length - 1, firstColumn:0, lastColumn:this.getColumnCount() - 1 };
+ this.dispatchEvent(new qx.event.type.DataEvent(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, data), true);
+ }
+
+ this._clearSorting();
+};
+
+
+/**
+ * Creates an array of maps to an array of arrays.
+ *
+ * @param mapArr {Map[]} An array containing a map for each row. Each
+ * row-map contains the column IDs as key and the cell values as value.
+ * @return {var[][]} An array containing an array for each row. Each
+ * row-array contains the values in that row in the order of the columns
+ * in this model.
+ */
+qx.Proto._mapArray2RowArr = function(mapArr) {
+ var rowCount = mapArr.length;
+ var columnCount = this.getColumnCount();
+ var dataArr = new Array(rowCount);
+ var columnArr;
+ var j;
+ for (var i = 0; i < rowCount; ++i) {
+ columnArr = new Array(columnCount);
+ for (var j = 0; j < columnCount; ++j) {
+ columnArr[j] = mapArr[i][this.getColumnId(j)];
+ }
+ dataArr[i] = columnArr;
+ }
+
+ return dataArr;
+};
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/Table.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/Table.js
new file mode 100644
index 0000000000..360662e718
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/Table.js
@@ -0,0 +1,1062 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+#require(qx.ui.table.DefaultDataRowRenderer)
+
+************************************************************************ */
+
+/**
+ * A table.
+ *
+ * @param tableModel {qx.ui.table.TableModel} The table
+ * model to read the data from.
+ */
+qx.OO.defineClass("qx.ui.table.Table", qx.ui.layout.VerticalBoxLayout,
+function(tableModel) {
+ qx.ui.layout.VerticalBoxLayout.call(this);
+
+ // Create the child widgets
+ this._scrollerParent = new qx.ui.layout.HorizontalBoxLayout;
+ this._scrollerParent.setDimension("100%", "1*");
+ this._scrollerParent.setSpacing(1);
+
+ this._statusBar = new qx.ui.basic.Label;
+ this._statusBar.setAppearance("table-focus-statusbar");
+ this._statusBar.setDimension("100%", "auto");
+
+ this.add(this._scrollerParent, this._statusBar);
+
+ this._columnVisibilityBt = new qx.ui.toolbar.Button(null, "widget/table/selectColumnOrder.png");
+ this._columnVisibilityBt.addEventListener("execute", this._onColumnVisibilityBtExecuted, this);
+
+ // Create the models
+ this._selectionManager = new qx.ui.table.SelectionManager;
+
+ this.setSelectionModel(new qx.ui.table.SelectionModel);
+ this.setTableColumnModel(new qx.ui.table.TableColumnModel);
+ this.setTableModel(tableModel);
+
+ // Update the status bar
+ this._updateStatusBar();
+
+ // create the main meta column
+ this.setMetaColumnCounts([ -1 ]);
+
+ // Make focusable
+ this.setTabIndex(1);
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keypress", this._onkeypress);
+ this.addEventListener("changeFocused", this._onFocusChanged);
+
+ this._focusedCol = 0;
+ this._focusedRow = 0;
+});
+
+
+/** The default row renderer to use when {@link #dataRowRenderer} is null. */
+qx.Class.DEFAULT_DATA_ROW_RENDERER = new qx.ui.table.DefaultDataRowRenderer();
+
+
+/** The selection model. */
+qx.OO.addProperty({ name:"selectionModel", type:"object", instance : "qx.ui.table.SelectionModel" });
+
+/** The table model. */
+qx.OO.addProperty({ name:"tableModel", type:"object", instance : "qx.ui.table.TableModel" });
+
+/** The table column model. */
+qx.OO.addProperty({ name:"tableColumnModel", type:"object", instance : "qx.ui.table.TableColumnModel" });
+
+/** The height of the table rows. */
+qx.OO.addProperty({ name:"rowHeight", type:"number", defaultValue:15 });
+
+/** Whether to show the status bar */
+qx.OO.addProperty({ name:"statusBarVisible", type:"boolean", defaultValue:true });
+
+/** Whether to show the column visibility button */
+qx.OO.addProperty({ name:"columnVisibilityButtonVisible", type:"boolean", defaultValue:true });
+
+/**
+ * {int[]} The number of columns per meta column. If the last array entry is -1,
+ * this meta column will get the remaining columns.
+ */
+qx.OO.addProperty({ name:"metaColumnCounts", type:"object" });
+
+/**
+ * Whether the focus should moved when the mouse is moved over a cell. If false
+ * the focus is only moved on mouse clicks.
+ */
+qx.OO.addProperty({ name:"focusCellOnMouseMove", type:"boolean", defaultValue:false });
+
+/**
+ * Whether the table should keep the first visible row complete. If set to false,
+ * the first row may be rendered partial, depending on the vertical scroll value.
+ */
+qx.OO.addProperty({ name:"keepFirstVisibleRowComplete", type:"boolean", defaultValue:true });
+
+/**
+ * Whether the table cells should be updated when only the selection or the
+ * focus changed. This slows down the table update but allows to react on a
+ * changed selection or a changed focus in a cell renderer.
+ */
+qx.OO.addProperty({ name:"alwaysUpdateCells", type:"boolean", defaultValue:false });
+
+/** The height of the header cells. */
+qx.OO.addProperty({ name:"headerCellHeight", type:"number", defaultValue:16, allowNull:false });
+
+/** The renderer to use for styling the rows. */
+qx.OO.addProperty({ name:"dataRowRenderer", type:"object", instance:"qx.ui.table.DataRowRenderer", defaultValue:qx.Class.DEFAULT_DATA_ROW_RENDERER, allowNull:false });
+
+
+// property modifier
+qx.Proto._modifySelectionModel = function(propValue, propOldValue, propData) {
+ this._selectionManager.setSelectionModel(propValue);
+
+ if (propOldValue != null) {
+ propOldValue.removeEventListener("changeSelection", this._onSelectionChanged, this);
+ }
+ propValue.addEventListener("changeSelection", this._onSelectionChanged, this);
+
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyTableModel = function(propValue, propOldValue, propData) {
+ this.getTableColumnModel().init(propValue.getColumnCount());
+
+ if (propOldValue != null) {
+ propOldValue.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED, this._onTableModelMetaDataChanged, this);
+ propOldValue.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, this._onTableModelDataChanged, this);
+ }
+ propValue.addEventListener(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED, this._onTableModelMetaDataChanged, this);
+ propValue.addEventListener(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, this._onTableModelDataChanged, this);
+
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyTableColumnModel = function(propValue, propOldValue, propData) {
+ if (propOldValue != null) {
+ propOldValue.removeEventListener("visibilityChanged", this._onColVisibilityChanged, this);
+ propOldValue.removeEventListener("widthChanged", this._onColWidthChanged, this);
+ propOldValue.removeEventListener("orderChanged", this._onColOrderChanged, this);
+ }
+ propValue.addEventListener("visibilityChanged", this._onColVisibilityChanged, this);
+ propValue.addEventListener("widthChanged", this._onColWidthChanged, this);
+ propValue.addEventListener("orderChanged", this._onColOrderChanged, this);
+
+ return true;
+};
+
+
+// property modifier
+qx.Proto._modifyStatusBarVisible = function(propValue, propOldValue, propData) {
+ this._statusBar.setDisplay(propValue);
+
+ if (propValue) {
+ this._updateStatusBar();
+ }
+ return true;
+};
+
+
+// property modifier
+qx.Proto._modifyColumnVisibilityButtonVisible = function(propValue, propOldValue, propData) {
+ this._columnVisibilityBt.setDisplay(propValue);
+
+ return true;
+};
+
+
+// property modifier
+qx.Proto._modifyMetaColumnCounts = function(propValue, propOldValue, propData) {
+ var metaColumnCounts = propValue;
+ var scrollerArr = this._getPaneScrollerArr();
+
+ // Remove the panes not needed any more
+ this._cleanUpMetaColumns(metaColumnCounts.length);
+
+ // Update the old panes
+ var leftX = 0;
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var paneScroller = scrollerArr[i];
+ var paneModel = paneScroller.getTablePaneModel();
+ paneModel.setFirstColumnX(leftX);
+ paneModel.setMaxColumnCount(metaColumnCounts[i]);
+ leftX += metaColumnCounts[i];
+ }
+
+ // Add the new panes
+ if (metaColumnCounts.length > scrollerArr.length) {
+ var selectionModel = this.getSelectionModel();
+ var tableModel = this.getTableModel();
+ var columnModel = this.getTableColumnModel();
+
+ for (var i = scrollerArr.length; i < metaColumnCounts.length; i++) {
+ var paneModel = new qx.ui.table.TablePaneModel(columnModel);
+ paneModel.setFirstColumnX(leftX);
+ paneModel.setMaxColumnCount(metaColumnCounts[i]);
+ leftX += metaColumnCounts[i];
+
+ var paneScroller = new qx.ui.table.TablePaneScroller(this);
+ paneScroller.setTablePaneModel(paneModel);
+
+ // Register event listener for vertical scrolling
+ paneScroller.addEventListener("changeScrollY", this._onScrollY, this);
+
+ this._scrollerParent.add(paneScroller);
+ }
+ }
+
+ // Update all meta columns
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var paneScroller = scrollerArr[i];
+ var isLast = (i == (scrollerArr.length - 1));
+
+ // Set the right header height
+ paneScroller.getHeader().setHeight(this.getHeaderCellHeight());
+
+ // Put the _columnVisibilityBt in the top right corner of the last meta column
+ paneScroller.setTopRightWidget(isLast ? this._columnVisibilityBt : null);
+ }
+
+ this._updateScrollerWidths();
+ this._updateScrollBarVisibility();
+
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyFocusCellOnMouseMove = function(propValue, propOldValue, propData) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i].setFocusCellOnMouseMove(propValue);
+ }
+ return true;
+};
+
+
+// property modifier
+qx.Proto._modifyKeepFirstVisibleRowComplete = function(propValue, propOldValue, propData) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onKeepFirstVisibleRowCompleteChanged();
+ }
+ return true;
+};
+
+
+// property modifier
+qx.Proto._modifyHeaderCellHeight = function(propValue, propOldValue, propData) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i].getHeader().setHeight(propValue);
+ }
+ return true;
+};
+
+
+/**
+ * Returns the selection manager.
+ *
+ * @return {SelectionManager} the selection manager.
+ */
+qx.Proto._getSelectionManager = function() {
+ return this._selectionManager;
+};
+
+
+/**
+ * Returns an array containing all TablePaneScrollers in this table.
+ *
+ * @return {TablePaneScroller[]} all TablePaneScrollers in this table.
+ */
+qx.Proto._getPaneScrollerArr = function() {
+ return this._scrollerParent.getChildren();
+}
+
+
+/**
+ * Returns a TablePaneScroller of this table.
+ *
+ * @param metaColumn {int} the meta column to get the TablePaneScroller for.
+ * @return {TablePaneScroller} the TablePaneScroller.
+ */
+qx.Proto.getPaneScroller = function(metaColumn) {
+ return this._getPaneScrollerArr()[metaColumn];
+}
+
+
+/**
+ * Cleans up the meta columns.
+ *
+ * @param fromMetaColumn {int} the first meta column to clean up. All following
+ * meta columns will be cleaned up, too. All previous meta columns will
+ * stay unchanged. If 0 all meta columns will be cleaned up.
+ */
+qx.Proto._cleanUpMetaColumns = function(fromMetaColumn) {
+ var scrollerArr = this._getPaneScrollerArr();
+ if (scrollerArr != null) {
+ for (var i = scrollerArr.length - 1; i >= fromMetaColumn; i--) {
+ var paneScroller = scrollerArr[i];
+ paneScroller.removeEventListener("changeScrollY", this._onScrollY, this);
+ this._scrollerParent.remove(paneScroller);
+ paneScroller.dispose();
+ }
+ }
+}
+
+
+/**
+ * Event handler. Called when the selection has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onSelectionChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onSelectionChanged(evt);
+ }
+
+ this._updateStatusBar();
+}
+
+
+/**
+ * Event handler. Called when the table model meta data has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onTableModelMetaDataChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onTableModelMetaDataChanged(evt);
+ }
+
+ this._updateStatusBar();
+}
+
+
+/**
+ * Event handler. Called when the table model data has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onTableModelDataChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onTableModelDataChanged(evt);
+ }
+
+ var rowCount = this.getTableModel().getRowCount();
+ if (rowCount != this._lastRowCount) {
+ this._lastRowCount = rowCount;
+
+ this._updateScrollBarVisibility();
+ this._updateStatusBar();
+ }
+};
+
+
+/**
+ * Event handler. Called when a TablePaneScroller has been scrolled vertically.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onScrollY = function(evt) {
+ if (! this._internalChange) {
+ this._internalChange = true;
+
+ // Set the same scroll position to all meta columns
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i].setScrollY(evt.getData());
+ }
+
+ this._internalChange = false;
+ }
+}
+
+
+/**
+ * Event handler. Called when a key was pressed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onkeydown = function(evt) {
+ var identifier = evt.getKeyIdentifier();
+
+ var consumed = false;
+ var oldFocusedRow = this._focusedRow;
+ if (this.isEditing()) {
+ // Editing mode
+ if (evt.getModifiers() == 0) {
+ consumed = true;
+ switch (identifier) {
+ case "Enter":
+ this.stopEditing();
+ var oldFocusedRow = this._focusedRow;
+ this.moveFocusedCell(0, 1);
+ if (this._focusedRow != oldFocusedRow) {
+ this.startEditing();
+ }
+ break;
+ case "Escape":
+ this.cancelEditing();
+ this.focus();
+ break;
+ default:
+ consumed = false;
+ break;
+ }
+ }
+ } else {
+ // No editing mode
+
+ // Handle keys that are independant from the modifiers
+ consumed = true;
+ switch (identifier) {
+ case "Home":
+ this.setFocusedCell(this._focusedCol, 0, true);
+ break;
+ case "End":
+ var rowCount = this.getTableModel().getRowCount();
+ this.setFocusedCell(this._focusedCol, rowCount - 1, true);
+ break;
+ default:
+ consumed = false;
+ break;
+ }
+
+ // Handle keys that depend on modifiers
+ if (evt.getModifiers() == 0) {
+ consumed = true;
+ switch (identifier) {
+ case "F2":
+ case "Enter":
+ this.startEditing();
+ break;
+ default:
+ consumed = false;
+ break;
+ }
+ } else if (evt.getCtrlKey()) {
+ consumed = true;
+ switch (identifier) {
+ case "A": // Ctrl + A
+ var rowCount = this.getTableModel().getRowCount();
+ if (rowCount > 0) {
+ this.getSelectionModel().setSelectionInterval(0, rowCount - 1);
+ }
+ break;
+ default:
+ consumed = false;
+ break;
+ }
+ }
+ }
+
+ if (oldFocusedRow != this._focusedRow) {
+ // The focus moved -> Let the selection manager handle this event
+ this._selectionManager.handleMoveKeyDown(this._focusedRow, evt);
+ }
+
+ if (consumed) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+};
+
+
+qx.Proto._onkeypress = function(evt)
+{
+ if (this.isEditing()) { return }
+ // No editing mode
+ var oldFocusedRow = this._focusedRow;
+ var consumed = true;
+
+ // Handle keys that are independant from the modifiers
+ var identifier = evt.getKeyIdentifier();
+ switch (identifier) {
+ case "Space":
+ this._selectionManager.handleSelectKeyDown(this._focusedRow, evt);
+ break;
+
+ case "Left":
+ this.moveFocusedCell(-1, 0);
+ break;
+
+ case "Right":
+ this.moveFocusedCell(1, 0);
+ break;
+
+ case "Up":
+ this.moveFocusedCell(0, -1);
+ break;
+
+ case "Down":
+ this.moveFocusedCell(0, 1);
+ break;
+
+ case "PageUp":
+ case "PageDown":
+ var scroller = this.getPaneScroller(0);
+ var pane = scroller.getTablePane();
+ var rowCount = pane.getVisibleRowCount() - 1;
+ var rowHeight = this.getRowHeight();
+ var direction = (identifier == "PageUp") ? -1 : 1;
+ scroller.setScrollY(scroller.getScrollY() + direction * rowCount * rowHeight);
+ this.moveFocusedCell(0, direction * rowCount);
+ break;
+
+ default:
+ consumed = false;
+ }
+ if (oldFocusedRow != this._focusedRow) {
+ // The focus moved -> Let the selection manager handle this event
+ this._selectionManager.handleMoveKeyDown(this._focusedRow, evt);
+ }
+
+ if (consumed) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ }
+};
+
+
+/**
+ * Event handler. Called when the table gets the focus.
+ */
+qx.Proto._onFocusChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onFocusChanged(evt);
+ }
+};
+
+
+/**
+ * Event handler. Called when the visibility of a column has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColVisibilityChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onColVisibilityChanged(evt);
+ }
+
+ this._updateScrollerWidths();
+ this._updateScrollBarVisibility();
+}
+
+
+/**
+ * Event handler. Called when the width of a column has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColWidthChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onColWidthChanged(evt);
+ }
+
+ this._updateScrollerWidths();
+ this._updateScrollBarVisibility();
+}
+
+
+/**
+ * Event handler. Called when the column order has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColOrderChanged = function(evt) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i]._onColOrderChanged(evt);
+ }
+
+ // A column may have been moved between meta columns
+ this._updateScrollerWidths();
+ this._updateScrollBarVisibility();
+}
+
+
+/**
+ * Gets the TablePaneScroller at a certain x position in the page. If there is
+ * no TablePaneScroller at this postion, null is returned.
+ *
+ * @param pageX {int} the position in the page to check (in pixels).
+ * @return {TablePaneScroller} the TablePaneScroller or null.
+ *
+ * @see TablePaneScrollerPool
+ */
+qx.Proto.getTablePaneScrollerAtPageX = function(pageX) {
+ var metaCol = this._getMetaColumnAtPageX(pageX);
+ return (metaCol != -1) ? this.getPaneScroller(metaCol) : null;
+}
+
+
+/**
+ * Sets the currently focused cell.
+ *
+ * @param col {int} the model index of the focused cell's column.
+ * @param row {int} the model index of the focused cell's row.
+ * @param scrollVisible {boolean ? false} whether to scroll the new focused cell
+ * visible.
+ *
+ * @see TablePaneScrollerPool
+ */
+qx.Proto.setFocusedCell = function(col, row, scrollVisible) {
+ if (!this.isEditing() && (col != this._focusedCol || row != this._focusedRow)) {
+ this._focusedCol = col;
+ this._focusedRow = row;
+
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ scrollerArr[i].setFocusedCell(col, row);
+ }
+
+ if (scrollVisible) {
+ this.scrollCellVisible(col, row);
+ }
+ }
+}
+
+
+/**
+ * Returns the column of the currently focused cell.
+ *
+ * @return {int} the model index of the focused cell's column.
+ */
+qx.Proto.getFocusedColumn = function() {
+ return this._focusedCol;
+};
+
+
+/**
+ * Returns the row of the currently focused cell.
+ *
+ * @return {int} the model index of the focused cell's column.
+ */
+qx.Proto.getFocusedRow = function() {
+ return this._focusedRow;
+};
+
+
+/**
+ * Moves the focus.
+ *
+ * @param deltaX {int} The delta by which the focus should be moved on the x axis.
+ * @param deltaY {int} The delta by which the focus should be moved on the y axis.
+ */
+qx.Proto.moveFocusedCell = function(deltaX, deltaY) {
+ var col = this._focusedCol;
+ var row = this._focusedRow;
+
+ if (deltaX != 0) {
+ var columnModel = this.getTableColumnModel();
+ var x = columnModel.getVisibleX(col);
+ var colCount = columnModel.getVisibleColumnCount();
+ x = qx.lang.Number.limit(x + deltaX, 0, colCount - 1);
+ col = columnModel.getVisibleColumnAtX(x);
+ }
+
+ if (deltaY != 0) {
+ var tableModel = this.getTableModel();
+ row = qx.lang.Number.limit(row + deltaY, 0, tableModel.getRowCount() - 1);
+ }
+
+ this.setFocusedCell(col, row, true);
+}
+
+
+/**
+ * Scrolls a cell visible.
+ *
+ * @param col {int} the model index of the column the cell belongs to.
+ * @param row {int} the model index of the row the cell belongs to.
+ */
+qx.Proto.scrollCellVisible = function(col, row) {
+ var columnModel = this.getTableColumnModel();
+ var x = columnModel.getVisibleX(col);
+
+ var metaColumn = this._getMetaColumnAtColumnX(x);
+ if (metaColumn != -1) {
+ this.getPaneScroller(metaColumn).scrollCellVisible(col, row);
+ }
+}
+
+
+/**
+ * Returns whether currently a cell is editing.
+ *
+ * @return whether currently a cell is editing.
+ */
+qx.Proto.isEditing = function() {
+ if (this._focusedCol != null) {
+ var x = this.getTableColumnModel().getVisibleX(this._focusedCol);
+ var metaColumn = this._getMetaColumnAtColumnX(x);
+ return this.getPaneScroller(metaColumn).isEditing();
+ }
+}
+
+
+/**
+ * Starts editing the currently focused cell. Does nothing if already editing
+ * or if the column is not editable.
+ *
+ * @return {boolean} whether editing was started
+ */
+qx.Proto.startEditing = function() {
+ if (this._focusedCol != null) {
+ var x = this.getTableColumnModel().getVisibleX(this._focusedCol);
+ var metaColumn = this._getMetaColumnAtColumnX(x);
+ return this.getPaneScroller(metaColumn).startEditing();
+ }
+ return false;
+}
+
+
+/**
+ * Stops editing and writes the editor's value to the model.
+ */
+qx.Proto.stopEditing = function() {
+ if (this._focusedCol != null) {
+ var x = this.getTableColumnModel().getVisibleX(this._focusedCol);
+ var metaColumn = this._getMetaColumnAtColumnX(x);
+ this.getPaneScroller(metaColumn).stopEditing();
+ }
+}
+
+
+/**
+ * Stops editing without writing the editor's value to the model.
+ */
+qx.Proto.cancelEditing = function() {
+ if (this._focusedCol != null) {
+ var x = this.getTableColumnModel().getVisibleX(this._focusedCol);
+ var metaColumn = this._getMetaColumnAtColumnX(x);
+ this.getPaneScroller(metaColumn).cancelEditing();
+ }
+}
+
+
+/**
+ * Gets the meta column at a certain x position in the page. If there is no
+ * meta column at this postion, -1 is returned.
+ *
+ * @param pageX {int} the position in the page to check (in pixels).
+ * @return {int} the index of the meta column or -1.
+ */
+qx.Proto._getMetaColumnAtPageX = function(pageX) {
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var elem = scrollerArr[i].getElement();
+ if (pageX >= qx.dom.Location.getPageBoxLeft(elem)
+ && pageX <= qx.dom.Location.getPageBoxRight(elem))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/**
+ * Returns the meta column a column is shown in. If the column is not shown at
+ * all, -1 is returned.
+ *
+ * @param visXPos {int} the visible x position of the column.
+ * @return {int} the meta column the column is shown in.
+ */
+qx.Proto._getMetaColumnAtColumnX = function(visXPos) {
+ var metaColumnCounts = this.getMetaColumnCounts();
+ var rightXPos = 0;
+ for (var i = 0; i < metaColumnCounts.length; i++) {
+ var counts = metaColumnCounts[i];
+ rightXPos += counts;
+
+ if (counts == -1 || visXPos < rightXPos) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+
+/**
+ * Updates the text shown in the status bar.
+ */
+qx.Proto._updateStatusBar = function() {
+ if (this.getStatusBarVisible()) {
+ var selectedRowCount = this.getSelectionModel().getSelectedCount();
+ var rowCount = this.getTableModel().getRowCount();
+
+ var text;
+ if (selectedRowCount == 0) {
+ text = rowCount + ((rowCount == 1) ? " row" : " rows");
+ } else {
+ text = selectedRowCount + " of " + rowCount
+ + ((rowCount == 1) ? " row" : " rows") + " selected";
+ }
+ this._statusBar.setHtml(text);
+ }
+}
+
+
+/**
+ * Updates the widths of all scrollers.
+ */
+qx.Proto._updateScrollerWidths = function() {
+/* no longer needed, per Til, and removing it does not appear to add problems.
+ * qx.ui.core.Widget.flushGlobalQueues();
+ */
+
+ // Give all scrollers except for the last one the wanted width
+ // (The last one has a flex with)
+ var scrollerArr = this._getPaneScrollerArr();
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var isLast = (i == (scrollerArr.length - 1));
+ var width = isLast ? "1*" : scrollerArr[i].getTablePaneModel().getTotalWidth();
+ scrollerArr[i].setWidth(width);
+ }
+}
+
+
+/**
+ * Updates the visibility of the scrollbars in the meta columns.
+ */
+qx.Proto._updateScrollBarVisibility = function() {
+ if (this.isSeeable()) {
+ var horBar = qx.ui.table.TablePaneScroller.HORIZONTAL_SCROLLBAR;
+ var verBar = qx.ui.table.TablePaneScroller.VERTICAL_SCROLLBAR;
+ var scrollerArr = this._getPaneScrollerArr();
+
+ // Check which scroll bars are needed
+ var horNeeded = false;
+ var verNeeded = false;
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var isLast = (i == (scrollerArr.length - 1));
+
+ // Only show the last vertical scrollbar
+ var bars = scrollerArr[i].getNeededScrollBars(horNeeded, !isLast);
+
+ if (bars & horBar) {
+ horNeeded = true;
+ }
+ if (isLast && (bars & verBar)) {
+ verNeeded = true;
+ }
+ }
+
+ // Set the needed scrollbars
+ for (var i = 0; i < scrollerArr.length; i++) {
+ var isLast = (i == (scrollerArr.length - 1));
+
+ // Only show the last vertical scrollbar
+ scrollerArr[i].setHorizontalScrollBarVisible(horNeeded);
+ scrollerArr[i].setVerticalScrollBarVisible(isLast && verNeeded);
+ }
+ }
+}
+
+
+/**
+ * Event handler. Called when the column visibiliy button was executed.
+ */
+qx.Proto._onColumnVisibilityBtExecuted = function() {
+ if ((this._columnVisibilityMenuCloseTime == null)
+ || (new Date().getTime() > this._columnVisibilityMenuCloseTime + 200))
+ {
+ this._toggleColumnVisibilityMenu();
+ }
+}
+
+
+/**
+ * Toggels the visibility of the menu used to change the visibility of columns.
+ */
+qx.Proto._toggleColumnVisibilityMenu = function() {
+ if (this._columnVisibilityMenu == null || !this._columnVisibilityMenu.isSeeable()) {
+ // Show the menu
+
+ // Create the new menu
+ var menu = new qx.ui.menu.Menu;
+
+ menu.addEventListener("disappear", function(evt) {
+ this._columnVisibilityMenuCloseTime = new Date().getTime();
+ }, this);
+
+ var tableModel = this.getTableModel();
+ var columnModel = this.getTableColumnModel();
+ for (var x = 0; x < columnModel.getOverallColumnCount(); x++) {
+ var col = columnModel.getOverallColumnAtX(x);
+ var visible = columnModel.isColumnVisible(col);
+ var cmd = { col:col }
+ var bt = new qx.ui.menu.CheckBox(tableModel.getColumnName(col), null, visible);
+
+ var handler = this._createColumnVisibilityCheckBoxHandler(col);
+ bt._handler = handler;
+ bt.addEventListener("execute", handler, this);
+
+ menu.add(bt);
+ }
+
+ menu.setParent(this.getTopLevelWidget());
+
+ this._columnVisibilityMenu = menu;
+
+ // Show the menu
+ var btElem = this._columnVisibilityBt.getElement();
+ menu.setRestrictToPageOnOpen(false);
+ menu.setTop(qx.dom.Location.getClientBoxBottom(btElem));
+ menu.setLeft(-1000);
+
+ // NOTE: We have to show the menu in a timeout, otherwise it won't be shown
+ // at all.
+ window.setTimeout(function() {
+ menu.show();
+ qx.ui.core.Widget.flushGlobalQueues();
+
+ menu.setLeft(qx.dom.Location.getClientBoxRight(btElem) - menu.getOffsetWidth());
+ qx.ui.core.Widget.flushGlobalQueues();
+ }, 0);
+ } else {
+ // hide the menu
+ menu.hide();
+ this._cleanupColumnVisibilityMenu();
+ }
+}
+
+
+/**
+ * Cleans up the column visibility menu.
+ */
+qx.Proto._cleanupColumnVisibilityMenu = function() {
+ if (this._columnVisibilityMenu != null && ! this._columnVisibilityMenu.getDisposed()) {
+ this._columnVisibilityMenu.dispose();
+ this._columnVisibilityMenu = null;
+ }
+}
+
+
+/**
+ * Creates a handler for a check box of the column visibility menu.
+ *
+ * @param col {int} the model index of column to create the handler for.
+ */
+qx.Proto._createColumnVisibilityCheckBoxHandler = function(col) {
+ return function(evt) {
+ var columnModel = this.getTableColumnModel();
+ columnModel.setColumnVisible(col, !columnModel.isColumnVisible(col));
+ }
+}
+
+
+/**
+ * Sets the width of a column.
+ *
+ * @param col {int} the model index of column.
+ * @param width {int} the new width in pixels.
+ */
+qx.Proto.setColumnWidth = function(col, width) {
+ this.getTableColumnModel().setColumnWidth(col, width);
+}
+
+
+// overridden
+qx.Proto._changeInnerWidth = function(newValue, oldValue) {
+ var self = this;
+ window.setTimeout(function() {
+ self._updateScrollBarVisibility();
+ qx.ui.core.Widget.flushGlobalQueues();
+ }, 0);
+
+ return qx.ui.layout.VerticalBoxLayout.prototype._changeInnerWidth.call(this, newValue, oldValue);
+}
+
+
+// overridden
+qx.Proto._changeInnerHeight = function(newValue, oldValue) {
+ var self = this;
+ window.setTimeout(function() {
+ self._updateScrollBarVisibility();
+ qx.ui.core.Widget.flushGlobalQueues();
+ }, 0);
+
+ return qx.ui.layout.VerticalBoxLayout.prototype._changeInnerHeight.call(this, newValue, oldValue);
+}
+
+
+// overridden
+qx.Proto._afterAppear = function() {
+ qx.ui.layout.VerticalBoxLayout.prototype._afterAppear.call(this);
+
+ this._updateScrollBarVisibility();
+}
+
+
+// overridden
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._tableModel) {
+ this._tableModel.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED, this._onTableModelMetaDataChanged, this);
+ }
+
+ this._columnVisibilityBt.removeEventListener("execute", this._onColumnVisibilityBtExecuted, this);
+ this._columnVisibilityBt.dispose();
+
+ this._cleanupColumnVisibilityMenu();
+
+ this._cleanUpMetaColumns(0);
+
+ var selectionModel = this.getSelectionModel();
+ if (selectionModel != null) {
+ selectionModel.removeEventListener("changeSelection", this._onSelectionChanged, this);
+ }
+
+ var tableModel = this.getTableModel();
+ if (tableModel != null) {
+ tableModel.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_META_DATA_CHANGED, this._onTableModelMetaDataChanged, this);
+ tableModel.removeEventListener(qx.ui.table.TableModel.EVENT_TYPE_DATA_CHANGED, this._onTableModelDataChanged, this);
+ }
+
+ var tableColumnModel = this.getTableColumnModel();
+ if (tableColumnModel) {
+ tableColumnModel.removeEventListener("visibilityChanged", this._onColVisibilityChanged, this);
+ tableColumnModel.removeEventListener("widthChanged", this._onColWidthChanged, this);
+ tableColumnModel.removeEventListener("orderChanged", this._onColOrderChanged, this);
+ }
+
+ this.removeEventListener("keydown", this._onkeydown);
+ this.removeEventListener("keypress", this._onkeypress);
+
+ return qx.ui.layout.VerticalBoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TableColumnModel.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TableColumnModel.js
new file mode 100644
index 0000000000..334187a268
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TableColumnModel.js
@@ -0,0 +1,399 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+// These are needed because of their instantiation at bottom. I don't think this
+// is a good idea. (wpbasti)
+#require(qx.ui.table.DefaultHeaderCellRenderer)
+#require(qx.ui.table.DefaultDataCellRenderer)
+#require(qx.ui.table.TextFieldCellEditorFactory)
+
+************************************************************************ */
+
+/**
+ * A model that contains all meta data about columns, such as width, renderers,
+ * visibility and order.
+ *
+ * @event widthChanged {qx.event.type.DataEvent} Fired when the width of a
+ * column has changed. The data property of the event is a map having the
+ * following attributes:
+ *
+ * col: The model index of the column the width of which has changed.
+ * newWidth: The new width of the column in pixels.
+ * oldWidth: The old width of the column in pixels.
+ *
+ * @event visibilityChangedPre {qx.event.type.DataEvent} Fired when the
+ * visibility of a column has changed. This event is equal to
+ * "visibilityChanged", but is fired right before.
+ * @event visibilityChanged {qx.event.type.DataEvent} Fired when the
+ * visibility of a column has changed. The data property of the
+ * event is a map having the following attributes:
+ *
+ * col: The model index of the column the visibility of which has changed.
+ * visible: Whether the column is now visible.
+ *
+ * @event orderChanged {qx.event.type.DataEvent} Fired when the column order
+ * has changed. The data property of the
+ * event is a map having the following attributes:
+ *
+ * col: The model index of the column that was moved.
+ * fromOverXPos: The old overall x position of the column.
+ * toOverXPos: The new overall x position of the column.
+ *
+ *
+ * @see com.ptvag.webcomponent.ui.table.TableModel
+ */
+qx.OO.defineClass("qx.ui.table.TableColumnModel", qx.core.Target,
+function() {
+ qx.core.Target.call(this);
+});
+
+
+/**
+ * Initializes the column model.
+ *
+ * @param colCount {int} the number of columns the model should have.
+ */
+qx.Proto.init = function(colCount) {
+ this._columnDataArr = [];
+
+ var width = qx.ui.table.TableColumnModel.DEFAULT_WIDTH;
+ var headerRenderer = qx.ui.table.TableColumnModel.DEFAULT_HEADER_RENDERER;
+ var dataRenderer = qx.ui.table.TableColumnModel.DEFAULT_DATA_RENDERER;
+ var editorFactory = qx.ui.table.TableColumnModel.DEFAULT_EDITOR_FACTORY;
+ this._overallColumnArr = [];
+ this._visibleColumnArr = [];
+ for (var col = 0; col < colCount; col++) {
+ this._columnDataArr[col] = { width:width, headerRenderer:headerRenderer,
+ dataRenderer:dataRenderer, editorFactory:editorFactory }
+ this._overallColumnArr[col] = col;
+ this._visibleColumnArr[col] = col;
+ }
+
+ this._colToXPosMap = null;
+}
+
+
+/**
+ * Sets the width of a column.
+ *
+ * @param col {int} the model index of the column.
+ * @param width {int} the new width the column should get in pixels.
+ */
+qx.Proto.setColumnWidth = function(col, width) {
+ var oldWidth = this._columnDataArr[col].width;
+ if (oldWidth != width) {
+ this._columnDataArr[col].width = width;
+ if (this.hasEventListeners("widthChanged")) {
+ var data = { col:col, newWidth:width, oldWidth:oldWidth }
+ this.dispatchEvent(new qx.event.type.DataEvent("widthChanged", data), true);
+ }
+ }
+}
+
+
+/**
+ * Returns the width of a column.
+ *
+ * @param col {int} the model index of the column.
+ * @return {int} the width of the column in pixels.
+ */
+qx.Proto.getColumnWidth = function(col) {
+ return this._columnDataArr[col].width;
+}
+
+
+/**
+ * Sets the header renderer of a column.
+ *
+ * @param col {int} the model index of the column.
+ * @param renderer {HeaderCellRenderer} the new header renderer the column
+ * should get.
+ */
+qx.Proto.setHeaderCellRenderer = function(col, renderer) {
+ this._columnDataArr[col].headerRenderer = renderer;
+}
+
+
+/**
+ * Returns the header renderer of a column.
+ *
+ * @param col {int} the model index of the column.
+ * @return {HeaderCellRenderer} the header renderer of the column.
+ */
+qx.Proto.getHeaderCellRenderer = function(col) {
+ return this._columnDataArr[col].headerRenderer;
+}
+
+
+/**
+ * Sets the data renderer of a column.
+ *
+ * @param col {int} the model index of the column.
+ * @param renderer {DataCellRenderer} the new data renderer the column should get.
+ */
+qx.Proto.setDataCellRenderer = function(col, renderer) {
+ this._columnDataArr[col].dataRenderer = renderer;
+}
+
+
+/**
+ * Returns the data renderer of a column.
+ *
+ * @param col {int} the model index of the column.
+ * @return {DataCellRenderer} the data renderer of the column.
+ */
+qx.Proto.getDataCellRenderer = function(col) {
+ return this._columnDataArr[col].dataRenderer;
+}
+
+
+/**
+ * Sets the cell editor factory of a column.
+ *
+ * @param col {int} the model index of the column.
+ * @param factory {CellEditorFactory} the new cell editor factory the column should get.
+ */
+qx.Proto.setCellEditorFactory = function(col, factory) {
+ this._columnDataArr[col].editorFactory = factory;
+}
+
+
+/**
+ * Returns the cell editor factory of a column.
+ *
+ * @param col {int} the model index of the column.
+ * @return {CellEditorFactory} the cell editor factory of the column.
+ */
+qx.Proto.getCellEditorFactory = function(col) {
+ return this._columnDataArr[col].editorFactory;
+}
+
+
+/**
+ * Returns the map that translates model indexes to x positions.
+ *
+ * The returned map contains for a model index (int) a map having two
+ * properties: overX (the overall x position of the column, int) and
+ * visX (the visible x position of the column, int). visX is missing for
+ * hidden columns.
+ *
+ * @return the "column to x postion" map.
+ */
+qx.Proto._getColToXPosMap = function() {
+ if (this._colToXPosMap == null) {
+ this._colToXPosMap = {};
+ for (var overX = 0; overX < this._overallColumnArr.length; overX++) {
+ var col = this._overallColumnArr[overX];
+ this._colToXPosMap[col] = { overX:overX }
+ }
+ for (var visX = 0; visX < this._visibleColumnArr.length; visX++) {
+ var col = this._visibleColumnArr[visX];
+ this._colToXPosMap[col].visX = visX;
+ }
+ }
+ return this._colToXPosMap;
+}
+
+
+/**
+ * Returns the number of visible columns.
+ *
+ * @return {int} the number of visible columns.
+ */
+qx.Proto.getVisibleColumnCount = function() {
+ return this._visibleColumnArr.length;
+}
+
+
+/**
+ * Returns the model index of a column at a certain visible x position.
+ *
+ * @param visXPos {int} the visible x position of the column.
+ * @return {int} the model index of the column.
+ */
+qx.Proto.getVisibleColumnAtX = function(visXPos) {
+ return this._visibleColumnArr[visXPos];
+}
+
+
+/**
+ * Returns the visible x position of a column.
+ *
+ * @param col {int} the model index of the column.
+ * @return {int} the visible x position of the column.
+ */
+qx.Proto.getVisibleX = function(col) {
+ return this._getColToXPosMap()[col].visX;
+}
+
+
+/**
+ * Returns the overall number of columns (including hidden columns).
+ *
+ * @return {int} the overall number of columns.
+ */
+qx.Proto.getOverallColumnCount = function() {
+ return this._overallColumnArr.length;
+}
+
+
+/**
+ * Returns the model index of a column at a certain overall x position.
+ *
+ * @param overXPos {int} the overall x position of the column.
+ * @return {int} the model index of the column.
+ */
+qx.Proto.getOverallColumnAtX = function(overXPos) {
+ return this._overallColumnArr[overXPos];
+}
+
+
+/**
+ * Returns the overall x position of a column.
+ *
+ * @param col {int} the model index of the column.
+ * @return {int} the overall x position of the column.
+ */
+qx.Proto.getOverallX = function(col) {
+ return this._getColToXPosMap()[col].overX;
+}
+
+
+/**
+ * Returns whether a certain column is visible.
+ *
+ * @param col {int} the model index of the column.
+ * @return {boolean} whether the column is visible.
+ */
+qx.Proto.isColumnVisible = function(col) {
+ return (this._getColToXPosMap()[col].visX != null);
+}
+
+
+/**
+ * Sets whether a certain column is visible.
+ *
+ * @param col {int} the model index of the column.
+ * @param visible {boolean} whether the column should be visible.
+ */
+qx.Proto.setColumnVisible = function(col, visible) {
+ if (visible != this.isColumnVisible(col)) {
+ if (visible) {
+ var colToXPosMap = this._getColToXPosMap();
+
+ var overX = colToXPosMap[col].overX;
+ if (overX == null) {
+ throw new Error("Showing column failed: " + col
+ + ". The column is not added to this TablePaneModel.");
+ }
+
+ // get the visX of the next visible column after the column to show
+ var nextVisX;
+ for (var x = overX + 1; x < this._overallColumnArr.length; x++) {
+ var currCol = this._overallColumnArr[x];
+ var currVisX = colToXPosMap[currCol].visX;
+ if (currVisX != null) {
+ nextVisX = currVisX;
+ break;
+ }
+ }
+
+ // If there comes no visible column any more, then show the column
+ // at the end
+ if (nextVisX == null) {
+ nextVisX = this._visibleColumnArr.length;
+ }
+
+ // Add the column to the visible columns
+ this._visibleColumnArr.splice(nextVisX, 0, col);
+ } else {
+ var visX = this.getVisibleX(col);
+ this._visibleColumnArr.splice(visX, 1);
+ }
+
+ // Invalidate the _colToXPosMap
+ this._colToXPosMap = null;
+
+ // Inform the listeners
+ if (! this._internalChange) {
+ if (this.hasEventListeners("visibilityChangedPre")) {
+ var data = { col:col, visible:visible }
+ this.dispatchEvent(new qx.event.type.DataEvent("visibilityChangedPre", data), true);
+ }
+ if (this.hasEventListeners("visibilityChanged")) {
+ var data = { col:col, visible:visible }
+ this.dispatchEvent(new qx.event.type.DataEvent("visibilityChanged", data), true);
+ }
+ }
+
+ //this.debug("setColumnVisible col:"+col+",visible:"+visible+",this._overallColumnArr:"+this._overallColumnArr+",this._visibleColumnArr:"+this._visibleColumnArr);
+ }
+}
+
+
+/**
+ * Moves a column.
+ *
+ * @param fromOverXPos {int} the overall x postion of the column to move.
+ * @param toOverXPos {int} the overall x postion of where the column should be
+ * moved to.
+ */
+qx.Proto.moveColumn = function(fromOverXPos, toOverXPos) {
+ this._internalChange = true;
+
+ var col = this._overallColumnArr[fromOverXPos];
+ var visible = this.isColumnVisible(col);
+
+ if (visible) {
+ this.setColumnVisible(col, false);
+ }
+
+ this._overallColumnArr.splice(fromOverXPos, 1);
+ this._overallColumnArr.splice(toOverXPos, 0, col);
+
+ // Invalidate the _colToXPosMap
+ this._colToXPosMap = null;
+
+ if (visible) {
+ this.setColumnVisible(col, true);
+ }
+
+ this._internalChange = false;
+
+ // Inform the listeners
+ if (this.hasEventListeners("orderChanged")) {
+ var data = { col:col, fromOverXPos:fromOverXPos, toOverXPos:toOverXPos }
+ this.dispatchEvent(new qx.event.type.DataEvent("orderChanged", data), true);
+ }
+}
+
+
+/** {int} the default width of a column in pixels. */
+qx.Class.DEFAULT_WIDTH = 100;
+
+/** {DefaultDataCellRenderer} the default header cell renderer. */
+qx.Class.DEFAULT_HEADER_RENDERER = new qx.ui.table.DefaultHeaderCellRenderer;
+
+/** {DefaultDataCellRenderer} the default data cell renderer. */
+qx.Class.DEFAULT_DATA_RENDERER = new qx.ui.table.DefaultDataCellRenderer;
+
+/** {TextFieldCellEditorFactory} the default editor factory. */
+qx.Class.DEFAULT_EDITOR_FACTORY = new qx.ui.table.TextFieldCellEditorFactory;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TableModel.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TableModel.js
new file mode 100644
index 0000000000..6bf4a55291
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TableModel.js
@@ -0,0 +1,243 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * The data model of a table.
+ *
+ * @event dataChanged {qx.event.type.DataEvent} Fired when the table data changed
+ * (the stuff shown in the table body). The data property of the event
+ * may be null or a map having the following attributes:
+ *
+ * firstRow: The index of the first row that has changed.
+ * lastRow: The index of the last row that has changed.
+ * firstColumn: The model index of the first column that has changed.
+ * lastColumn: The model index of the last column that has changed.
+ *
+ * @event metaDataChanged {qx.event.type.Event} Fired when the meta data changed
+ * (the stuff shown in the table header).
+ */
+qx.OO.defineClass("qx.ui.table.TableModel", qx.core.Target,
+function() {
+ qx.core.Target.call(this);
+});
+
+
+/**
+ * Returns the number of rows in the model.
+ *
+ * @return {int} the number of rows.
+ */
+qx.Proto.getRowCount = function() {
+ throw new Error("getRowCount is abstract");
+}
+
+
+/**
+ * Returns the data of one row. This function may be overriden by models which hold
+ * all data of a row in one object. By using this function, clients have a way of
+ * quickly retrieving the entire row data.
+ *
+ * Important: Models which do not have their row data accessible in one object
+ * may return null.
+ *
+ * @param rowIndex {int} the model index of the row.
+ * @return {Object} the row data as an object or null if the model does not support row data
+ * objects. The details on the object returned are determined by the model
+ * implementation only.
+ */
+qx.Proto.getRowData = function(rowIndex) {
+ return null;
+}
+
+
+/**
+ * Returns the number of columns in the model.
+ *
+ * @return {int} the number of columns.
+ */
+qx.Proto.getColumnCount = function() {
+ throw new Error("getColumnCount is abstract");
+}
+
+
+/**
+ * Returns the ID of column. The ID may be used to identify columns
+ * independent from their index in the model. E.g. for being aware of added
+ * columns when saving the width of a column.
+ *
+ * @param columnIndex {int} the index of the column.
+ * @return {string} the ID of the column.
+ */
+qx.Proto.getColumnId = function(columnIndex) {
+ throw new Error("getColumnId is abstract");
+}
+
+
+/**
+ * Returns the index of a column.
+ *
+ * @param columnId {string} the ID of the column.
+ * @return {int} the index of the column.
+ */
+qx.Proto.getColumnIndexById = function(columnId) {
+ throw new Error("getColumnIndexById is abstract");
+}
+
+
+/**
+ * Returns the name of a column. This name will be shown to the user in the
+ * table header.
+ *
+ * @param columnIndex {int} the index of the column.
+ * @return {string} the name of the column.
+ */
+qx.Proto.getColumnName = function(columnIndex) {
+ throw new Error("getColumnName is abstract");
+}
+
+
+/**
+ * Returns whether a column is editable.
+ *
+ * @param columnIndex {int} the column to check.
+ * @return {boolean} whether the column is editable.
+ */
+qx.Proto.isColumnEditable = function(columnIndex) {
+ return false;
+}
+
+
+/**
+ * Returns whether a column is sortable.
+ *
+ * @param columnIndex {int} the column to check.
+ * @return {boolean} whether the column is sortable.
+ */
+qx.Proto.isColumnSortable = function(columnIndex) {
+ return false;
+}
+
+
+/**
+ * Sorts the model by a column.
+ *
+ * @param columnIndex {int} the column to sort by.
+ * @param ascending {boolean} whether to sort ascending.
+ */
+qx.Proto.sortByColumn = function(columnIndex, ascending) {
+}
+
+
+/**
+ * Returns the column index the model is sorted by. If the model is not sorted
+ * -1 is returned.
+ *
+ * @return {int} the column index the model is sorted by.
+ */
+qx.Proto.getSortColumnIndex = function() {
+ return -1;
+}
+
+
+/**
+ * Returns whether the model is sorted ascending.
+ *
+ * @return {boolean} whether the model is sorted ascending.
+ */
+qx.Proto.isSortAscending = function() {
+ return true;
+}
+
+
+/**
+ * Prefetches some rows. This is a hint to the model that the specified rows
+ * will be read soon.
+ *
+ * @param firstRowIndex {int} the index of first row.
+ * @param lastRowIndex {int} the index of last row.
+ */
+qx.Proto.prefetchRows = function(firstRowIndex, lastRowIndex) {
+}
+
+
+/**
+ * Returns a cell value by column index.
+ *
+ * @param columnIndex {int} the index of the column.
+ * @param rowIndex {int} the index of the row.
+ * @return {var} The value of the cell.
+ * @see #getValueById{}
+ */
+qx.Proto.getValue = function(columnIndex, rowIndex) {
+ throw new Error("getValue is abstract");
+}
+
+
+/**
+ * Returns a cell value by column ID.
+ *
+ * Whenever you have the choice, use {@link #getValue()} instead,
+ * because this should be faster.
+ *
+ * @param columnId {string} the ID of the column.
+ * @param rowIndex {int} the index of the row.
+ * @return {var} the value of the cell.
+ */
+qx.Proto.getValueById = function(columnId, rowIndex) {
+ return this.getValue(this.getColumnIndexById(columnId), rowIndex);
+}
+
+
+/**
+ * Sets a cell value by column index.
+ *
+ * @param columnIndex {int} The index of the column.
+ * @param rowIndex {int} the index of the row.
+ * @param value {var} The new value.
+ * @see #setValueById{}
+ */
+qx.Proto.setValue = function(columnIndex, rowIndex, value) {
+ throw new Error("setValue is abstract");
+}
+
+
+/**
+ * Sets a cell value by column ID.
+ *
+ * Whenever you have the choice, use {@link #setValue()} instead,
+ * because this should be faster.
+ *
+ * @param columnId {string} The ID of the column.
+ * @param rowIndex {int} The index of the row.
+ * @param value {var} The new value.
+ */
+qx.Proto.setValueById = function(columnId, rowIndex, value) {
+ return this.setValue(this.getColumnIndexById(columnId), rowIndex, value);
+}
+
+
+/** {string} The type of the event fired when the data changed. */
+qx.Class.EVENT_TYPE_DATA_CHANGED = "dataChanged";
+
+/** {string} The type of the event fired when the meta data changed. */
+qx.Class.EVENT_TYPE_META_DATA_CHANGED = "metaDataChanged";
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePane.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePane.js
new file mode 100644
index 0000000000..41db2ab274
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePane.js
@@ -0,0 +1,486 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * The table pane that shows a certain section from a table. This class handles
+ * the display of the data part of a table and is therefore the base for virtual
+ * scrolling.
+ *
+ * @param paneScroller {TablePaneScroller} the TablePaneScroller the header belongs to.
+ */
+qx.OO.defineClass("qx.ui.table.TablePane", qx.ui.basic.Terminator,
+function(paneScroller) {
+ qx.ui.basic.Terminator.call(this);
+
+ this._paneScroller = paneScroller;
+
+ this.debug("USE_ARRAY_JOIN:" + qx.ui.table.TablePane.USE_ARRAY_JOIN + ", USE_TABLE:" + qx.ui.table.TablePane.USE_TABLE);
+
+ this._lastColCount = 0;
+ this._lastRowCount = 0;
+});
+
+/** The index of the first row to show. */
+qx.OO.addProperty({ name:"firstVisibleRow", type:"number", defaultValue:0 });
+
+/** The number of rows to show. */
+qx.OO.addProperty({ name:"visibleRowCount", type:"number", defaultValue:0 });
+
+
+// property modifier
+qx.Proto._modifyFirstVisibleRow = function(propValue, propOldValue, propData) {
+ this._updateContent();
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyVisibleRowCount = function(propValue, propOldValue, propData) {
+ this._updateContent();
+ return true;
+}
+
+
+// overridden
+qx.Proto._afterAppear = function() {
+ qx.ui.basic.Terminator.prototype._afterAppear.call(this);
+
+ if (this._updateWantedWhileInvisible) {
+ // We are visible now and an update was wanted while we were invisible
+ // -> Do the update now
+ this._updateContent();
+ this._updateWantedWhileInvisible = false;
+ }
+};
+
+
+/**
+ * Returns the TablePaneScroller this pane belongs to.
+ *
+ * @return {TablePaneScroller} the TablePaneScroller.
+ */
+qx.Proto.getPaneScroller = function() {
+ return this._paneScroller;
+};
+
+
+/**
+ * Returns the table this pane belongs to.
+ *
+ * @return {Table} the table.
+ */
+qx.Proto.getTable = function() {
+ return this._paneScroller.getTable();
+};
+
+
+/**
+ * Sets the currently focused cell.
+ *
+ * @param col {int} the model index of the focused cell's column.
+ * @param row {int} the model index of the focused cell's row.
+ * @param massUpdate {boolean ? false} Whether other updates are planned as well.
+ * If true, no repaint will be done.
+ */
+qx.Proto.setFocusedCell = function(col, row, massUpdate) {
+ if (col != this._focusedCol || row != this._focusedRow) {
+ var oldCol = this._focusedCol;
+ var oldRow = this._focusedRow;
+ this._focusedCol = col;
+ this._focusedRow = row;
+
+ // Update the focused row background
+ if (row != oldRow && !massUpdate) {
+ // NOTE: Only the old and the new row need update
+ this._updateContent(false, oldRow, true);
+ this._updateContent(false, row, true);
+ }
+ }
+}
+
+
+/**
+ * Event handler. Called when the selection has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onSelectionChanged = function(evt) {
+ this._updateContent(false, null, true);
+}
+
+
+/**
+ * Event handler. Called when the table gets or looses the focus.
+ */
+qx.Proto._onFocusChanged = function(evt) {
+ this._updateContent(false, null, true);
+};
+
+
+/**
+ * Event handler. Called when the width of a column has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColWidthChanged = function(evt) {
+ this._updateContent(true);
+}
+
+
+/**
+ * Event handler. Called the column order has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColOrderChanged = function(evt) {
+ this._updateContent(true);
+}
+
+
+/**
+ * Event handler. Called when the pane model has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onPaneModelChanged = function(evt) {
+ this._updateContent(true);
+}
+
+
+/**
+ * Event handler. Called when the table model data has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onTableModelDataChanged = function(evt) {
+ var data = evt.getData ? evt.getData() : null;
+
+ var firstRow = this.getFirstVisibleRow();
+ var rowCount = this.getVisibleRowCount();
+ if (data == null || data.lastRow == -1
+ || data.lastRow >= firstRow && data.firstRow < firstRow + rowCount)
+ {
+ // The change intersects this pane
+ this._updateContent();
+ }
+}
+
+
+/**
+ * Event handler. Called when the table model meta data has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onTableModelMetaDataChanged = function(evt) {
+ this._updateContent();
+}
+
+
+/**
+ * Updates the content of the pane.
+ *
+ * @param completeUpdate {boolean ? false} if true a complete update is performed.
+ * On a complete update all cell widgets are recreated.
+ * @param onlyRow {int ? null} if set only the specified row will be updated.
+ * @param onlySelectionOrFocusChanged {boolean ? false} if true, cell values won't
+ * be updated. Only the row background will.
+ */
+qx.Proto._updateContent = function(completeUpdate, onlyRow,
+ onlySelectionOrFocusChanged)
+{
+ if (! this.isSeeable()) {
+ this._updateWantedWhileInvisible = true;
+ return;
+ }
+
+ if (qx.ui.table.TablePane.USE_ARRAY_JOIN) {
+ this._updateContent_array_join(completeUpdate, onlyRow, onlySelectionOrFocusChanged);
+ } else {
+ this._updateContent_orig(completeUpdate, onlyRow, onlySelectionOrFocusChanged);
+ }
+}
+
+
+qx.Proto._updateContent_array_join = function(completeUpdate, onlyRow,
+ onlySelectionOrFocusChanged)
+{
+ var TablePane = qx.ui.table.TablePane;
+
+ var table = this.getTable();
+
+ var selectionModel = table.getSelectionModel();
+ var tableModel = table.getTableModel();
+ var columnModel = table.getTableColumnModel();
+ var paneModel = this.getPaneScroller().getTablePaneModel();
+ var rowRenderer = table.getDataRowRenderer();
+
+ var colCount = paneModel.getColumnCount();
+ var rowHeight = table.getRowHeight();
+
+ var firstRow = this.getFirstVisibleRow();
+ var rowCount = this.getVisibleRowCount();
+ var modelRowCount = tableModel.getRowCount();
+ if (firstRow + rowCount > modelRowCount) {
+ rowCount = Math.max(0, modelRowCount - firstRow);
+ }
+
+ var cellInfo = { table:table };
+ cellInfo.styleHeight = rowHeight;
+
+ var htmlArr = [];
+ var rowWidth = paneModel.getTotalWidth();
+
+ if (TablePane.USE_TABLE) {
+ htmlArr.push('
');
+
+ for (var x = 0; x < colCount; x++) {
+ var col = paneModel.getColumnAtX(x);
+
+ htmlArr.push();
+ htmlArr.push(columnModel.getColumnWidth(col));
+ htmlArr.push('"/>');
+ }
+
+ htmlArr.push(' ');
+ }
+
+ tableModel.prefetchRows(firstRow, firstRow + rowCount - 1);
+ for (var y = 0; y < rowCount; y++) {
+ var row = firstRow + y;
+
+ cellInfo.row = row;
+ cellInfo.selected = selectionModel.isSelectedIndex(row);
+ cellInfo.focusedRow = (this._focusedRow == row);
+ cellInfo.rowData = tableModel.getRowData(row);
+
+ // Update this row
+ if (TablePane.USE_TABLE) {
+ htmlArr.push('');
+
+ var left = 0;
+ for (var x = 0; x < colCount; x++) {
+ var col = paneModel.getColumnAtX(x);
+ cellInfo.xPos = x;
+ cellInfo.col = col;
+ cellInfo.editable = tableModel.isColumnEditable(col);
+ cellInfo.focusedCol = (this._focusedCol == col);
+ cellInfo.value = tableModel.getValue(col, row);
+ var cellWidth = columnModel.getColumnWidth(col);
+
+ cellInfo.styleLeft = left;
+ cellInfo.styleWidth = cellWidth;
+
+ var cellRenderer = columnModel.getDataCellRenderer(col);
+ cellRenderer.createDataCellHtml_array_join(cellInfo, htmlArr);
+
+ left += cellWidth;
+ }
+
+ if (TablePane.USE_TABLE) {
+ htmlArr.push(' ');
+ } else {
+ htmlArr.push('');
+ }
+ }
+
+ if (TablePane.USE_TABLE) {
+ htmlArr.push('
');
+ }
+
+ var elem = this.getElement();
+ // this.debug(">>>" + htmlArr.join("") + "<<<")
+ elem.innerHTML = htmlArr.join("");
+
+ this.setHeight(rowCount * rowHeight);
+
+ this._lastColCount = colCount;
+ this._lastRowCount = rowCount;
+}
+
+
+qx.Proto._updateContent_orig = function(completeUpdate, onlyRow,
+ onlySelectionOrFocusChanged)
+{
+ var TablePane = qx.ui.table.TablePane;
+
+ var table = this.getTable();
+
+ var alwaysUpdateCells = table.getAlwaysUpdateCells();
+
+ var selectionModel = table.getSelectionModel();
+ var tableModel = table.getTableModel();
+ var columnModel = table.getTableColumnModel();
+ var paneModel = this.getPaneScroller().getTablePaneModel();
+ var rowRenderer = table.getDataRowRenderer();
+
+ var colCount = paneModel.getColumnCount();
+ var rowHeight = table.getRowHeight();
+
+ var firstRow = this.getFirstVisibleRow();
+ var rowCount = this.getVisibleRowCount();
+ var modelRowCount = tableModel.getRowCount();
+ if (firstRow + rowCount > modelRowCount) {
+ rowCount = Math.max(0, modelRowCount - firstRow);
+ }
+
+ // Remove the rows that are not needed any more
+ if (completeUpdate || this._lastRowCount > rowCount) {
+ var firstRowToRemove = completeUpdate ? 0 : rowCount;
+ this._cleanUpRows(firstRowToRemove);
+ }
+
+ if (TablePane.USE_TABLE) {
+ throw new Error("Combination of USE_TABLE==true and USE_ARRAY_JOIN==false is not yet implemented");
+ }
+
+ var elem = this.getElement();
+ var childNodes = elem.childNodes;
+ var cellInfo = { table:table };
+ tableModel.prefetchRows(firstRow, firstRow + rowCount - 1);
+ for (var y = 0; y < rowCount; y++) {
+ var row = firstRow + y;
+ if ((onlyRow != null) && (row != onlyRow)) {
+ continue;
+ }
+
+ cellInfo.row = row;
+ cellInfo.selected = selectionModel.isSelectedIndex(row);
+ cellInfo.focusedRow = (this._focusedRow == row);
+ cellInfo.rowData = tableModel.getRowData(row);
+
+ // Update this row
+ var rowElem;
+ var recyleRowElem;
+ if (y < childNodes.length) {
+ rowElem = childNodes[y];
+ recyleRowElem = true
+ } else {
+ var rowElem = document.createElement("div");
+
+ //rowElem.style.position = "relative";
+ rowElem.style.position = "absolute";
+ rowElem.style.left = "0px";
+ rowElem.style.top = (y * rowHeight) + "px";
+
+ rowElem.style.height = rowHeight + "px";
+ rowElem.style.fontFamily = TablePane.CONTENT_ROW_FONT_FAMILY;
+ rowElem.style.fontSize = TablePane.CONTENT_ROW_FONT_SIZE;
+ elem.appendChild(rowElem);
+ recyleRowElem = false;
+ }
+
+ rowRenderer.updateDataRowElement(cellInfo, rowElem);
+
+ if (alwaysUpdateCells || !recyleRowElem || !onlySelectionOrFocusChanged) {
+ var html = "";
+ var left = 0;
+ for (var x = 0; x < colCount; x++) {
+ var col = paneModel.getColumnAtX(x);
+ cellInfo.xPos = x;
+ cellInfo.col = col;
+ cellInfo.editable = tableModel.isColumnEditable(col);
+ cellInfo.focusedCol = (this._focusedCol == col);
+ cellInfo.value = tableModel.getValue(col, row);
+ var width = columnModel.getColumnWidth(col);
+ cellInfo.style = 'position:absolute;left:' + left
+ + 'px;top:0px;width:' + width
+ + 'px; height:' + rowHeight + "px";
+
+ var cellRenderer = columnModel.getDataCellRenderer(col);
+ if (recyleRowElem) {
+ var cellElem = rowElem.childNodes[x];
+ cellRenderer.updateDataCellElement(cellInfo, cellElem);
+ } else {
+ html += cellRenderer.createDataCellHtml(cellInfo);
+ }
+
+ left += width;
+ }
+ if (! recyleRowElem) {
+ rowElem.style.width = left + "px";
+ rowElem.innerHTML = html;
+ }
+ }
+ }
+
+ this.setHeight(rowCount * rowHeight);
+
+ this._lastColCount = colCount;
+ this._lastRowCount = rowCount;
+}
+
+
+/**
+ * Cleans up the row widgets.
+ *
+ * @param firstRowToRemove {int} the visible index of the first row to clean up.
+ * All following rows will be cleaned up, too.
+ */
+qx.Proto._cleanUpRows = function(firstRowToRemove) {
+ var elem = this.getElement();
+ if (elem) {
+ var childNodes = this.getElement().childNodes;
+ var paneModel = this.getPaneScroller().getTablePaneModel();
+ var colCount = paneModel.getColumnCount();
+ for (var y = childNodes.length - 1; y >= firstRowToRemove; y--) {
+ elem.removeChild(childNodes[y]);
+ }
+ }
+}
+
+
+// overridden
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ this._cleanUpRows(0);
+
+ return qx.ui.basic.Terminator.prototype.dispose.call(this);
+}
+
+
+qx.Class.USE_ARRAY_JOIN = false;
+qx.Class.USE_TABLE = false;
+
+
+qx.Class.CONTENT_ROW_FONT_FAMILY = '"Segoe UI", Corbel, Calibri, Tahoma, "Lucida Sans Unicode", sans-serif';
+qx.Class.CONTENT_ROW_FONT_SIZE = "11px";
+
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneHeader.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneHeader.js
new file mode 100644
index 0000000000..657950293f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneHeader.js
@@ -0,0 +1,276 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * Shows the header of a table.
+ *
+ * @param paneScroller {TablePaneScroller} the TablePaneScroller the header belongs to.
+ */
+qx.OO.defineClass("qx.ui.table.TablePaneHeader", qx.ui.layout.HorizontalBoxLayout,
+function(paneScroller) {
+ qx.ui.layout.HorizontalBoxLayout.call(this);
+
+ this._paneScroller = paneScroller;
+});
+
+
+/**
+ * Returns the TablePaneScroller this header belongs to.
+ *
+ * @return {TablePaneScroller} the TablePaneScroller.
+ */
+qx.Proto.getPaneScroller = function() {
+ return this._paneScroller;
+};
+
+
+/**
+ * Returns the table this header belongs to.
+ *
+ * @return {Table} the table.
+ */
+qx.Proto.getTable = function() {
+ return this._paneScroller.getTable();
+};
+
+
+/**
+ * Event handler. Called when the width of a column has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColWidthChanged = function(evt) {
+ var data = evt.getData();
+ this.setColumnWidth(data.col, data.newWidth);
+}
+
+
+/**
+ * Event handler. Called the column order has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColOrderChanged = function(evt) {
+ this._updateContent(true);
+}
+
+
+/**
+ * Event handler. Called when the pane model has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onPaneModelChanged = function(evt) {
+ this._updateContent(true);
+}
+
+
+/**
+ * Event handler. Called when the table model meta data has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onTableModelMetaDataChanged = function(evt) {
+ this._updateContent();
+}
+
+
+/**
+ * Sets the column width. This overrides the width from the column model.
+ *
+ * @param col {int} the column to change the width for.
+ * @param width {int} the new width.
+ */
+qx.Proto.setColumnWidth = function(col, width) {
+ var x = this.getPaneScroller().getTablePaneModel().getX(col);
+ var children = this.getChildren();
+ if (children[x] != null) {
+ children[x].setWidth(width);
+ }
+}
+
+
+/**
+ * Sets the column the mouse is currently over.
+ *
+ * @param col {int} the model index of the column the mouse is currently over or
+ * null if the mouse is over no column.
+ */
+qx.Proto.setMouseOverColumn = function(col) {
+ if (col != this._lastMouseOverColumn) {
+ var paneModel = this.getPaneScroller().getTablePaneModel();
+ var children = this.getChildren();
+
+ if (this._lastMouseOverColumn != null) {
+ var widget = children[paneModel.getX(this._lastMouseOverColumn)];
+ if (widget != null) {
+ widget.removeState("mouseover");
+ }
+ }
+ if (col != null) {
+ children[paneModel.getX(col)].addState("mouseover");
+ }
+
+ this._lastMouseOverColumn = col;
+ }
+}
+
+
+/**
+ * Shows the feedback shown while a column is moved by the user.
+ *
+ * @param col {int} the model index of the column to show the move feedback for.
+ * @param x {int} the x position the left side of the feeback should have
+ * (in pixels, relative to the left side of the header).
+ */
+qx.Proto.showColumnMoveFeedback = function(col, x) {
+ var elem = this.getElement();
+ if (this._moveFeedback == null) {
+ var xPos = this.getPaneScroller().getTablePaneModel().getX(col);
+ var cellWidget = this.getChildren()[xPos];
+
+ // Create the feedback
+ // Workaround: Since a cloned widget throws an exception when it is
+ // added to another component we have to create a new one
+ // using the renderer
+ //this._moveFeedback = cellWidget.clone();
+ var tableModel = this.getTable().getTableModel();
+ var columnModel = this.getTable().getTableColumnModel();
+ var cellInfo = { xPos:xPos, col:col, name:tableModel.getColumnName(col) }
+ var cellRenderer = columnModel.getHeaderCellRenderer(col);
+ this._moveFeedback = cellRenderer.createHeaderCell(cellInfo);
+
+ // Configure the feedback
+ with (this._moveFeedback) {
+ setWidth(cellWidget.getBoxWidth());
+ setHeight(cellWidget.getBoxHeight());
+ setZIndex(1000000);
+ setOpacity(0.8);
+ setTop(qx.dom.Location.getClientBoxTop(elem));
+ }
+ this.getTopLevelWidget().add(this._moveFeedback);
+ }
+
+ this._moveFeedback.setLeft(qx.dom.Location.getClientBoxLeft(elem) + x);
+}
+
+
+/**
+ * Hides the feedback shown while a column is moved by the user.
+ */
+qx.Proto.hideColumnMoveFeedback = function() {
+ if (this._moveFeedback != null) {
+ this.getTopLevelWidget().remove(this._moveFeedback);
+ this._moveFeedback.dispose();
+ this._moveFeedback = null;
+ }
+}
+
+
+/**
+ * Returns whether the column move feedback is currently shown.
+ */
+qx.Proto.isShowingColumnMoveFeedback = function() {
+ return this._moveFeedback != null;
+}
+
+
+/**
+ * Updates the content of the header.
+ *
+ * @param completeUpdate {boolean} if true a complete update is performed. On a
+ * complete update all header widgets are recreated.
+ */
+qx.Proto._updateContent = function(completeUpdate) {
+ var tableModel = this.getTable().getTableModel();
+ var columnModel = this.getTable().getTableColumnModel();
+ var paneModel = this.getPaneScroller().getTablePaneModel();
+
+ var children = this.getChildren();
+ var oldColCount = children.length;
+ var colCount = paneModel.getColumnCount();
+
+ var sortedColum = tableModel.getSortColumnIndex();
+
+ // Remove all widgets on the complete update
+ if (completeUpdate) {
+ this._cleanUpCells();
+ }
+
+ // Update the header
+ var cellInfo = {};
+ cellInfo.sortedAscending = tableModel.isSortAscending();
+ for (var x = 0; x < colCount; x++) {
+ var col = paneModel.getColumnAtX(x);
+
+ var colWidth = columnModel.getColumnWidth(col);
+
+ // TODO: Get real cell renderer
+ var cellRenderer = columnModel.getHeaderCellRenderer(col);
+
+ cellInfo.xPos = x;
+ cellInfo.col = col;
+ cellInfo.name = tableModel.getColumnName(col);
+ cellInfo.editable = tableModel.isColumnEditable(col);
+ cellInfo.sorted = (col == sortedColum);
+
+ // Get the cached widget
+ var cachedWidget = children[x];
+
+ // Create or update the widget
+ if (cachedWidget == null) {
+ // We have no cached widget -> create it
+ cachedWidget = cellRenderer.createHeaderCell(cellInfo);
+ cachedWidget.set({ width:colWidth, height:"100%" });
+
+ this.add(cachedWidget);
+ } else {
+ // This widget already created before -> recycle it
+ cellRenderer.updateHeaderCell(cellInfo, cachedWidget);
+ }
+ }
+}
+
+
+/**
+ * Cleans up all header cells.
+ */
+qx.Proto._cleanUpCells = function() {
+ var children = this.getChildren();
+ for (var x = children.length - 1; x >= 0; x--) {
+ var cellWidget = children[x];
+ //this.debug("disposed:" + cellWidget.getDisposed() + ",has parent: " + (cellWidget.getParent() != null) + ",x:"+x);
+ this.remove(cellWidget);
+ cellWidget.dispose();
+ }
+}
+
+
+// overridden
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ return qx.ui.layout.HorizontalBoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneModel.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneModel.js
new file mode 100644
index 0000000000..d53da59251
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneModel.js
@@ -0,0 +1,179 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * The model of a table pane. This model works as proxy to a
+ * {@link TableColumnModel} and manages the visual order of the columns shown in
+ * a {@link TablePane}.
+ *
+ * @param tableColumnModel {TableColumnModel} The TableColumnModel of which this
+ * model is the proxy.
+ *
+ * @event modelChanged {qx.event.type.Event} Fired when the model changed.
+ */
+qx.OO.defineClass("qx.ui.table.TablePaneModel", qx.core.Target,
+function(tableColumnModel) {
+ qx.core.Target.call(this);
+
+ tableColumnModel.addEventListener("visibilityChangedPre", this._onColVisibilityChanged, this);
+
+ this._tableColumnModel = tableColumnModel;
+});
+
+
+/** The visible x position of the first column this model should contain. */
+qx.OO.addProperty({ name : "firstColumnX", type : "number", defaultValue : 0 });
+
+/**
+ * The maximum number of columns this model should contain. If -1 this model will
+ * contain all remaining columns.
+ */
+qx.OO.addProperty({ name : "maxColumnCount", type : "number", defaultValue : -1 });
+
+
+// property modifier
+qx.Proto._modifyFirstColumnX = function(propValue, propOldValue, propData) {
+ this._columnCount = null;
+ this.createDispatchEvent(qx.ui.table.TablePaneModel.EVENT_TYPE_MODEL_CHANGED);
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyMaxColumnCount = function(propValue, propOldValue, propData) {
+ this._columnCount = null;
+ this.createDispatchEvent(qx.ui.table.TablePaneModel.EVENT_TYPE_MODEL_CHANGED);
+ return true;
+}
+
+
+/**
+ * Event handler. Called when the visibility of a column has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColVisibilityChanged = function(evt) {
+ this._columnCount = null;
+
+ // TODO: Check whether the column is in this model (This is a little bit
+ // tricky, because the column could _have been_ in this model, but is
+ // not in it after the change)
+ this.createDispatchEvent(qx.ui.table.TablePaneModel.EVENT_TYPE_MODEL_CHANGED);
+}
+
+
+/**
+ * Returns the number of columns in this model.
+ *
+ * @return {int} the number of columns in this model.
+ */
+qx.Proto.getColumnCount = function() {
+ if (this._columnCount == null) {
+ var firstX = this.getFirstColumnX();
+ var maxColCount = this.getMaxColumnCount();
+ var totalColCount = this._tableColumnModel.getVisibleColumnCount();
+
+ if (maxColCount == -1 || (firstX + maxColCount) > totalColCount) {
+ this._columnCount = totalColCount - firstX;
+ } else {
+ this._columnCount = maxColCount;
+ }
+ }
+ return this._columnCount;
+}
+
+
+/**
+ * Returns the model index of the column at the position xPos
.
+ *
+ * @param xPos {int} the x postion in the table pane of the column.
+ * @return {int} the model index of the column.
+ */
+qx.Proto.getColumnAtX = function(xPos) {
+ var firstX = this.getFirstColumnX();
+ return this._tableColumnModel.getVisibleColumnAtX(firstX + xPos);
+}
+
+
+/**
+ * Returns the x position of the column col
.
+ *
+ * @param col {int} the model index of the column.
+ * @return {int} the x postion in the table pane of the column.
+ */
+qx.Proto.getX = function(col) {
+ var firstX = this.getFirstColumnX();
+ var maxColCount = this.getMaxColumnCount();
+
+ var x = this._tableColumnModel.getVisibleX(col) - firstX;
+ if (x >= 0 && (maxColCount == -1 || x < maxColCount)) {
+ return x;
+ } else {
+ return -1;
+ }
+}
+
+
+/**
+ * Gets the position of the left side of a column (in pixels, relative to the
+ * left side of the table pane).
+ *
+ * This value corresponds to the sum of the widths of all columns left of the
+ * column.
+ *
+ * @param col {int} the model index of the column.
+ * @return the position of the left side of the column.
+ */
+qx.Proto.getColumnLeft = function(col) {
+ var left = 0;
+ var colCount = this.getColumnCount();
+ for (var x = 0; x < colCount; x++) {
+ var currCol = this.getColumnAtX(x);
+ if (currCol == col) {
+ return left;
+ }
+
+ left += this._tableColumnModel.getColumnWidth(currCol);
+ }
+ return -1;
+}
+
+
+/**
+ * Returns the total width of all columns in the model.
+ *
+ * @return {int} the total width of all columns in the model.
+ */
+qx.Proto.getTotalWidth = function() {
+ var totalWidth = 0;
+ var colCount = this.getColumnCount();
+ for (var x = 0; x < colCount; x++) {
+ var col = this.getColumnAtX(x);
+ totalWidth += this._tableColumnModel.getColumnWidth(col);
+ }
+ return totalWidth;
+}
+
+
+/** {string} The type of the event fired when the model changed. */
+qx.Class.EVENT_TYPE_MODEL_CHANGED = "modelChanged";
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneScroller.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneScroller.js
new file mode 100644
index 0000000000..d6f7773148
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneScroller.js
@@ -0,0 +1,1331 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * Shows a whole meta column. This includes a {@link TablePaneHeader},
+ * a {@link TablePane} and the needed scroll bars. This class handles the
+ * virtual scrolling and does all the mouse event handling.
+ *
+ * @param table {Table} the table the scroller belongs to.
+ */
+qx.OO.defineClass("qx.ui.table.TablePaneScroller", qx.ui.layout.VerticalBoxLayout,
+function(table) {
+ qx.ui.layout.VerticalBoxLayout.call(this);
+
+ this._table = table;
+
+ // init scrollbars
+ this._verScrollBar = new qx.ui.core.ScrollBar(false);
+ this._horScrollBar = new qx.ui.core.ScrollBar(true);
+
+ var scrollBarWidth = this._verScrollBar.getPreferredBoxWidth();
+
+ this._verScrollBar.setWidth("auto");
+ this._horScrollBar.setHeight("auto");
+ this._horScrollBar.setPaddingRight(scrollBarWidth);
+ //this._verScrollBar.setMergeEvents(true);
+
+ this._horScrollBar.addEventListener("changeValue", this._onScrollX, this);
+ this._verScrollBar.addEventListener("changeValue", this._onScrollY, this);
+
+ // init header
+ this._header = new qx.ui.table.TablePaneHeader(this);
+ this._header.set({ width:"auto", height:"auto" });
+
+ this._headerClipper = new qx.ui.layout.CanvasLayout;
+ with (this._headerClipper) {
+ setDimension("1*", "auto");
+ setOverflow("hidden");
+ add(this._header);
+ }
+
+ this._spacer = new qx.ui.basic.Terminator;
+ this._spacer.setWidth(scrollBarWidth);
+
+ this._top = new qx.ui.layout.HorizontalBoxLayout;
+ with (this._top) {
+ setHeight("auto");
+ add(this._headerClipper, this._spacer);
+ }
+
+ // init pane
+ this._tablePane = new qx.ui.table.TablePane(this);
+ this._tablePane.set({ width:"auto", height:"auto" });
+
+ this._focusIndicator = new qx.ui.layout.HorizontalBoxLayout;
+ this._focusIndicator.setAppearance("table-focus-indicator");
+ this._focusIndicator.hide();
+
+ // Workaround: If the _focusIndicator has no content if always gets a too
+ // high hight in IE.
+ var dummyContent = new qx.ui.basic.Terminator;
+ dummyContent.setWidth(0);
+ this._focusIndicator.add(dummyContent);
+
+ this._paneClipper = new qx.ui.layout.CanvasLayout;
+ with (this._paneClipper) {
+ setWidth("1*");
+ setOverflow("hidden");
+ add(this._tablePane, this._focusIndicator);
+ addEventListener("mousewheel", this._onmousewheel, this);
+ }
+
+ // add all child widgets
+ var scrollerBody = new qx.ui.layout.HorizontalBoxLayout;
+ scrollerBody.setHeight("1*");
+ scrollerBody.add(this._paneClipper, this._verScrollBar);
+
+ this.add(this._top, scrollerBody, this._horScrollBar);
+
+ // init event handlers
+ this.addEventListener("mousemove", this._onmousemove, this);
+ this.addEventListener("mousedown", this._onmousedown, this);
+ this.addEventListener("mouseup", this._onmouseup, this);
+ this.addEventListener("click", this._onclick, this);
+ this.addEventListener("dblclick", this._ondblclick, this);
+ this.addEventListener("mouseout", this._onmouseout, this);
+});
+
+/** Whether to show the horizontal scroll bar */
+qx.OO.addProperty({ name:"horizontalScrollBarVisible", type:"boolean", defaultValue:true });
+
+/** Whether to show the vertical scroll bar */
+qx.OO.addProperty({ name:"verticalScrollBarVisible", type:"boolean", defaultValue:true });
+
+/** The table pane model. */
+qx.OO.addProperty({ name:"tablePaneModel", type:"object", instance:"qx.ui.table.TablePaneModel" });
+
+/** The current position of the the horizontal scroll bar. */
+qx.OO.addProperty({ name:"scrollX", type:"number", allowNull:false, defaultValue:0 });
+
+/** The current position of the the vertical scroll bar. */
+qx.OO.addProperty({ name:"scrollY", type:"number", allowNull:false, defaultValue:0 });
+
+/**
+ * Whether column resize should be live. If false, during resize only a line is
+ * shown and the real resize happens when the user releases the mouse button.
+ */
+qx.OO.addProperty({ name:"liveResize", type:"boolean", defaultValue:false });
+
+/**
+ * Whether the focus should moved when the mouse is moved over a cell. If false
+ * the focus is only moved on mouse clicks.
+ */
+qx.OO.addProperty({ name:"focusCellOnMouseMove", type:"boolean", defaultValue:false });
+
+
+// property modifier
+qx.Proto._modifyHorizontalScrollBarVisible = function(propValue, propOldValue, propData) {
+ // Workaround: We can't use setDisplay, because the scroll bar needs its
+ // correct height in order to check its value. When using
+ // setDisplay(false) the height isn't relayouted any more
+ if (propValue) {
+ this._horScrollBar.setHeight("auto");
+ } else {
+ this._horScrollBar.setHeight(0);
+ }
+ this._horScrollBar.setVisibility(propValue);
+
+ // NOTE: We have to flush the queues before updating the content so the new
+ // layout has been applied and _updateContent is able to work with
+ // correct values.
+ qx.ui.core.Widget.flushGlobalQueues();
+ this._updateContent();
+
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyVerticalScrollBarVisible = function(propValue, propOldValue, propData) {
+ // Workaround: See _modifyHorizontalScrollBarVisible
+ if (propValue) {
+ this._verScrollBar.setWidth("auto");
+ } else {
+ this._verScrollBar.setWidth(0);
+ }
+ this._verScrollBar.setVisibility(propValue);
+
+ var scrollBarWidth = propValue ? this._verScrollBar.getPreferredBoxWidth() : 0;
+ this._horScrollBar.setPaddingRight(scrollBarWidth);
+ this._spacer.setWidth(scrollBarWidth);
+
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyTablePaneModel = function(propValue, propOldValue, propData) {
+ if (propOldValue != null) {
+ propOldValue.removeEventListener("modelChanged", this._onPaneModelChanged, this);
+ }
+ propValue.addEventListener("modelChanged", this._onPaneModelChanged, this);
+
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyScrollX = function(propValue, propOldValue, propData) {
+ this._horScrollBar.setValue(propValue);
+ return true;
+}
+
+
+// property modifier
+qx.Proto._modifyScrollY = function(propValue, propOldValue, propData) {
+ this._verScrollBar.setValue(propValue);
+ return true;
+}
+
+
+/**
+ * Returns the table this scroller belongs to.
+ *
+ * @return {Table} the table.
+ */
+qx.Proto.getTable = function() {
+ return this._table;
+};
+
+
+/**
+ * Event handler. Called when the visibility of a column has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColVisibilityChanged = function(evt) {
+ this._updateHorScrollBarMaximum();
+ this._updateFocusIndicator();
+}
+
+
+/**
+ * Event handler. Called when the width of a column has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColWidthChanged = function(evt) {
+ this._header._onColWidthChanged(evt);
+ this._tablePane._onColWidthChanged(evt);
+
+ var data = evt.getData();
+ var paneModel = this.getTablePaneModel();
+ var x = paneModel.getX(data.col);
+ if (x != -1) {
+ // The change was in this scroller
+ this._updateHorScrollBarMaximum();
+ this._updateFocusIndicator();
+ }
+}
+
+
+/**
+ * Event handler. Called when the column order has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onColOrderChanged = function(evt) {
+ this._header._onColOrderChanged(evt);
+ this._tablePane._onColOrderChanged(evt);
+
+ this._updateHorScrollBarMaximum();
+}
+
+
+/**
+ * Event handler. Called when the table model has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onTableModelDataChanged = function(evt) {
+ this._tablePane._onTableModelDataChanged(evt);
+
+ var rowCount = this.getTable().getTableModel().getRowCount();
+ if (rowCount != this._lastRowCount) {
+ this._lastRowCount = rowCount;
+
+ this._updateVerScrollBarMaximum();
+ if (this.getFocusedRow() >= rowCount) {
+ if (rowCount == 0) {
+ this.setFocusedCell(null, null);
+ } else {
+ this.setFocusedCell(this.getFocusedColumn(), rowCount - 1);
+ }
+ }
+ }
+}
+
+
+/**
+ * Event handler. Called when the selection has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onSelectionChanged = function(evt) {
+ this._tablePane._onSelectionChanged(evt);
+};
+
+
+/**
+ * Event handler. Called when the table gets or looses the focus.
+ */
+qx.Proto._onFocusChanged = function(evt) {
+ this._focusIndicator.setState("tableHasFocus", this.getTable().getFocused());
+
+ this._tablePane._onFocusChanged(evt);
+};
+
+
+/**
+ * Event handler. Called when the table model meta data has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onTableModelMetaDataChanged = function(evt) {
+ this._header._onTableModelMetaDataChanged(evt);
+ this._tablePane._onTableModelMetaDataChanged(evt);
+};
+
+
+/**
+ * Event handler. Called when the pane model has changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onPaneModelChanged = function(evt) {
+ this._header._onPaneModelChanged(evt);
+ this._tablePane._onPaneModelChanged(evt);
+};
+
+
+/**
+ * Updates the maximum of the horizontal scroll bar, so it corresponds to the
+ * total width of the columns in the table pane.
+ */
+qx.Proto._updateHorScrollBarMaximum = function() {
+ this._horScrollBar.setMaximum(this.getTablePaneModel().getTotalWidth());
+}
+
+
+/**
+ * Updates the maximum of the vertical scroll bar, so it corresponds to the
+ * number of rows in the table.
+ */
+qx.Proto._updateVerScrollBarMaximum = function() {
+ var rowCount = this.getTable().getTableModel().getRowCount();
+ var rowHeight = this.getTable().getRowHeight();
+
+ if (this.getTable().getKeepFirstVisibleRowComplete()) {
+ this._verScrollBar.setMaximum((rowCount + 1) * rowHeight);
+ } else {
+ this._verScrollBar.setMaximum(rowCount * rowHeight);
+ }
+}
+
+
+/**
+ * Event handler. Called when the table property "keepFirstVisibleRowComplete"
+ * changed.
+ */
+qx.Proto._onKeepFirstVisibleRowCompleteChanged = function() {
+ this._updateVerScrollBarMaximum();
+ this._updateContent();
+};
+
+
+// overridden
+qx.Proto._changeInnerHeight = function(newValue, oldValue) {
+ // The height has changed -> Update content
+ this._postponedUpdateContent();
+
+ return qx.ui.layout.VerticalBoxLayout.prototype._changeInnerHeight.call(this, newValue, oldValue);
+}
+
+
+// overridden
+qx.Proto._afterAppear = function() {
+ qx.ui.layout.VerticalBoxLayout.prototype._afterAppear.call(this);
+
+ var self = this;
+ this.getElement().onselectstart = qx.util.Return.returnFalse;
+
+ this._updateContent();
+ this._header._updateContent();
+ this._updateHorScrollBarMaximum();
+ this._updateVerScrollBarMaximum();
+}
+
+
+/**
+ * Event handler. Called when the horizontal scroll bar moved.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onScrollX = function(evt) {
+ // Workaround: See _updateContent
+ this._header.setLeft(-evt.getData());
+
+ this._paneClipper.setScrollLeft(evt.getData());
+ this.setScrollX(evt.getData());
+}
+
+
+/**
+ * Event handler. Called when the vertical scroll bar moved.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onScrollY = function(evt) {
+ this._postponedUpdateContent();
+ this.setScrollY(evt.getData());
+}
+
+
+/**
+ * Event handler. Called when the user moved the mouse wheel.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onmousewheel = function(evt) {
+ this._verScrollBar.setValue(this._verScrollBar.getValue()
+ - evt.getWheelDelta() * this.getTable().getRowHeight());
+
+ // Update the focus
+ if (this._lastMousePageX && this.getFocusCellOnMouseMove()) {
+ this._focusCellAtPagePos(this._lastMousePageX, this._lastMousePageY);
+ }
+}
+
+
+/**
+ * Event handler. Called when the user moved the mouse.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onmousemove = function(evt) {
+ var tableModel = this.getTable().getTableModel();
+ var columnModel = this.getTable().getTableColumnModel();
+
+ var useResizeCursor = false;
+ var mouseOverColumn = null;
+
+ var pageX = evt.getPageX();
+ var pageY = evt.getPageY();
+
+ // Workaround: In onmousewheel the event has wrong coordinates for pageX
+ // and pageY. So we remember the last move event.
+ this._lastMousePageX = pageX;
+ this._lastMousePageY = pageY;
+
+ if (this._resizeColumn != null) {
+ // We are currently resizing -> Update the position
+ var minColumnWidth = qx.ui.table.TablePaneScroller.MIN_COLUMN_WIDTH;
+ var newWidth = Math.max(minColumnWidth, this._lastResizeWidth + pageX - this._lastResizeMousePageX);
+
+ if (this.getLiveResize()) {
+ columnModel.setColumnWidth(this._resizeColumn, newWidth);
+ } else {
+ this._header.setColumnWidth(this._resizeColumn, newWidth);
+
+ var paneModel = this.getTablePaneModel();
+ this._showResizeLine(paneModel.getColumnLeft(this._resizeColumn) + newWidth);
+ }
+
+ useResizeCursor = true;
+ this._lastResizeMousePageX += newWidth - this._lastResizeWidth;
+ this._lastResizeWidth = newWidth;
+ } else if (this._moveColumn != null) {
+ // We are moving a column
+
+ // Check whether we moved outside the click tolerance so we can start
+ // showing the column move feedback
+ // (showing the column move feedback prevents the onclick event)
+ var clickTolerance = qx.ui.table.TablePaneScroller.CLICK_TOLERANCE;
+ if (this._header.isShowingColumnMoveFeedback()
+ || pageX > this._lastMoveMousePageX + clickTolerance
+ || pageX < this._lastMoveMousePageX - clickTolerance)
+ {
+ this._lastMoveColPos += pageX - this._lastMoveMousePageX;
+
+ this._header.showColumnMoveFeedback(this._moveColumn, this._lastMoveColPos);
+
+ // Get the responsible scroller
+ var targetScroller = this._table.getTablePaneScrollerAtPageX(pageX);
+ if (this._lastMoveTargetScroller && this._lastMoveTargetScroller != targetScroller) {
+ this._lastMoveTargetScroller.hideColumnMoveFeedback();
+ }
+ if (targetScroller != null) {
+ this._lastMoveTargetX = targetScroller.showColumnMoveFeedback(pageX);
+ } else {
+ this._lastMoveTargetX = null;
+ }
+
+ this._lastMoveTargetScroller = targetScroller;
+ this._lastMoveMousePageX = pageX;
+ }
+ } else {
+ // This is a normal mouse move
+ var row = this._getRowForPagePos(pageX, pageY);
+ if (row == -1) {
+ // The mouse is over the header
+ var resizeCol = this._getResizeColumnForPageX(pageX);
+ if (resizeCol != -1) {
+ // The mouse is over a resize region -> Show the right cursor
+ useResizeCursor = true;
+ } else {
+ var col = this._getColumnForPageX(pageX);
+ if (col != null && tableModel.isColumnSortable(col)) {
+ mouseOverColumn = col;
+ }
+ }
+ } else if (row != null) {
+ // The mouse is over the data -> update the focus
+ if (this.getFocusCellOnMouseMove()) {
+ this._focusCellAtPagePos(pageX, pageY);
+ }
+ }
+ }
+
+ // Workaround: Setting the cursor to the right widget doesn't work
+ //this._header.setCursor(useResizeCursor ? "e-resize" : null);
+ this.getTopLevelWidget().setGlobalCursor(useResizeCursor ? qx.ui.table.TablePaneScroller.CURSOR_RESIZE_HORIZONTAL : null);
+
+ this._header.setMouseOverColumn(mouseOverColumn);
+}
+
+
+/**
+ * Event handler. Called when the user pressed a mouse button.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onmousedown = function(evt) {
+ var tableModel = this.getTable().getTableModel();
+ var columnModel = this.getTable().getTableColumnModel();
+
+ var pageX = evt.getPageX();
+ var pageY = evt.getPageY();
+ var row = this._getRowForPagePos(pageX, pageY);
+ if (row == -1) {
+ // mouse is in header
+ var resizeCol = this._getResizeColumnForPageX(pageX);
+ if (resizeCol != -1) {
+ // The mouse is over a resize region -> Start resizing
+ this._resizeColumn = resizeCol;
+ this._lastResizeMousePageX = pageX;
+ this._lastResizeWidth = columnModel.getColumnWidth(this._resizeColumn);
+ this.setCapture(true);
+ } else {
+ // The mouse is not in a resize region
+ var col = this._getColumnForPageX(pageX);
+ if (col != null) {
+ // Prepare column moving
+ this._moveColumn = col;
+ this._lastMoveMousePageX = pageX;
+ this._lastMoveColPos = this.getTablePaneModel().getColumnLeft(col);
+ this.setCapture(true);
+ }
+ }
+ } else if (row != null) {
+ // The mouse is over the data -> update the focus
+ if (! this.getFocusCellOnMouseMove()) {
+ this._focusCellAtPagePos(pageX, pageY);
+ }
+
+ this.getTable()._getSelectionManager().handleMouseDown(row, evt);
+ }
+}
+
+
+/**
+ * Event handler. Called when the user released a mouse button.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onmouseup = function(evt) {
+ var columnModel = this.getTable().getTableColumnModel();
+ var paneModel = this.getTablePaneModel();
+
+ if (this._resizeColumn != null) {
+ // We are currently resizing -> Finish resizing
+ if (! this.getLiveResize()) {
+ this._hideResizeLine();
+ columnModel.setColumnWidth(this._resizeColumn, this._lastResizeWidth);
+ }
+
+ this._resizeColumn = null;
+ this.setCapture(false);
+
+ this.getTopLevelWidget().setGlobalCursor(null);
+ } else if (this._moveColumn != null) {
+ // We are moving a column -> Drop the column
+ this._header.hideColumnMoveFeedback();
+ if (this._lastMoveTargetScroller) {
+ this._lastMoveTargetScroller.hideColumnMoveFeedback();
+ }
+
+ if (this._lastMoveTargetX != null) {
+ var fromVisXPos = paneModel.getFirstColumnX() + paneModel.getX(this._moveColumn);
+ var toVisXPos = this._lastMoveTargetX;
+ if (toVisXPos != fromVisXPos && toVisXPos != fromVisXPos + 1) {
+ // The column was really moved to another position
+ // (and not moved before or after itself, which is a noop)
+
+ // Translate visible positions to overall positions
+ var fromCol = columnModel.getVisibleColumnAtX(fromVisXPos);
+ var toCol = columnModel.getVisibleColumnAtX(toVisXPos);
+ var fromOverXPos = columnModel.getOverallX(fromCol);
+ var toOverXPos = (toCol != null) ? columnModel.getOverallX(toCol) : columnModel.getOverallColumnCount();
+
+ if (toOverXPos > fromOverXPos) {
+ // Don't count the column itself
+ toOverXPos--;
+ }
+
+ // Move the column
+ columnModel.moveColumn(fromOverXPos, toOverXPos);
+ }
+ }
+
+ this._moveColumn = null;
+ this._lastMoveTargetX = null;
+ this.setCapture(false);
+ } else {
+ // This is a normal mouse up
+ var row = this._getRowForPagePos(evt.getPageX(), evt.getPageY());
+ if (row != -1 && row != null) {
+ this.getTable()._getSelectionManager().handleMouseUp(row, evt);
+ }
+ }
+}
+
+
+/**
+ * Event handler. Called when the user clicked a mouse button.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onclick = function(evt) {
+ var tableModel = this.getTable().getTableModel();
+
+ var pageX = evt.getPageX();
+ var pageY = evt.getPageY();
+ var row = this._getRowForPagePos(pageX, pageY);
+ if (row == -1) {
+ // mouse is in header
+ var resizeCol = this._getResizeColumnForPageX(pageX);
+ if (resizeCol == -1) {
+ // mouse is not in a resize region
+ var col = this._getColumnForPageX(pageX);
+ if (col != null && tableModel.isColumnSortable(col)) {
+ // Sort that column
+ var sortCol = tableModel.getSortColumnIndex();
+ var ascending = (col != sortCol) ? true : !tableModel.isSortAscending();
+
+ tableModel.sortByColumn(col, ascending);
+ this.getTable().getSelectionModel().clearSelection();
+ }
+ }
+ } else if (row != null) {
+ this.getTable()._getSelectionManager().handleClick(row, evt);
+ }
+}
+
+
+/**
+ * Event handler. Called when the user double clicked a mouse button.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._ondblclick = function(evt) {
+ if (! this.isEditing()) {
+ this._focusCellAtPagePos(evt.getPageX(), evt.getPageY());
+ this.startEditing();
+ }
+}
+
+
+/**
+ * Event handler. Called when the mouse moved out.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onmouseout = function(evt) {
+ /*
+ // Workaround: See _onmousemove
+ this._lastMousePageX = null;
+ this._lastMousePageY = null;
+ */
+
+ // Reset the resize cursor when the mouse leaves the header
+ // If currently a column is resized then do nothing
+ // (the cursor will be reset on mouseup)
+ if (this._resizeColumn == null) {
+ this.getTopLevelWidget().setGlobalCursor(null);
+ }
+
+ this._header.setMouseOverColumn(null);
+}
+
+
+/**
+ * Shows the resize line.
+ *
+ * @param x {int} the position where to show the line (in pixels, relative to
+ * the left side of the pane).
+ */
+qx.Proto._showResizeLine = function(x) {
+ var resizeLine = this._resizeLine;
+ if (resizeLine == null) {
+ resizeLine = new qx.ui.basic.Terminator;
+ resizeLine.setBackgroundColor("#D6D5D9");
+ resizeLine.setWidth(3);
+ this._paneClipper.add(resizeLine);
+ qx.ui.core.Widget.flushGlobalQueues();
+
+ this._resizeLine = resizeLine;
+ }
+
+ resizeLine._applyRuntimeLeft(x - 2); // -1 for the width
+ resizeLine._applyRuntimeHeight(this._paneClipper.getBoxHeight() + this._paneClipper.getScrollTop());
+
+ this._resizeLine.removeStyleProperty("visibility");
+}
+
+
+/**
+ * Hides the resize line.
+ */
+qx.Proto._hideResizeLine = function() {
+ this._resizeLine.setStyleProperty("visibility", "hidden");
+}
+
+
+/**
+ * Shows the feedback shown while a column is moved by the user.
+ *
+ * @param pageX {int} the x position of the mouse in the page (in pixels).
+ * @return {int} the visible x position of the column in the whole table.
+ */
+qx.Proto.showColumnMoveFeedback = function(pageX) {
+ var paneModel = this.getTablePaneModel();
+ var columnModel = this.getTable().getTableColumnModel();
+ var paneLeftX = qx.dom.Location.getClientBoxLeft(this._tablePane.getElement());
+ var colCount = paneModel.getColumnCount();
+
+ var targetXPos = 0;
+ var targetX = 0;
+ var currX = paneLeftX;
+ for (var xPos = 0; xPos < colCount; xPos++) {
+ var col = paneModel.getColumnAtX(xPos);
+ var colWidth = columnModel.getColumnWidth(col);
+
+ if (pageX < currX + colWidth / 2) {
+ break;
+ }
+
+ currX += colWidth;
+ targetXPos = xPos + 1;
+ targetX = currX - paneLeftX;
+ }
+
+ // Ensure targetX is visible
+ var clipperLeftX = qx.dom.Location.getClientBoxLeft(this._paneClipper.getElement());
+ var clipperWidth = this._paneClipper.getBoxWidth();
+ var scrollX = clipperLeftX - paneLeftX;
+ // NOTE: +2/-1 because of feedback width
+ targetX = qx.lang.Number.limit(targetX, scrollX + 2, scrollX + clipperWidth - 1);
+
+ this._showResizeLine(targetX);
+
+ // Return the overall target x position
+ return paneModel.getFirstColumnX() + targetXPos;
+}
+
+
+/**
+ * Hides the feedback shown while a column is moved by the user.
+ */
+qx.Proto.hideColumnMoveFeedback = function() {
+ this._hideResizeLine();
+}
+
+
+/**
+ * Sets the focus to the cell that's located at the page position
+ * pageX
/pageY
. If there is no cell at that position,
+ * nothing happens.
+ *
+ * @param pageX {int} the x position in the page (in pixels).
+ * @param pageY {int} the y position in the page (in pixels).
+ */
+qx.Proto._focusCellAtPagePos = function(pageX, pageY) {
+ var row = this._getRowForPagePos(pageX, pageY);
+ if (row != -1 && row != null) {
+ // The mouse is over the data -> update the focus
+ var col = this._getColumnForPageX(pageX);
+ if (col != null) {
+ this._table.setFocusedCell(col, row);
+ }
+ }
+}
+
+
+/**
+ * Sets the currently focused cell.
+ *
+ * @param col {int} the model index of the focused cell's column.
+ * @param row {int} the model index of the focused cell's row.
+ */
+qx.Proto.setFocusedCell = function(col, row) {
+ if (!this.isEditing()) {
+ this._tablePane.setFocusedCell(col, row, this._updateContentPlanned);
+
+ this._focusedCol = col;
+ this._focusedRow = row;
+
+ // Move the focus indicator
+ if (! this._updateContentPlanned) {
+ this._updateFocusIndicator();
+ }
+ }
+}
+
+
+/**
+ * Returns the column of currently focused cell.
+ *
+ * @return {int} the model index of the focused cell's column.
+ */
+qx.Proto.getFocusedColumn = function() {
+ return this._focusedCol;
+};
+
+
+/**
+ * Returns the row of currently focused cell.
+ *
+ * @return {int} the model index of the focused cell's column.
+ */
+qx.Proto.getFocusedRow = function() {
+ return this._focusedRow;
+};
+
+
+/**
+ * Scrolls a cell visible.
+ *
+ * @param col {int} the model index of the column the cell belongs to.
+ * @param row {int} the model index of the row the cell belongs to.
+ */
+qx.Proto.scrollCellVisible = function(col, row) {
+ var paneModel = this.getTablePaneModel();
+ var xPos = paneModel.getX(col);
+
+ if (xPos != -1) {
+ var columnModel = this.getTable().getTableColumnModel();
+
+ var colLeft = paneModel.getColumnLeft(col);
+ var colWidth = columnModel.getColumnWidth(col);
+ var rowHeight = this.getTable().getRowHeight();
+ var rowTop = row * rowHeight;
+
+ var scrollX = this.getScrollX();
+ var scrollY = this.getScrollY();
+ var viewWidth = this._paneClipper.getBoxWidth();
+ var viewHeight = this._paneClipper.getBoxHeight();
+
+ // NOTE: We don't use qx.lang.Number.limit, because min should win if max < min
+ var minScrollX = Math.min(colLeft, colLeft + colWidth - viewWidth);
+ var maxScrollX = colLeft;
+ this.setScrollX(Math.max(minScrollX, Math.min(maxScrollX, scrollX)));
+
+ var minScrollY = rowTop + rowHeight - viewHeight;
+ if (this.getTable().getKeepFirstVisibleRowComplete()) {
+ minScrollY += rowHeight - 1;
+ }
+ var maxScrollY = rowTop;
+ this.setScrollY(Math.max(minScrollY, Math.min(maxScrollY, scrollY)));
+ }
+}
+
+
+/**
+ * Returns whether currently a cell is editing.
+ *
+ * @return whether currently a cell is editing.
+ */
+qx.Proto.isEditing = function() {
+ return this._cellEditor != null;
+}
+
+
+/**
+ * Starts editing the currently focused cell. Does nothing if already editing
+ * or if the column is not editable.
+ *
+ * @return {boolean} whether editing was started
+ */
+qx.Proto.startEditing = function() {
+ var tableModel = this.getTable().getTableModel();
+ var col = this._focusedCol;
+
+ if (!this.isEditing() && (col != null) && tableModel.isColumnEditable(col)) {
+ var row = this._focusedRow;
+ var xPos = this.getTablePaneModel().getX(col);
+ var value = tableModel.getValue(col, row);
+
+ this._cellEditorFactory = this.getTable().getTableColumnModel().getCellEditorFactory(col);
+ var cellInfo = { col:col, row:row, xPos:xPos, value:value }
+ this._cellEditor = this._cellEditorFactory.createCellEditor(cellInfo);
+ this._cellEditor.set({ width:"100%", height:"100%" });
+
+ this._focusIndicator.add(this._cellEditor);
+ this._focusIndicator.addState("editing");
+
+ this._cellEditor.addEventListener("changeFocused", this._onCellEditorFocusChanged, this);
+
+ // Workaround: Calling focus() directly has no effect
+ var editor = this._cellEditor;
+ window.setTimeout(function() {
+ editor.focus();
+ }, 0);
+
+ return true;
+ }
+
+ return false;
+}
+
+
+/**
+ * Stops editing and writes the editor's value to the model.
+ */
+qx.Proto.stopEditing = function() {
+ this.flushEditor();
+ this.cancelEditing();
+}
+
+
+/**
+ * Writes the editor's value to the model.
+ */
+qx.Proto.flushEditor = function() {
+ if (this.isEditing()) {
+ var value = this._cellEditorFactory.getCellEditorValue(this._cellEditor);
+ this.getTable().getTableModel().setValue(this._focusedCol, this._focusedRow, value);
+
+ this._table.focus();
+ }
+}
+
+
+/**
+ * Stops editing without writing the editor's value to the model.
+ */
+qx.Proto.cancelEditing = function() {
+ if (this.isEditing()) {
+ this._focusIndicator.remove(this._cellEditor);
+ this._focusIndicator.removeState("editing");
+ this._cellEditor.dispose();
+
+ this._cellEditor.removeEventListener("changeFocused", this._onCellEditorFocusChanged, this);
+ this._cellEditor = null;
+ this._cellEditorFactory = null;
+ }
+}
+
+
+/**
+ * Event handler. Called when the focused state of the cell editor changed.
+ *
+ * @param evt {Map} the event.
+ */
+qx.Proto._onCellEditorFocusChanged = function(evt) {
+ if (!this._cellEditor.getFocused()) {
+ this.stopEditing();
+ }
+}
+
+
+/**
+ * Returns the model index of the column the mouse is over or null if the mouse
+ * is not over a column.
+ *
+ * @param pageX {int} the x position of the mouse in the page (in pixels).
+ * @return {int} the model index of the column the mouse is over.
+ */
+qx.Proto._getColumnForPageX = function(pageX) {
+ var headerLeftX = qx.dom.Location.getClientBoxLeft(this._header.getElement());
+
+ var columnModel = this.getTable().getTableColumnModel();
+ var paneModel = this.getTablePaneModel();
+ var colCount = paneModel.getColumnCount();
+ var currX = headerLeftX;
+ for (var x = 0; x < colCount; x++) {
+ var col = paneModel.getColumnAtX(x);
+ var colWidth = columnModel.getColumnWidth(col);
+ currX += colWidth;
+
+ if (pageX < currX) {
+ return col;
+ }
+ }
+
+ return null;
+}
+
+
+/**
+ * Returns the model index of the column that should be resized when dragging
+ * starts here. Returns -1 if the mouse is in no resize region of any column.
+ *
+ * @param pageX {int} the x position of the mouse in the page (in pixels).
+ * @return {int} the column index.
+ */
+qx.Proto._getResizeColumnForPageX = function(pageX) {
+ var headerLeftX = qx.dom.Location.getClientBoxLeft(this._header.getElement());
+
+ var columnModel = this.getTable().getTableColumnModel();
+ var paneModel = this.getTablePaneModel();
+ var colCount = paneModel.getColumnCount();
+ var currX = headerLeftX;
+ var regionRadius = qx.ui.table.TablePaneScroller.RESIZE_REGION_RADIUS;
+ for (var x = 0; x < colCount; x++) {
+ var col = paneModel.getColumnAtX(x);
+ var colWidth = columnModel.getColumnWidth(col);
+ currX += colWidth;
+
+ if (pageX >= (currX - regionRadius) && pageX <= (currX + regionRadius)) {
+ return col;
+ }
+ }
+
+ return -1;
+}
+
+
+/**
+ * Returns the model index of the row the mouse is currently over. Returns -1 if
+ * the mouse is over the header. Returns null if the mouse is not over any
+ * column.
+ *
+ * @param pageX {int} the mouse x position in the page.
+ * @param pageY {int} the mouse y position in the page.
+ * @return {int} the model index of the row the mouse is currently over.
+ */
+qx.Proto._getRowForPagePos = function(pageX, pageY) {
+ var paneClipperElem = this._paneClipper.getElement();
+ var paneClipperLeftX = qx.dom.Location.getClientBoxLeft(paneClipperElem);
+ var paneClipperRightX = qx.dom.Location.getClientBoxRight(paneClipperElem);
+ if (pageX < paneClipperLeftX || pageX > paneClipperRightX) {
+ // There was no cell or header cell hit
+ return null;
+ }
+
+ var paneClipperTopY = qx.dom.Location.getClientBoxTop(paneClipperElem);
+ var paneClipperBottomY = qx.dom.Location.getClientBoxBottom(paneClipperElem);
+ if (pageY >= paneClipperTopY && pageY <= paneClipperBottomY) {
+ // This event is in the pane -> Get the row
+ var rowHeight = this.getTable().getRowHeight();
+
+ var scrollY = this._verScrollBar.getValue();
+ if (this.getTable().getKeepFirstVisibleRowComplete()) {
+ scrollY = Math.floor(scrollY / rowHeight) * rowHeight;
+ }
+
+ var tableY = scrollY + pageY - paneClipperTopY;
+ var row = Math.floor(tableY / rowHeight);
+
+ var rowCount = this.getTable().getTableModel().getRowCount();
+ return (row < rowCount) ? row : null;
+ }
+
+ var headerElem = this._headerClipper.getElement();
+ if (pageY >= qx.dom.Location.getClientBoxTop(headerElem)
+ && pageY <= qx.dom.Location.getClientBoxBottom(headerElem)
+ && pageX <= qx.dom.Location.getClientBoxRight(headerElem))
+ {
+ // This event is in the pane -> Return -1 for the header
+ return -1;
+ }
+
+ return null;
+}
+
+
+/**
+ * Sets the widget that should be shown in the top right corner.
+ *
+ * The widget will not be disposed, when this table scroller is disposed. So the
+ * caller has to dispose it.
+ *
+ * @param widget {qx.ui.core.Widget} The widget to set. May be null.
+ */
+qx.Proto.setTopRightWidget = function(widget) {
+ var oldWidget = this._topRightWidget;
+ if (oldWidget != null) {
+ this._top.remove(oldWidget);
+ }
+
+ if (widget != null) {
+ this._top.remove(this._spacer);
+ this._top.add(widget);
+ } else if (oldWidget != null) {
+ this._top.add(this._spacer);
+ }
+
+ this._topRightWidget = widget;
+}
+
+
+/**
+ * Returns the header.
+ *
+ * @return {TablePaneHeader} the header.
+ */
+qx.Proto.getHeader = function() {
+ return this._header;
+}
+
+
+/**
+ * Returns the table pane.
+ *
+ * @return {TablePane} the table pane.
+ */
+qx.Proto.getTablePane = function() {
+ return this._tablePane;
+}
+
+
+/**
+ * Returns which scrollbars are needed.
+ *
+ * @param forceHorizontal {boolean ? false} Whether to show the horizontal
+ * scrollbar always.
+ * @param preventVertical {boolean ? false} Whether tp show the vertical scrollbar
+ * never.
+ * @return {int} which scrollbars are needed. This may be any combination of
+ * {@link #HORIZONTAL_SCROLLBAR} or {@link #VERTICAL_SCROLLBAR}
+ * (combined by OR).
+ */
+qx.Proto.getNeededScrollBars = function(forceHorizontal, preventVertical) {
+ var barWidth = this._verScrollBar.getPreferredBoxWidth();
+
+ // Get the width and height of the view (without scroll bars)
+ var viewWidth = this._paneClipper.getInnerWidth();
+ if (this.getVerticalScrollBarVisible()) {
+ viewWidth += barWidth;
+ }
+ var viewHeight = this._paneClipper.getInnerHeight();
+ if (this.getHorizontalScrollBarVisible()) {
+ viewHeight += barWidth;
+ }
+
+ // Get the (virtual) width and height of the pane
+ var paneWidth = this.getTablePaneModel().getTotalWidth();
+ var paneHeight = this.getTable().getRowHeight() * this.getTable().getTableModel().getRowCount();
+
+ // Check which scrollbars are needed
+ var horNeeded = false;
+ var verNeeded = false;
+ if (paneWidth > viewWidth) {
+ horNeeded = true;
+ if (paneHeight > viewHeight - barWidth) {
+ verNeeded = true;
+ }
+ } else if (paneHeight > viewHeight) {
+ verNeeded = true;
+ if (!preventVertical && (paneWidth > viewWidth - barWidth)) {
+ horNeeded = true;
+ }
+ }
+
+ // Create the mask
+ var horBar = qx.ui.table.TablePaneScroller.HORIZONTAL_SCROLLBAR;
+ var verBar = qx.ui.table.TablePaneScroller.VERTICAL_SCROLLBAR;
+ return ((forceHorizontal || horNeeded) ? horBar : 0)
+ | ((preventVertical || !verNeeded) ? 0 : verBar);
+}
+
+
+/**
+ * Does a postponed update of the content.
+ *
+ * @see #_updateContent
+ */
+qx.Proto._postponedUpdateContent = function() {
+ if (! this._updateContentPlanned) {
+ var self = this;
+ window.setTimeout(function() {
+ self._updateContent();
+ self._updateContentPlanned = false;
+ qx.ui.core.Widget.flushGlobalQueues();
+ }, 0);
+ this._updateContentPlanned = true;
+ }
+}
+
+
+/**
+ * Updates the content. Sets the right section the table pane should show and
+ * does the scrolling.
+ */
+qx.Proto._updateContent = function() {
+ var paneHeight = this._paneClipper.getInnerHeight();
+ var scrollX = this._horScrollBar.getValue();
+ var scrollY = this._verScrollBar.getValue();
+ var rowHeight = this.getTable().getRowHeight();
+
+ var firstRow = Math.floor(scrollY / rowHeight);
+ var oldFirstRow = this._tablePane.getFirstVisibleRow();
+ this._tablePane.setFirstVisibleRow(firstRow);
+
+ var rowCount = Math.ceil(paneHeight / rowHeight);
+ var paneOffset = 0;
+ if (! this.getTable().getKeepFirstVisibleRowComplete()) {
+ // NOTE: We don't consider paneOffset, because this may cause alternating
+ // adding and deleting of one row when scolling. Instead we add one row
+ // in every case.
+ rowCount++;
+ paneOffset = scrollY % rowHeight;
+ }
+ this._tablePane.setVisibleRowCount(rowCount);
+
+ if (firstRow != oldFirstRow) {
+ this._updateFocusIndicator();
+ }
+
+ // Workaround: We can't use scrollLeft for the header because IE
+ // automatically scrolls the header back, when a column is
+ // resized.
+ this._header.setLeft(-scrollX);
+ this._paneClipper.setScrollLeft(scrollX);
+ this._paneClipper.setScrollTop(paneOffset);
+
+ //this.debug("paneHeight:"+paneHeight+",rowHeight:"+rowHeight+",firstRow:"+firstRow+",rowCount:"+rowCount+",paneOffset:"+paneOffset);
+}
+
+
+/**
+ * Updates the location and the visibility of the focus indicator.
+ */
+qx.Proto._updateFocusIndicator = function() {
+ if (this._focusedCol == null) {
+ this._focusIndicator.hide();
+ } else {
+ var xPos = this.getTablePaneModel().getX(this._focusedCol);
+ if (xPos == -1) {
+ this._focusIndicator.hide();
+ } else {
+ var columnModel = this.getTable().getTableColumnModel();
+ var paneModel = this.getTablePaneModel();
+
+ var firstRow = this._tablePane.getFirstVisibleRow();
+ var rowHeight = this.getTable().getRowHeight();
+
+ this._focusIndicator.setHeight(rowHeight + 3);
+ this._focusIndicator.setWidth(columnModel.getColumnWidth(this._focusedCol) + 3);
+ this._focusIndicator.setTop((this._focusedRow - firstRow) * rowHeight - 2);
+ this._focusIndicator.setLeft(paneModel.getColumnLeft(this._focusedCol) - 2);
+
+ this._focusIndicator.show();
+ }
+ }
+}
+
+
+// overridden
+qx.Proto.dispose = function() {
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this.getElement() != null) {
+ this.getElement().onselectstart = null;
+ }
+
+ this._verScrollBar.dispose();
+ this._horScrollBar.dispose();
+ this._header.dispose();
+ this._headerClipper.dispose();
+ this._spacer.dispose();
+ this._top.dispose();
+ this._tablePane.dispose();
+ this._paneClipper.dispose();
+
+ if (this._resizeLine != null) {
+ this._resizeLine.dispose();
+ }
+
+ this.removeEventListener("mousemove", this._onmousemove, this);
+ this.removeEventListener("mousedown", this._onmousedown, this);
+ this.removeEventListener("mouseup", this._onmouseup, this);
+ this.removeEventListener("click", this._onclick, this);
+ this.removeEventListener("dblclick", this._ondblclick, this);
+ this.removeEventListener("mouseout", this._onmouseout, this);
+
+ var tablePaneModel = this.getTablePaneModel();
+ if (tablePaneModel != null) {
+ tablePaneModel.removeEventListener("modelChanged", this._onPaneModelChanged, this);
+ }
+
+ return qx.ui.layout.VerticalBoxLayout.prototype.dispose.call(this);
+}
+
+
+/** {int} The minimum width a colum could get in pixels. */
+qx.Class.MIN_COLUMN_WIDTH = 10;
+
+/** {int} The radius of the resize region in pixels. */
+qx.Class.RESIZE_REGION_RADIUS = 5;
+
+/**
+ * (int) The number of pixels the mouse may move between mouse down and mouse up
+ * in order to count as a click.
+ */
+qx.Class.CLICK_TOLERANCE = 5;
+
+/**
+ * (int) The mask for the horizontal scroll bar.
+ * May be combined with {@link #VERTICAL_SCROLLBAR}.
+ *
+ * @see #getNeededScrollBars
+ */
+qx.Class.HORIZONTAL_SCROLLBAR = 1;
+
+/**
+ * (int) The mask for the vertical scroll bar.
+ * May be combined with {@link #HORIZONTAL_SCROLLBAR}.
+ *
+ * @see #getNeededScrollBars
+ */
+qx.Class.VERTICAL_SCROLLBAR = 2;
+
+/**
+ * (string) The correct value for the CSS style attribute "cursor" for the
+ * horizontal resize cursor.
+ */
+qx.Class.CURSOR_RESIZE_HORIZONTAL = (qx.sys.Client.getInstance().isGecko() && (qx.sys.Client.getInstance().getMajor() > 1 || qx.sys.Client.getInstance().getMinor() >= 8)) ? "ew-resize" : "e-resize";
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TextFieldCellEditorFactory.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TextFieldCellEditorFactory.js
new file mode 100644
index 0000000000..6878ce7470
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TextFieldCellEditorFactory.js
@@ -0,0 +1,58 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_table)
+
+************************************************************************ */
+
+/**
+ * A cell editor factory creating text fields.
+ */
+qx.OO.defineClass("qx.ui.table.TextFieldCellEditorFactory", qx.ui.table.CellEditorFactory,
+function() {
+ qx.ui.table.CellEditorFactory.call(this);
+});
+
+
+// overridden
+qx.Proto.createCellEditor = function(cellInfo) {
+ var cellEditor = new qx.ui.form.TextField;
+ cellEditor.setAppearance("table-editor-textfield");
+ cellEditor.originalValue = cellInfo.value;
+ cellEditor.setValue("" + cellInfo.value);
+
+ cellEditor.addEventListener("appear", function() {
+ this.selectAll();
+ });
+
+ return cellEditor;
+}
+
+
+// overridden
+qx.Proto.getCellEditorValue = function(cellEditor) {
+ // Workaround: qx.ui.form.TextField.getValue() delivers the old value, so we use the
+ // value property of the DOM element directly
+ var value = cellEditor.getElement().value;
+
+ if (typeof cellEditor.originalValue == "number") {
+ value = parseFloat(value);
+ }
+ return value;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Button.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Button.js
new file mode 100644
index 0000000000..a231960872
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Button.js
@@ -0,0 +1,47 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_toolbar)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.toolbar.Button", qx.ui.form.Button,
+function(vText, vIcon, vIconWidth, vIconHeight, vFlash)
+{
+ qx.ui.form.Button.call(this, vText, vIcon, vIconWidth, vIconHeight, vFlash);
+
+ // Omit focus
+ this.setTabIndex(-1);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "toolbar-button" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeydown = qx.util.Return.returnTrue;
+qx.Proto._onkeyup = qx.util.Return.returnTrue;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/CheckBox.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/CheckBox.js
new file mode 100644
index 0000000000..781a8bc794
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/CheckBox.js
@@ -0,0 +1,86 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_toolbar)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.toolbar.CheckBox", qx.ui.toolbar.Button,
+function(vText, vIcon, vChecked)
+{
+ qx.ui.toolbar.Button.call(this, vText, vIcon);
+
+ if (qx.util.Validation.isValid(vChecked)) {
+ this.setChecked(vChecked);
+ }
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "checked", type : "boolean", defaultValue : false, getAlias:"isChecked" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyChecked = function(propValue, propOldValue, propData)
+{
+ propValue ? this.addState("checked") : this.removeState("checked");
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmouseup = function(e)
+{
+ this.setCapture(false);
+
+ if (!this.hasState("abandoned"))
+ {
+ this.addState("over");
+ this.setChecked(!this.getChecked());
+ this.execute();
+ }
+
+ this.removeState("abandoned");
+ this.removeState("pressed");
+
+ e.stopPropagation();
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/MenuButton.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/MenuButton.js
new file mode 100644
index 0000000000..a06c26fdc1
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/MenuButton.js
@@ -0,0 +1,258 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_toolbar)
+#module(ui_menu)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.toolbar.MenuButton", qx.ui.toolbar.Button,
+function(vText, vMenu, vIcon, vIconWidth, vIconHeight, vFlash)
+{
+ qx.ui.toolbar.Button.call(this, vText, vIcon, vIconWidth, vIconHeight, vFlash);
+
+ if (qx.util.Validation.isValidObject(vMenu)) {
+ this.setMenu(vMenu);
+ }
+
+ /*
+ this._menuButton = new qx.ui.basic.Image("widget/arrows/down_small.gif");
+ this._menuButton.setAnonymous(true);
+ this.addAtEnd(this._menuButton);
+ */
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "menu", type : "object", instance : "qx.ui.menu.Menu" });
+qx.OO.addProperty({ name : "direction", type : "string", allowNull : false, possibleValues : [ "up", "down" ], defaultValue : "down" });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getParentToolBar = function()
+{
+ var vParent = this.getParent();
+
+ if (vParent instanceof qx.ui.toolbar.Part) {
+ vParent = vParent.getParent();
+ }
+
+ return vParent instanceof qx.ui.toolbar.ToolBar ? vParent : null;
+}
+
+qx.Proto._showMenu = function(vFromKeyEvent)
+{
+ var vMenu = this.getMenu();
+
+ if (vMenu)
+ {
+ // Caching common stuff
+ var vMenuParent = vMenu.getParent();
+ var vMenuParentElement = vMenuParent.getElement();
+ var vButtonElement = this.getElement();
+ var vButtonHeight = qx.dom.Dimension.getBoxHeight(vButtonElement);
+
+ // Apply X-Location
+ var vMenuParentLeft = qx.dom.Location.getPageBoxLeft(vMenuParentElement);
+ var vButtonLeft = qx.dom.Location.getPageBoxLeft(vButtonElement);
+
+ vMenu.setLeft(vButtonLeft - vMenuParentLeft);
+
+ // Apply Y-Location
+ switch(this.getDirection())
+ {
+ case "up":
+ var vBodyHeight = qx.dom.Dimension.getInnerHeight(document.body);
+ var vMenuParentBottom = qx.dom.Location.getPageBoxBottom(vMenuParentElement);
+ var vButtonBottom = qx.dom.Location.getPageBoxBottom(vButtonElement);
+
+ vMenu.setBottom(vButtonHeight + (vBodyHeight - vButtonBottom) - (vBodyHeight - vMenuParentBottom));
+ vMenu.setTop(null);
+ break;
+
+ case "down":
+ var vButtonTop = qx.dom.Location.getPageBoxTop(vButtonElement);
+
+ vMenu.setTop(vButtonTop + vButtonHeight);
+ vMenu.setBottom(null);
+ break;
+ }
+
+ this.addState("pressed");
+
+ // If this show is called from a key event occured, we want to highlight
+ // the first menubutton inside.
+ if (vFromKeyEvent) {
+ vMenu.setHoverItem(vMenu.getFirstActiveChild());
+ }
+
+ vMenu.show();
+ }
+}
+
+qx.Proto._hideMenu = function()
+{
+ var vMenu = this.getMenu();
+
+ if (vMenu) {
+ vMenu.hide();
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyMenu = function(propValue, propOldValue, propData)
+{
+ if (propOldValue)
+ {
+ propOldValue.setOpener(null);
+
+ propOldValue.removeEventListener("appear", this._onmenuappear, this);
+ propOldValue.removeEventListener("disappear", this._onmenudisappear, this);
+ }
+
+ if (propValue)
+ {
+ propValue.setOpener(this);
+
+ propValue.addEventListener("appear", this._onmenuappear, this);
+ propValue.addEventListener("disappear", this._onmenudisappear, this);
+ }
+
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS: MOUSE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousedown = function(e)
+{
+ if (e.getTarget() != this || !e.isLeftButtonPressed()) {
+ return;
+ }
+
+ this.hasState("pressed") ? this._hideMenu() : this._showMenu();
+}
+
+qx.Proto._onmouseup = function(e) {}
+
+qx.Proto._onmouseout = function(e)
+{
+ if (e.getTarget() != this) {
+ return;
+ }
+
+ this.removeState("over");
+}
+
+qx.Proto._onmouseover = function(e)
+{
+ var vToolBar = this.getParentToolBar();
+
+ if (vToolBar)
+ {
+ var vMenu = this.getMenu();
+
+ switch(vToolBar.getOpenMenu())
+ {
+ case null:
+ case vMenu:
+ break;
+
+ default:
+ // hide other menus
+ qx.manager.object.MenuManager.getInstance().update();
+
+ // show this menu
+ this._showMenu();
+ }
+ }
+
+ return qx.ui.toolbar.Button.prototype._onmouseover.call(this, e);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS: MENU
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmenuappear = function(e)
+{
+ var vToolBar = this.getParentToolBar();
+
+ if (!vToolBar) {
+ return;
+ }
+
+ var vMenu = this.getMenu();
+
+ vToolBar.setOpenMenu(vMenu);
+}
+
+qx.Proto._onmenudisappear = function(e)
+{
+ var vToolBar = this.getParentToolBar();
+
+ if (!vToolBar) {
+ return;
+ }
+
+ var vMenu = this.getMenu();
+
+ if (vToolBar.getOpenMenu() == vMenu) {
+ vToolBar.setOpenMenu(null);
+ }
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Part.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Part.js
new file mode 100644
index 0000000000..292a9045c4
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Part.js
@@ -0,0 +1,82 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_toolbar)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.toolbar.Part", qx.ui.layout.HorizontalBoxLayout,
+function()
+{
+ qx.ui.layout.HorizontalBoxLayout.call(this);
+
+ this._handle = new qx.ui.toolbar.PartHandle;
+ this.add(this._handle);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "toolbar-part" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CLONE
+---------------------------------------------------------------------------
+*/
+
+// Omit recursive cloning of qx.ui.toolbar.PartHandle
+qx.Proto._cloneRecursive = function(cloneInstance)
+{
+ var vChildren = this.getChildren();
+ var vLength = vChildren.length;
+
+ for (var i=0; i=0; i--)
+ {
+ vCurrent = vChildren[i];
+
+ if (vCurrent instanceof qx.ui.toolbar.MenuButton && vCurrent.getEnabled())
+ {
+ vPrevButton = vCurrent;
+ break;
+ }
+ }
+
+ // If none found, try again from the begin (looping)
+ if (!vPrevButton)
+ {
+ for (var i=vChildrenLength-1; i>vIndex; i--)
+ {
+ vCurrent = vChildren[i];
+
+ if (vCurrent instanceof qx.ui.toolbar.MenuButton && vCurrent.getEnabled())
+ {
+ vPrevButton = vCurrent;
+ break;
+ }
+ }
+ }
+
+ if (vPrevButton)
+ {
+ // hide other menus
+ qx.manager.object.MenuManager.getInstance().update();
+
+ // show previous menu
+ vPrevButton._showMenu(true);
+ }
+}
+
+qx.Proto._onkeypress_right = function()
+{
+ var vMenu = this.getOpenMenu();
+ if (!vMenu) {
+ return;
+ }
+
+ var vOpener = vMenu.getOpener();
+ if (!vOpener) {
+ return;
+ }
+
+ var vChildren = this.getAllButtons();
+ var vChildrenLength = vChildren.length;
+ var vIndex = vChildren.indexOf(vOpener);
+ var vCurrent;
+ var vNextButton = null;
+
+ for (var i=vIndex+1; ideselects, disconnects, removes and disposes the
+ * current tree element and its content.
+ *
+ *
+ * destroys the current item (TreeFile or TreeFolder)
+ * and all its subitems. The destruction of the subitems
+ * is done by calling destroyContent. This is done if the
+ * subitem has the method destroyContent which is true if the
+ * subitem is a TreeFolder (or one of its subclasses).
+ *
+ *
+ * The method destroyContent is defined in the TreeFolder class.
+ *
+ */
+qx.Proto.destroy = function() {
+ var manager = this.getTree() ? this.getTree().getManager() : null;
+ if(manager) {
+
+ // if the current destroyed item is
+ // selectd deselect the item. If we are
+ // in single selection mode we have to
+ // call deselectAll because setItemSelected
+ // refuses to deselect in this case
+ if(manager.getItemSelected(this)) {
+ if(manager.getMultiSelection()) {
+ manager.setItemSelected(this,false);
+ }
+ else {
+ manager.deselectAll();
+ }
+ }
+
+ // set the leadItem to null if the current
+ // destroyed item is the leadItem
+ if(manager.getLeadItem() == this) {
+ manager.setLeadItem(null);
+ }
+ // set the anchorItem to null if the current
+ // destroyed item is the anchorItem
+ if(manager.getAnchorItem() == this) {
+ manager.setAnchorItem(null);
+ }
+ }
+
+ // if the item has the method destroyContent defined
+ // then it is a TreeFolder (and it's subclasses)
+ // which potentially have content which also
+ // has to be destroyed
+ if(this.destroyContent) {
+ this.destroyContent();
+ }
+
+ // first disconnect the item so rendering
+ // of the tree lines can be done correctly
+ this.disconnect();
+
+ // remove the current item from
+ // the parent folder
+ var parentFolder = this.getParentFolder();
+ if(parentFolder) {
+ parentFolder.remove(this);
+ }
+
+ this.dispose();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ QUEUE HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.addToTreeQueue = function()
+{
+ var vTree = this.getTree();
+ if (vTree) {
+ vTree.addChildToTreeQueue(this);
+ }
+}
+
+qx.Proto.removeFromTreeQueue = function()
+{
+ var vTree = this.getTree();
+ if (vTree) {
+ vTree.removeChildFromTreeQueue(this);
+ }
+}
+
+qx.Proto.addToCustomQueues = function(vHint)
+{
+ this.addToTreeQueue();
+
+ qx.ui.layout.BoxLayout.prototype.addToCustomQueues.call(this, vHint);
+}
+
+qx.Proto.removeFromCustomQueues = function(vHint)
+{
+ this.removeFromTreeQueue();
+
+ qx.ui.layout.BoxLayout.prototype.removeFromCustomQueues.call(this, vHint);
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPLAYBLE HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyParent = function(propValue, propOldValue, propData)
+{
+ qx.ui.layout.BoxLayout.prototype._modifyParent.call(this, propValue, propOldValue, propData);
+
+ // Be sure to update previous folder also if it is closed currently (plus/minus symbol)
+ if (propOldValue && !propOldValue.isDisplayable() && propOldValue.getParent() && propOldValue.getParent().isDisplayable()) {
+ propOldValue.getParent().addToTreeQueue();
+ }
+
+ // Be sure to update new folder also if it is closed currently (plus/minus symbol)
+ if (propValue && !propValue.isDisplayable() && propValue.getParent() && propValue.getParent().isDisplayable()) {
+ propValue.getParent().addToTreeQueue();
+ }
+
+ return true;
+}
+
+qx.Proto._handleDisplayableCustom = function(vDisplayable, vParent, vHint)
+{
+ qx.ui.layout.BoxLayout.prototype._handleDisplayableCustom.call(this, vDisplayable, vParent, vHint);
+
+ if (vHint)
+ {
+ var vParentFolder = this.getParentFolder();
+ var vPreviousParentFolder = this._previousParentFolder;
+
+ if (vPreviousParentFolder)
+ {
+ if (this._wasLastVisibleChild)
+ {
+ vPreviousParentFolder._updateIndent();
+ }
+ else if (!vPreviousParentFolder.hasContent())
+ {
+ vPreviousParentFolder.addToTreeQueue();
+ }
+ }
+
+ if (vParentFolder && vParentFolder.isDisplayable() && vParentFolder._initialLayoutDone) {
+ vParentFolder.addToTreeQueue();
+ }
+
+ if (this.isLastVisibleChild())
+ {
+ var vPrev = this.getPreviousVisibleSibling();
+
+ if (vPrev && vPrev instanceof qx.ui.tree.AbstractTreeElement) {
+ vPrev._updateIndent();
+ }
+ }
+
+ if (vDisplayable) {
+ this._updateIndent();
+ }
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT LISTENERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousedown = function(e)
+{
+ this.getTree().getManager().handleMouseDown(this, e);
+ e.stopPropagation();
+}
+
+qx.Proto._onmouseup = qx.util.Return.returnTrue;
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ TREE FLUSH
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.flushTree = function()
+{
+ // store informations for update process
+ this._previousParentFolder = this.getParentFolder();
+ this._wasLastVisibleChild = this.isLastVisibleChild();
+
+ // generate html for indent area
+ var vLevel = this.getLevel();
+ var vTree = this.getTree();
+ var vImage;
+ var vHtml = [];
+ var vCurrentObject = this;
+
+ for (var i=0; i ");
+ }
+
+ vCurrentObject = vCurrentObject.getParentFolder();
+ }
+
+ this._indentObject.setHtml(vHtml.join(""));
+ this._indentObject.setWidth(vLevel * 19);
+}
+
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._indentObject)
+ {
+ this._indentObject.dispose();
+ this._indentObject = null;
+ }
+
+ if (this._iconObject)
+ {
+ this._iconObject.dispose();
+ this._iconObject = null;
+ }
+
+ if (this._labelObject)
+ {
+ this._labelObject.dispose();
+ this._labelObject = null;
+ }
+
+ this._previousParentFolder = null;
+
+ this.removeEventListener("mousedown", this._onmousedown);
+ this.removeEventListener("mouseup", this._onmouseup);
+
+ return qx.ui.layout.BoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/Tree.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/Tree.js
new file mode 100644
index 0000000000..18affeccb4
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/Tree.js
@@ -0,0 +1,398 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_tree)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.tree.Tree", qx.ui.tree.TreeFolder,
+function(vLabel, vIcon, vIconSelected)
+{
+ qx.ui.tree.TreeFolder.call(this, vLabel, vIcon, vIconSelected);
+
+ // ************************************************************************
+ // INITILISIZE MANAGER
+ // ************************************************************************
+ this._manager = new qx.manager.selection.TreeSelectionManager(this);
+
+
+ this._iconObject.setAppearance("tree-icon");
+ this._labelObject.setAppearance("tree-label");
+
+
+ // ************************************************************************
+ // DEFAULT STATE
+ // ************************************************************************
+ // The tree should be open by default
+ this.setOpen(true);
+
+ // Fix vertical alignment of empty tree
+ this.addToFolder();
+
+
+ // ************************************************************************
+ // KEY EVENT LISTENER
+ // ************************************************************************
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keypress", this._onkeypress);
+ this.addEventListener("keyup", this._onkeyup);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "useDoubleClick", type : "boolean", defaultValue : false, getAlias : "useDoubleClick" });
+qx.OO.addProperty({ name : "useTreeLines", type : "boolean", defaultValue : true, getAlias : "useTreeLines" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MANAGER BINDING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getManager = function() {
+ return this._manager;
+}
+
+qx.Proto.getSelectedElement = function() {
+ return this.getManager().getSelectedItem();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ QUEUE HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.addChildToTreeQueue = function(vChild)
+{
+ if (!vChild._isInTreeQueue && !vChild._isDisplayable) {
+ this.debug("Ignoring invisible child: " + vChild);
+ }
+
+ if (!vChild._isInTreeQueue && vChild._isDisplayable)
+ {
+ qx.ui.core.Widget.addToGlobalWidgetQueue(this);
+
+ if (!this._treeQueue) {
+ this._treeQueue = {};
+ }
+
+ this._treeQueue[vChild.toHashCode()] = vChild;
+
+ vChild._isInTreeQueue = true;
+ }
+}
+
+qx.Proto.removeChildFromTreeQueue = function(vChild)
+{
+ if (vChild._isInTreeQueue)
+ {
+ if (this._treeQueue) {
+ delete this._treeQueue[vChild.toHashCode()];
+ }
+
+ delete vChild._isInTreeQueue;
+ }
+}
+
+qx.Proto.flushWidgetQueue = function() {
+ this.flushTreeQueue();
+}
+
+qx.Proto.flushTreeQueue = function()
+{
+ if (!qx.lang.Object.isEmpty(this._treeQueue))
+ {
+ for (var vHashCode in this._treeQueue)
+ {
+ // this.debug("Flushing Tree Child: " + this._treeQueue[vHashCode]);
+ this._treeQueue[vHashCode].flushTree();
+ delete this._treeQueue[vHashCode]._isInTreeQueue;
+ }
+
+ delete this._treeQueue;
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyUseTreeLines = function(propValue, propOldValue, propData)
+{
+ if (this._initialLayoutDone) {
+ this._updateIndent();
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getTree = function() {
+ return this;
+}
+
+qx.Proto.getParentFolder = function() {
+ return null;
+}
+
+qx.Proto.getLevel = function() {
+ return 0;
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ COMMON CHECKERS
+---------------------------------------------------------------------------
+*/
+
+qx.ui.tree.Tree.isTreeFolder = function(vObject) {
+ return vObject && vObject instanceof qx.ui.tree.TreeFolder && !(vObject instanceof qx.ui.tree.Tree);
+};
+
+qx.ui.tree.Tree.isOpenTreeFolder = function(vObject) {
+ return vObject instanceof qx.ui.tree.TreeFolder && vObject.getOpen() && vObject.hasContent();
+};
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeydown = function(e)
+{
+ var vSelectedItem = this.getManager().getSelectedItem();
+
+ if (e.getKeyIdentifier() == "Enter") {
+ e.preventDefault();
+
+ if (qx.ui.tree.Tree.isTreeFolder(vSelectedItem)) {
+ return vSelectedItem.toggle();
+ }
+ }
+};
+
+
+qx.Proto._onkeypress = function(e)
+{
+ var vManager = this.getManager();
+ var vSelectedItem = vManager.getSelectedItem();
+
+ switch(e.getKeyIdentifier())
+ {
+ case "Left":
+ e.preventDefault();
+
+ if (qx.ui.tree.Tree.isTreeFolder(vSelectedItem))
+ {
+ if (!vSelectedItem.getOpen())
+ {
+ var vParent = vSelectedItem.getParentFolder();
+ if (vParent instanceof qx.ui.tree.TreeFolder) {
+ if (!(vParent instanceof qx.ui.tree.Tree)) {
+ vParent.close();
+ }
+
+ this.setSelectedElement(vParent);
+ }
+ }
+ else
+ {
+ return vSelectedItem.close();
+ }
+ }
+ else if (vSelectedItem instanceof qx.ui.tree.TreeFile)
+ {
+ var vParent = vSelectedItem.getParentFolder();
+ if (vParent instanceof qx.ui.tree.TreeFolder) {
+ if (!(vParent instanceof qx.ui.tree.Tree)) {
+ vParent.close();
+ }
+
+ this.setSelectedElement(vParent);
+ }
+ }
+
+ break;
+
+ case "Right":
+ e.preventDefault();
+
+ if (qx.ui.tree.Tree.isTreeFolder(vSelectedItem))
+ {
+ if (!vSelectedItem.getOpen())
+ {
+ return vSelectedItem.open();
+ }
+ else if (vSelectedItem.hasContent())
+ {
+ var vFirst = vSelectedItem.getFirstVisibleChildOfFolder();
+ this.setSelectedElement(vFirst);
+
+ if (vFirst instanceof qx.ui.tree.TreeFolder) {
+ vFirst.open();
+ }
+
+ return;
+ }
+ }
+
+ break;
+
+ default:
+ if (!this._fastUpdate)
+ {
+ this._fastUpdate = true;
+ this._oldItem = vSelectedItem;
+ }
+
+ vManager.handleKeyPress(e);
+ }
+};
+
+
+qx.Proto._onkeyup = function(e)
+{
+ if (this._fastUpdate)
+ {
+ var vOldItem = this._oldItem;
+ var vNewItem = this.getManager().getSelectedItem();
+
+ vNewItem.getIconObject().addState("selected");
+
+ delete this._fastUpdate;
+ delete this._oldItem;
+ }
+};
+
+
+qx.Proto.getLastTreeChild = function()
+{
+ var vLast = this;
+
+ while (vLast instanceof qx.ui.tree.AbstractTreeElement)
+ {
+ if (!(vLast instanceof qx.ui.tree.TreeFolder) || !vLast.getOpen()) {
+ return vLast;
+ }
+
+ vLast = vLast.getLastVisibleChildOfFolder();
+ }
+
+ return null;
+};
+
+
+qx.Proto.getFirstTreeChild = function() {
+ return this;
+};
+
+
+qx.Proto.setSelectedElement = function(vElement)
+{
+ var vManager = this.getManager();
+
+ vManager.setSelectedItem(vElement);
+ vManager.setLeadItem(vElement);
+};
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this.removeEventListener("keydown", this._onkeydown);
+ this.removeEventListener("keypress", this._onkeypress);
+ this.removeEventListener("keyup", this._onkeyup);
+
+ if (this._manager)
+ {
+ this._manager.dispose();
+ this._manager = null;
+ }
+
+ delete this._oldItem;
+
+ return qx.ui.tree.TreeFolder.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/TreeFile.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/TreeFile.js
new file mode 100644
index 0000000000..8939b18e2d
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/TreeFile.js
@@ -0,0 +1,62 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_tree)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.tree.TreeFile", qx.ui.tree.AbstractTreeElement,
+function(vLabel, vIcon, vIconSelected) {
+ qx.ui.tree.AbstractTreeElement.call(this, vLabel, vIcon, vIconSelected);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INDENT HELPER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getIndentSymbol = function(vUseTreeLines, vIsLastColumn)
+{
+ if (vUseTreeLines)
+ {
+ if (vIsLastColumn)
+ {
+ return this.isLastChild() ? "end" : "cross";
+ }
+ else
+ {
+ return "line";
+ }
+ }
+
+ return null;
+}
+
+qx.Proto._updateIndent = function() {
+ this.addToTreeQueue();
+}
+
+qx.Proto.getItems = function() {
+ return [this];
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/TreeFolder.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/TreeFolder.js
new file mode 100644
index 0000000000..3f660867f3
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/TreeFolder.js
@@ -0,0 +1,605 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_tree)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.tree.TreeFolder", qx.ui.tree.AbstractTreeElement,
+function(vLabel, vIcon, vIconSelected)
+{
+ qx.ui.tree.AbstractTreeElement.call(this, vLabel, vIcon, vIconSelected);
+
+ this._iconObject.setAppearance("tree-folder-icon");
+ this._labelObject.setAppearance("tree-folder-label");
+
+ this.addEventListener("dblclick", this._ondblclick);
+
+ // Remapping of add/remove methods
+ this.add = this.addToFolder;
+ this.addBefore = this.addBeforeToFolder;
+ this.addAfter = this.addAfterToFolder;
+ this.addAt = this.addAtToFolder;
+ this.addAtBegin = this.addAtBeginToFolder;
+ this.addAtEnd = this.addAtEndToFolder;
+ this.remove = this.removeFromFolder;
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "tree-folder" });
+qx.OO.changeProperty({ name : "icon", type : "string" });
+qx.OO.changeProperty({ name : "iconSelected", type : "string" });
+
+qx.OO.addProperty({ name : "open", type : "boolean", defaultValue : false });
+qx.OO.addProperty({ name : "alwaysShowPlusMinusSymbol", type : "boolean", defaultValue : false });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.hasContent = function() {
+ return this._containerObject && this._containerObject.getChildrenLength() > 0;
+}
+
+qx.Proto.open = function()
+{
+ if (this.getOpen()) {
+ return;
+ }
+
+ if (this.hasContent() && this.isSeeable())
+ {
+ this.getTopLevelWidget().setGlobalCursor("progress");
+ qx.client.Timer.once(this._openCallback, this, 0);
+ }
+ else
+ {
+ this.setOpen(true);
+ }
+}
+
+qx.Proto.close = function() {
+ this.setOpen(false);
+}
+
+qx.Proto.toggle = function() {
+ this.getOpen() ? this.close() : this.open();
+}
+
+qx.Proto._openCallback = function()
+{
+ this.setOpen(true);
+ qx.ui.core.Widget.flushGlobalQueues();
+ this.getTopLevelWidget().setGlobalCursor(null);
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._createChildrenStructure = function()
+{
+ this.setAppearance(this instanceof qx.ui.tree.Tree ? "tree-container" : "tree-folder-container");
+
+ if (!this._horizontalLayout)
+ {
+ this.setOrientation("vertical");
+
+ this._horizontalLayout = new qx.ui.layout.HorizontalBoxLayout;
+ this._horizontalLayout.setWidth(null);
+ this._horizontalLayout.setParent(this);
+ this._horizontalLayout.setAnonymous(true);
+ this._horizontalLayout.setAppearance(this instanceof qx.ui.tree.Tree ? "tree" : "tree-folder");
+
+ this._indentObject.setParent(this._horizontalLayout);
+ this._iconObject.setParent(this._horizontalLayout);
+ this._labelObject.setParent(this._horizontalLayout);
+ }
+
+ if (!this._containerObject)
+ {
+ this._containerObject = new qx.ui.layout.VerticalBoxLayout;
+ this._containerObject.setWidth(null);
+ this._containerObject.setAnonymous(true);
+
+ // it should be faster to first handle display,
+ // because the default display value is true and if we first
+ // setup the parent the logic do all to make the
+ // widget first visible and then, if the folder is not
+ // opened again invisible.
+ this._containerObject.setDisplay(this.getOpen());
+ this._containerObject.setParent(this);
+
+ // remap remove* functions
+ this.remapChildrenHandlingTo(this._containerObject);
+ }
+}
+
+qx.Proto._handleChildMove = function(vChild, vRelationIndex, vRelationChild)
+{
+ if (vChild.isDisplayable())
+ {
+ var vChildren = this._containerObject.getChildren();
+ var vOldChildIndex = vChildren.indexOf(vChild);
+
+ if (vOldChildIndex != -1)
+ {
+ if (vRelationChild) {
+ vRelationIndex = vChildren.indexOf(vRelationChild);
+ }
+
+ if (vRelationIndex == vChildren.length-1)
+ {
+ vChild._updateIndent();
+
+ // Update indent of previous last child
+ this._containerObject.getLastVisibleChild()._updateIndent();
+ }
+ else if (vChild._wasLastVisibleChild)
+ {
+ vChild._updateIndent();
+
+ // Update indent for new last child
+ var vPreviousSibling = vChild.getPreviousVisibleSibling();
+ if (vPreviousSibling) {
+ vPreviousSibling._updateIndent();
+ }
+ }
+ }
+ }
+}
+
+qx.Proto.addToFolder = function()
+{
+ this._createChildrenStructure();
+
+ if (this._containerObject) {
+ return this._containerObject.add.apply(this._containerObject, arguments);
+ }
+}
+
+qx.Proto.addBeforeToFolder = function(vChild, vBefore)
+{
+ this._createChildrenStructure();
+
+ if (this._containerObject)
+ {
+ this._handleChildMove(vChild, null, vBefore);
+ return this._containerObject.addBefore.apply(this._containerObject, arguments);
+ }
+}
+
+qx.Proto.addAfterToFolder = function(vChild, vAfter)
+{
+ this._createChildrenStructure();
+
+ if (this._containerObject)
+ {
+ this._handleChildMove(vChild, null, vAfter);
+ return this._containerObject.addAfter.apply(this._containerObject, arguments);
+ }
+}
+
+qx.Proto.addAtToFolder = function(vChild, vIndex)
+{
+ this._createChildrenStructure();
+
+ if (this._containerObject)
+ {
+ this._handleChildMove(vChild, vIndex);
+ return this._containerObject.addAt.apply(this._containerObject, arguments);
+ }
+}
+
+qx.Proto.addAtBeginToFolder = function(vChild) {
+ return this.addAtToFolder(vChild, 0);
+}
+
+qx.Proto.addAtEndToFolder = function(vChild)
+{
+ this._createChildrenStructure();
+
+ if (this._containerObject)
+ {
+ var vLast = this._containerObject.getLastChild();
+
+ if (vLast)
+ {
+ this._handleChildMove(vChild, null, vLast);
+ return this._containerObject.addAfter.call(this._containerObject, vChild, vLast);
+ }
+ else
+ {
+ return this.addAtBeginToFolder(vChild);
+ }
+ }
+}
+
+qx.Proto._remappingChildTable = [ "remove", "removeAt", "removeAll" ];
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getContainerObject = function() {
+ return this._containerObject;
+}
+
+qx.Proto.getHorizontalLayout = function() {
+ return this._horizontalLayout;
+}
+
+qx.Proto.getFirstVisibleChildOfFolder = function()
+{
+ if (this._containerObject) {
+ return this._containerObject.getFirstChild();
+ }
+}
+
+qx.Proto.getLastVisibleChildOfFolder = function()
+{
+ if (this._containerObject) {
+ return this._containerObject.getLastChild();
+ }
+}
+
+qx.Proto.getItems = function(recursive, invisible)
+{
+ var a = [this];
+
+ if (this._containerObject)
+ {
+ var ch = invisible == true ? this._containerObject.getChildren() : this._containerObject.getVisibleChildren();
+
+ if (recursive == false)
+ {
+ a = a.concat(ch);
+ }
+ else
+ {
+ for (var i=0, chl=ch.length; ideselects, disconnects, removes and disposes the
+ * content of the folder and its subfolders.
+ *
+ *
+ * the current items subitems (and the subitems of each
+ * subitem) are destoyed going top down the TreeFolder
+ * hierarchy. The current item is left as is.
+ *
+ */
+qx.Proto.destroyContent = function() {
+ if(this.hasContent()) {
+
+ var manager = this.getTree() ? this.getTree().getManager() : null;
+
+ var leadItem;
+ var anchorItem;
+ if(manager) {
+ leadItem = manager.getLeadItem();
+ anchorItem = manager.getAnchorItem();
+ }
+
+ var items = this.getItems();
+ var item;
+
+ for(var i=items.length-1;i>=0;--i) {
+ item = items[i];
+
+ // this.getItems seems to also contain this.
+ // In order to avoid endless loops by calling
+ // recursively destroyContent we have to avoid
+ // destroying ourselves
+ if(item != this) {
+ if(manager) {
+ // set the leadItem to null if the current
+ // destroyed item is the leadItem
+ if(leadItem == item) {
+ manager.setLeadItem(null);
+ }
+ // set the anchorItem to null if the current
+ // destroyed item is the anchorItem
+ if(anchorItem == item) {
+ manager.setAnchorItem(null);
+ }
+
+ // if the current destroyed item is
+ // selectd deselect the item. If we are
+ // in single selection mode we have to
+ // call deselectAll because setItemSelected
+ // refuses to deselect in this case
+ if(manager.getItemSelected(item)) {
+ if(manager.getMultiSelection()) {
+ manager.setItemSelected(item,false);
+ }
+ else {
+ manager.deselectAll();
+ }
+ }
+
+ // if the item has the method destroyContent defined
+ // then it is a TreeFolder (and it's subclasses)
+ // which potentially have content which also
+ // has to be destroyed
+ if (item.destroyContent) {
+ item.destroyContent();
+ }
+ }
+
+ // first disconnect the item so rendering
+ // of the tree lines can be done correctly
+ item.disconnect();
+ this.remove(item);
+ item.dispose();
+ }
+ }
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._evalCurrentIcon = function()
+{
+ if (this.getSelected()) {
+ return this.getIconSelected() || "icon/16/folder-open.png";
+ } else {
+ return this.getIcon() || "icon/16/folder.png";
+ }
+}
+
+qx.Proto._modifyOpen = function(propValue, propOldValue, propData)
+{
+ this._updateLastColumn();
+
+ if (this._containerObject) {
+ this._containerObject.setDisplay(propValue);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyAlwaysShowPlusMinusSymbol = function(propValue, propOldValue, propData)
+{
+ this._updateLastColumn();
+
+ return true;
+}
+
+qx.Proto._updateLastColumn = function()
+{
+ if (this._indentObject)
+ {
+ var vElement = this._indentObject.getElement();
+
+ if (vElement && vElement.firstChild) {
+ vElement.firstChild.src = this.BASE_URI + this.getIndentSymbol(this.getTree().getUseTreeLines(), true) + ".gif";
+ }
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT LISTENERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousedown = function(e)
+{
+ var vOriginalTarget = e.getOriginalTarget();
+
+ switch(vOriginalTarget)
+ {
+ case this._indentObject:
+ if (this._indentObject.getElement().firstChild == e.getDomTarget())
+ {
+ this.getTree().getManager().handleMouseDown(this, e);
+ this.toggle();
+ }
+
+ break;
+
+ case this._containerObject:
+ break;
+
+ case this:
+ if (this._containerObject) {
+ break;
+ }
+
+ // no break here
+
+ default:
+ this.getTree().getManager().handleMouseDown(this, e);
+ }
+
+ e.stopPropagation();
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ var vOriginalTarget = e.getOriginalTarget();
+
+ switch(vOriginalTarget)
+ {
+ case this._indentObject:
+ case this._containerObject:
+ case this:
+ break;
+
+ default:
+ if (!this.getTree().getUseDoubleClick()) {
+ this.open();
+ }
+ }
+}
+
+qx.Proto._ondblclick = function(e)
+{
+ if (!this.getTree().getUseDoubleClick()) {
+ return;
+ }
+
+ this.toggle();
+ e.stopPropagation();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INDENT HELPER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getIndentSymbol = function(vUseTreeLines, vIsLastColumn)
+{
+ if (vIsLastColumn)
+ {
+ if (this.hasContent() || this.getAlwaysShowPlusMinusSymbol())
+ {
+ if (!vUseTreeLines)
+ {
+ return this.getOpen() ? "minus" : "plus";
+ }
+ else if (this.isLastChild())
+ {
+ return this.getOpen() ? "end_minus" : "end_plus";
+ }
+ else
+ {
+ return this.getOpen() ? "cross_minus" : "cross_plus";
+ }
+ }
+ else if (vUseTreeLines)
+ {
+ return this.isLastChild() ? "end" : "cross";
+ }
+ }
+ else
+ {
+ return vUseTreeLines && !this.isLastChild() ? "line" : null;
+ }
+}
+
+qx.Proto._updateIndent = function()
+{
+ // Intentionally bypass superclass; the _updateIndent we want is in TreeFile
+ qx.ui.tree.TreeFile.prototype._updateIndent.call(this);
+
+ if (!this._containerObject) {
+ return;
+ }
+
+ var ch = this._containerObject.getVisibleChildren();
+ for (var i=0, l=ch.length; i ");
+ }
+
+ vCurrentObject = vCurrentObject.getParentFolder();
+ }
+
+ this._indentObject.setHtml(vHtml.join(""));
+ this._indentObject.setWidth((vMaxLevel - vMinLevel) * 19);
+}
+
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._indentObject)
+ {
+ this._indentObject.dispose();
+ this._indentObject = null;
+ }
+
+ if (this._iconObject)
+ {
+ this._iconObject.dispose();
+ this._iconObject = null;
+ }
+
+ if (this._labelObject)
+ {
+ this._labelObject.dispose();
+ this._labelObject = null;
+ }
+
+ this._previousParentFolder = null;
+
+ this.removeEventListener("mousedown", this._onmousedown);
+ this.removeEventListener("mouseup", this._onmouseup);
+
+ return qx.ui.layout.BoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/Tree.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/Tree.js
new file mode 100644
index 0000000000..912ede6d60
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/Tree.js
@@ -0,0 +1,539 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+ 2006 by Derrell Lipman
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+ * Derrell Lipman (derrell)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_treefullcontrol)
+
+************************************************************************ */
+
+/**
+ * qx.ui.treefullcontrol.Tree objects are tree root nodes but act like
+ * TreeFolder.
+ *
+ * @param treeRowStructure An instance of qx.ui.treefullcontrol.TreeRowStructure,
+ * defining the structure of this tree row.
+ */
+qx.OO.defineClass("qx.ui.treefullcontrol.Tree", qx.ui.treefullcontrol.TreeFolder,
+function(treeRowStructure)
+{
+ qx.ui.treefullcontrol.TreeFolder.call(this, treeRowStructure);
+
+ // ************************************************************************
+ // INITILISIZE MANAGER
+ // ************************************************************************
+ this._manager = new qx.manager.selection.TreeFullControlSelectionManager(this);
+
+
+ this._iconObject.setAppearance("tree-icon");
+ this._labelObject.setAppearance("tree-label");
+
+
+ // ************************************************************************
+ // DEFAULT STATE
+ // ************************************************************************
+ // The tree should be open by default
+ this.setOpen(true);
+
+ // Fix vertical alignment of empty tree
+ this.addToFolder();
+
+
+ // ************************************************************************
+ // KEY EVENT LISTENER
+ // ************************************************************************
+ this.addEventListener("keydown", this._onkeydown);
+ this.addEventListener("keypress", this._onkeypress);
+ this.addEventListener("keyup", this._onkeyup);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "useDoubleClick",
+ type : "boolean",
+ defaultValue : false,
+ getAlias : "useDoubleClick"
+ });
+
+qx.OO.addProperty({ name : "useTreeLines",
+ type : "boolean",
+ defaultValue : true,
+ getAlias : "useTreeLines"
+ });
+
+/*!
+ In specific applications, it is desirable to omit tree lines for only
+ certain indentation levels. This property provides an array wherein the
+ index of the array corresponds to the indentation level, counted from left
+ to right; and the value of that element, if it contains, specifically, the
+ boolean value true , indicates that tree lines at that indentation
+ level are to be omitted. Any value of that element other than true ,
+ or if an indentation level's index does not exist in the array, means that
+ tree lines should be displayed for that indentation level. (There are some
+ minor code efficiencies that are realized if this array is empty, so after
+ having set an element to true and desiring to reset the default
+ behavior, you should 'delete' the element rather than setting it to some
+ value other than true .)
+
+ If useTreeLines is false , then all tree lines are excluded and this
+ property is ignored.
+*/
+qx.OO.addProperty({ name : "excludeSpecificTreeLines",
+ type : "object",
+ defaultValue : []
+ });
+
+/*!
+ Hide the root (Tree) node. This differs from the visibility property in
+ that this property hides *only* the current node, not the node's children.
+*/
+qx.OO.addProperty({ name : "hideNode",
+ type : "boolean",
+ defaultValue : false,
+ getAlias : "hideNode"
+ });
+
+/*!
+ Whether the Root should have an open/close button. This may also be
+ used in conjunction with the hideNode property to provide for virtual root
+ nodes. In the latter case, be very sure that the virtual root nodes are
+ expanded programatically, since there will be no open/close button for the
+ user to open them.
+*/
+qx.OO.addProperty({ name : "rootOpenClose",
+ type : "boolean",
+ defaultValue : true
+ });
+
+
+/*
+---------------------------------------------------------------------------
+ MANAGER BINDING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getManager = function() {
+ return this._manager;
+}
+
+qx.Proto.getSelectedElement = function() {
+ return this.getManager().getSelectedItems()[0];
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ QUEUE HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.addChildToTreeQueue = function(vChild)
+{
+ if (!vChild._isInTreeQueue && !vChild._isDisplayable) {
+ this.debug("Ignoring invisible child: " + vChild);
+ }
+
+ if (!vChild._isInTreeQueue && vChild._isDisplayable)
+ {
+ qx.ui.core.Widget.addToGlobalWidgetQueue(this);
+
+ if (!this._treeQueue) {
+ this._treeQueue = {};
+ }
+
+ this._treeQueue[vChild.toHashCode()] = vChild;
+
+ vChild._isInTreeQueue = true;
+ }
+}
+
+qx.Proto.removeChildFromTreeQueue = function(vChild)
+{
+ if (vChild._isInTreeQueue)
+ {
+ if (this._treeQueue) {
+ delete this._treeQueue[vChild.toHashCode()];
+ }
+
+ delete vChild._isInTreeQueue;
+ }
+}
+
+qx.Proto.flushWidgetQueue = function() {
+ this.flushTreeQueue();
+}
+
+qx.Proto.flushTreeQueue = function()
+{
+ if (!qx.lang.Object.isEmpty(this._treeQueue))
+ {
+ for (var vHashCode in this._treeQueue)
+ {
+ // this.debug("Flushing Tree Child: " + this._treeQueue[vHashCode]);
+ this._treeQueue[vHashCode].flushTree();
+ delete this._treeQueue[vHashCode]._isInTreeQueue;
+ }
+
+ delete this._treeQueue;
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyUseTreeLines = function(propValue, propOldValue, propData)
+{
+ if (this._initialLayoutDone) {
+ this._updateIndent();
+ }
+
+ return true;
+}
+
+qx.Proto._modifyHideNode = function(propValue, propOldValue, propData)
+{
+ if (! propValue) {
+ this._horizontalLayout.setHeight(this._horizontalLayout.originalHeight);
+ this._horizontalLayout.show();
+ } else {
+ this._horizontalLayout.originalHeight = this._horizontalLayout.getHeight();
+ this._horizontalLayout.setHeight(0);
+ this._horizontalLayout.hide();
+ }
+
+ if (this._initialLayoutDone) {
+ this._updateIndent();
+ }
+
+ return true;
+}
+
+qx.Proto._modifyRootOpenClose = function(propValue, propOldValue, propData)
+{
+ if (this._initialLayoutDone) {
+ this._updateIndent();
+ }
+
+ return true;
+}
+
+// Override getter so we can return a clone of the array. Otherwise, the
+// setter finds the identical array (after user modifications) and the modify
+// function doesn't get called.
+qx.Proto.getExcludeSpecificTreeLines = function()
+{
+ var vName = "excludeSpecificTreeLines";
+ var vUpName = qx.lang.String.toFirstUp(vName);
+ var vStorageField = "_value" + vUpName;
+
+ return this[vStorageField].slice(0);
+}
+
+qx.Proto._modifyExcludeSpecificTreeLines = function(propValue,
+ propOldValue,
+ propData)
+{
+ if (this._initialLayoutDone) {
+ this._updateIndent();
+ }
+
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getTree = function() {
+ return this;
+}
+
+qx.Proto.getParentFolder = function() {
+ return null;
+}
+
+qx.Proto.getLevel = function() {
+ return 0;
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ COMMON CHECKERS
+---------------------------------------------------------------------------
+*/
+
+qx.ui.treefullcontrol.Tree.isTreeFolder = function(vObject) {
+ return (vObject &&
+ vObject instanceof qx.ui.treefullcontrol.TreeFolder &&
+ !(vObject instanceof qx.ui.treefullcontrol.Tree));
+}
+
+qx.ui.treefullcontrol.Tree.isOpenTreeFolder = function(vObject) {
+ return (vObject instanceof qx.ui.treefullcontrol.TreeFolder &&
+ vObject.getOpen() &&
+ vObject.hasContent());
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeydown = function(e)
+{
+ var vManager = this.getManager();
+ var vSelectedItem = vManager.getSelectedItem();
+
+ if (e.getKeyIdentifier() == "Enter")
+ {
+ e.preventDefault();
+ if (qx.ui.treefullcontrol.Tree.isTreeFolder(vSelectedItem)) {
+ return vSelectedItem.toggle();
+ }
+ }
+}
+
+
+qx.Proto._onkeypress = function(e)
+{
+ var vManager = this.getManager();
+ var vSelectedItem = vManager.getSelectedItem();
+
+ switch(e.getKeyIdentifier())
+ {
+ case "Left":
+ e.preventDefault();
+
+ if (qx.ui.treefullcontrol.Tree.isTreeFolder(vSelectedItem))
+ {
+ if (!vSelectedItem.getOpen())
+ {
+ var vParent = vSelectedItem.getParentFolder();
+ if (vParent instanceof qx.ui.treefullcontrol.TreeFolder) {
+ if (!(vParent instanceof qx.ui.treefullcontrol.Tree)) {
+ vParent.close();
+ }
+
+ this.setSelectedElement(vParent);
+ }
+ }
+ else
+ {
+ return vSelectedItem.close();
+ }
+ }
+ else if (vSelectedItem instanceof qx.ui.treefullcontrol.TreeFile)
+ {
+ var vParent = vSelectedItem.getParentFolder();
+ if (vParent instanceof qx.ui.treefullcontrol.TreeFolder) {
+ if (!(vParent instanceof qx.ui.treefullcontrol.Tree)) {
+ vParent.close();
+ }
+
+ this.setSelectedElement(vParent);
+ }
+ }
+
+ break;
+
+ case "Right":
+ e.preventDefault();
+
+ if (qx.ui.treefullcontrol.Tree.isTreeFolder(vSelectedItem))
+ {
+ if (!vSelectedItem.getOpen())
+ {
+ return vSelectedItem.open();
+ }
+ else if (vSelectedItem.hasContent())
+ {
+ var vFirst = vSelectedItem.getFirstVisibleChildOfFolder();
+ this.setSelectedElement(vFirst);
+
+ if (vFirst instanceof qx.ui.tree.TreeFolder) {
+ vFirst.open();
+ }
+
+ return;
+ }
+ }
+
+ break;
+
+ default:
+ if (!this._fastUpdate)
+ {
+ this._fastUpdate = true;
+ this._oldItem = vSelectedItem;
+ }
+
+ vManager.handleKeyPress(e);
+ }
+};
+
+
+qx.Proto._onkeyup = function(e)
+{
+ if (this._fastUpdate)
+ {
+ var vNewItem = this.getManager().getSelectedItem();
+
+ if (! vNewItem) {
+ return;
+ }
+
+ vNewItem.getIconObject().addState("selected");
+
+ delete this._fastUpdate;
+ delete this._oldItem;
+ }
+}
+
+qx.Proto.getLastTreeChild = function()
+{
+ var vLast = this;
+
+ while (vLast instanceof qx.ui.treefullcontrol.AbstractTreeElement)
+ {
+ if (!(vLast instanceof qx.ui.treefullcontrol.TreeFolder) ||
+ !vLast.getOpen()) {
+ return vLast;
+ }
+
+ vLast = vLast.getLastVisibleChildOfFolder();
+ }
+
+ return null;
+}
+
+qx.Proto.getFirstTreeChild = function() {
+ return this;
+}
+
+qx.Proto.setSelectedElement = function(vElement)
+{
+ var vManager = this.getManager();
+
+ vManager.setSelectedItem(vElement);
+ vManager.setLeadItem(vElement);
+}
+
+/* Override getHierarchy: do not add label if root node is hidden */
+qx.Proto.getHierarchy = function(vArr)
+{
+ if (! this.hideNode() && this._labelObject) {
+ vArr.unshift(this._labelObject.getHtml());
+ }
+ return vArr;
+}
+
+
+qx.Proto.getIndentSymbol = function(vUseTreeLines, vColumn, vLastColumn)
+{
+ if (vColumn == vLastColumn &&
+ (this.hasContent() || this.getAlwaysShowPlusMinusSymbol()))
+ {
+ if (! vUseTreeLines)
+ {
+ return this.getOpen() ? "minus" : "plus";
+ }
+ else
+ {
+ return this.getOpen() ? "only_minus" : "only_plus";
+ }
+ }
+ else
+ {
+ return null;
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this.removeEventListener("keydown", this._onkeydown);
+ this.removeEventListener("keypress", this._onkeypress);
+ this.removeEventListener("keyup", this._onkeyup);
+
+ if (this._manager)
+ {
+ this._manager.dispose();
+ this._manager = null;
+ }
+
+ delete this._oldItem;
+
+ return qx.ui.treefullcontrol.TreeFolder.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeFile.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeFile.js
new file mode 100644
index 0000000000..bf38a87c47
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeFile.js
@@ -0,0 +1,81 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+ 2006 by Derrell Lipman
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+ * Derrell Lipman (derrell)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_treefullcontrol)
+
+************************************************************************ */
+
+/**
+ * qx.ui.treefullcontrol.TreeFile objects are terminal tree rows (i.e. no
+ * sub-trees)
+ *
+ * @param
+ * treeRowStructure -
+ * An instance of qx.ui.treefullcontrol.TreeRowStructure, defining the
+ * structure of this tree row.
+ */
+qx.OO.defineClass("qx.ui.treefullcontrol.TreeFile", qx.ui.treefullcontrol.AbstractTreeElement,
+function(treeRowStructure)
+{
+ qx.ui.treefullcontrol.AbstractTreeElement.call(this, treeRowStructure);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INDENT HELPER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getIndentSymbol = function(vUseTreeLines,
+ vColumn,
+ vFirstColumn,
+ vLastColumn)
+{
+ var vLevel = this.getLevel();
+ var vExcludeList = this.getTree().getExcludeSpecificTreeLines();
+ var vExclude = vExcludeList[vLastColumn - vColumn - 1];
+
+ if (vUseTreeLines && ! (vExclude === true))
+ {
+ if (vColumn == vFirstColumn)
+ {
+ return this.isLastChild() ? "end" : "cross";
+ }
+ else
+ {
+ return "line";
+ }
+ }
+
+ return null;
+}
+
+qx.Proto._updateIndent = function() {
+ this.addToTreeQueue();
+}
+
+qx.Proto.getItems = function() {
+ return [this];
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeFolder.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeFolder.js
new file mode 100644
index 0000000000..93a50c27bd
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeFolder.js
@@ -0,0 +1,651 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+ 2006 by Derrell Lipman
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+ * Derrell Lipman (derrell)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_treefullcontrol)
+
+************************************************************************ */
+
+/**
+ * qx.ui.treefullcontrol.TreeFolder objects are tree rows which may contain
+ * sub-trees
+ *
+ * @param
+ * treeRowStructure -
+ * An instance of qx.ui.treefullcontrol.TreeRowStructure, defining the
+ * structure of this tree row.
+ *
+ * @event treeOpenWithContent {qx.event.type.DataEvent}
+ * @event treeOpenWhileEmpty {qx.event.type.DataEvent}
+ * @event treeClose {qx.event.type.DataEvent}
+ */
+qx.OO.defineClass("qx.ui.treefullcontrol.TreeFolder", qx.ui.treefullcontrol.AbstractTreeElement,
+function(treeRowStructure)
+{
+ qx.ui.treefullcontrol.AbstractTreeElement.call(this, treeRowStructure);
+
+ // Save the tree row field order. We'll need it to create children structure.
+ this._treeRowStructureFields = treeRowStructure._fields;
+
+ this._iconObject.setAppearance("tree-folder-icon");
+ this._labelObject.setAppearance("tree-folder-label");
+
+ this.addEventListener("dblclick", this._ondblclick);
+
+ // Remapping of add/remove methods
+ this.add = this.addToFolder;
+ this.addBefore = this.addBeforeToFolder;
+ this.addAfter = this.addAfterToFolder;
+ this.addAt = this.addAtToFolder;
+ this.addAtBegin = this.addAtBeginToFolder;
+ this.addAtEnd = this.addAtEndToFolder;
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+
+qx.OO.changeProperty({ name : "appearance",
+ type : "string",
+ defaultValue : "tree-folder"
+ });
+
+qx.OO.changeProperty({ name : "icon",
+ type : "string"
+ });
+
+qx.OO.changeProperty({ name : "iconSelected",
+ type : "string"
+ });
+
+qx.OO.addProperty({ name : "open",
+ type : "boolean",
+ defaultValue : false
+ });
+
+qx.OO.addProperty({ name : "alwaysShowPlusMinusSymbol",
+ type : "boolean",
+ defaultValue : false
+ });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.hasContent = function() {
+ return (this._containerObject &&
+ this._containerObject.getChildrenLength() > 0);
+}
+
+qx.Proto.open = function()
+{
+ if (this.getOpen()) {
+ return;
+ }
+
+ if (this.hasContent())
+ {
+ // If there are listeners waiting for a treeOpenWithContent event...
+ if (this.getTree().hasEventListeners("treeOpenWithContent")) {
+ // ... then issue the event
+ this.getTree().dispatchEvent(new qx.event.type.DataEvent("treeOpenWithContent", this), true);
+ }
+
+ this.getTopLevelWidget().setGlobalCursor("progress");
+ qx.client.Timer.once(this._openCallback, this, 0);
+ }
+ else
+ {
+ // If there are listeners waiting for a treeOpenWithContent event...
+ if (this.getTree().hasEventListeners("treeOpenWhileEmpty")) {
+ // ... then issue the event
+ this.getTree().dispatchEvent(new qx.event.type.DataEvent("treeOpenWhileEmpty", this), true);
+ }
+
+ this.setOpen(true);
+ }
+}
+
+qx.Proto.close = function()
+{
+ // If there are listeners waiting for a treeClose event...
+ if (this.getTree().hasEventListeners("treeClose")) {
+ // ... then issue the event
+ this.getTree().dispatchEvent(new qx.event.type.DataEvent("treeClose", this), true);
+ }
+
+ this.setOpen(false);
+}
+
+qx.Proto.toggle = function()
+{
+ this.getOpen() ? this.close() : this.open();
+}
+
+qx.Proto._openCallback = function()
+{
+ this.setOpen(true);
+ qx.ui.core.Widget.flushGlobalQueues();
+ this.getTopLevelWidget().setGlobalCursor(null);
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._createChildrenStructure = function()
+{
+ this.setAppearance(this instanceof qx.ui.treefullcontrol.Tree
+ ? "tree-container"
+ : "tree-folder-container");
+
+ if (!this._horizontalLayout)
+ {
+ this.setOrientation("vertical");
+
+ // Create a horizontal layout for this tree row
+ this._horizontalLayout = new qx.ui.layout.HorizontalBoxLayout;
+ this._horizontalLayout.setWidth(null);
+ this._horizontalLayout.setParent(this);
+ this._horizontalLayout.setAnonymous(true);
+ this._horizontalLayout.setAppearance(this instanceof qx.ui.treefullcontrol.Tree
+ ? "tree"
+ : "tree-folder");
+
+ // Move the row fields into the horizontal layout
+ for (var i = 0; i < this._treeRowStructureFields.length; i++)
+ {
+ this._treeRowStructureFields[i].setParent(this._horizontalLayout);
+ }
+
+ // We don't need the tree row structure any more.
+ this._treeRowStructureFields = null;
+ }
+
+ if (!this._containerObject)
+ {
+ // Create a veritcal box layout for all of this folder's children
+ this._containerObject = new qx.ui.layout.VerticalBoxLayout;
+ this._containerObject.setWidth(null);
+ this._containerObject.setAnonymous(true);
+
+ // it should be faster to first handle display,
+ // because the default display value is true and if we first
+ // setup the parent the logic do all to make the
+ // widget first visible and then, if the folder is not
+ // opened again invisible.
+ this._containerObject.setDisplay(this.getOpen());
+ this._containerObject.setParent(this);
+
+ // remap remove* functions
+ this.remapChildrenHandlingTo(this._containerObject);
+ }
+}
+
+qx.Proto._handleChildMove = function(vChild, vRelationIndex, vRelationChild)
+{
+ if (vChild.isDisplayable())
+ {
+ var vChildren = this._containerObject.getChildren();
+ var vOldChildIndex = vChildren.indexOf(vChild);
+
+ if (vOldChildIndex != -1)
+ {
+ if (vRelationChild) {
+ vRelationIndex = vChildren.indexOf(vRelationChild);
+ }
+
+ if (vRelationIndex == vChildren.length-1)
+ {
+ vChild._updateIndent();
+
+ // Update indent of previous last child
+ this._containerObject.getLastVisibleChild()._updateIndent();
+ }
+ else if (vChild._wasLastVisibleChild)
+ {
+ vChild._updateIndent();
+
+ // Update indent for new last child
+ var vPreviousSibling = vChild.getPreviousVisibleSibling();
+ if (vPreviousSibling) {
+ vPreviousSibling._updateIndent();
+ }
+ }
+ }
+ }
+}
+
+qx.Proto.addToFolder = function()
+{
+ this._createChildrenStructure();
+
+ if (this._containerObject) {
+ return this._containerObject.add.apply(this._containerObject, arguments);
+ }
+}
+
+qx.Proto.addBeforeToFolder = function(vChild, vBefore)
+{
+ this._createChildrenStructure();
+
+ if (this._containerObject)
+ {
+ this._handleChildMove(vChild, null, vBefore);
+ return this._containerObject.addBefore.apply(this._containerObject,
+ arguments);
+ }
+}
+
+qx.Proto.addAfterToFolder = function(vChild, vAfter)
+{
+ this._createChildrenStructure();
+
+ if (this._containerObject)
+ {
+ this._handleChildMove(vChild, null, vAfter);
+ return this._containerObject.addAfter.apply(this._containerObject,
+ arguments);
+ }
+}
+
+qx.Proto.addAtToFolder = function(vChild, vIndex)
+{
+ this._createChildrenStructure();
+
+ if (this._containerObject)
+ {
+ this._handleChildMove(vChild, vIndex);
+ return this._containerObject.addAt.apply(this._containerObject, arguments);
+ }
+}
+
+qx.Proto.addAtBeginToFolder = function(vChild) {
+ return this.addAtToFolder(vChild, 0);
+}
+
+qx.Proto.addAtEndToFolder = function(vChild)
+{
+ this._createChildrenStructure();
+
+ if (this._containerObject)
+ {
+ var vLast = this._containerObject.getLastChild();
+
+ if (vLast)
+ {
+ this._handleChildMove(vChild, null, vLast);
+ return this._containerObject.addAfter.call(this._containerObject,
+ vChild,
+ vLast);
+ }
+ else
+ {
+ return this.addAtBeginToFolder(vChild);
+ }
+ }
+}
+
+qx.Proto._remappingChildTable = [ "remove", "removeAt", "removeAll" ];
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getContainerObject = function()
+{
+ return this._containerObject;
+}
+
+qx.Proto.getHorizontalLayout = function()
+{
+ return this._horizontalLayout;
+}
+
+qx.Proto.getFirstVisibleChildOfFolder = function()
+{
+ if (this._containerObject) {
+ return this._containerObject.getFirstChild();
+ }
+}
+
+qx.Proto.getLastVisibleChildOfFolder = function()
+{
+ if (this._containerObject) {
+ return this._containerObject.getLastChild();
+ }
+}
+
+qx.Proto.getItems = function()
+{
+ var a = [this];
+
+ if (this._containerObject)
+ {
+ var ch = this._containerObject.getVisibleChildren();
+
+ for (var i=0, chl=ch.length; i 0) {
+ this._updateIndent();
+ } else {
+ this._updateLastColumn();
+ }
+
+ if (this._containerObject) {
+ this._containerObject.setDisplay(propValue);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyAlwaysShowPlusMinusSymbol = function(propValue, propOldValue, propData)
+{
+ var t = this.getTree();
+ if (t) {
+ // we need the whole indent process if only certain tree lines are to be
+ // excluded
+ if (t.getExcludeSpecificTreeLines().length > 0) {
+ this._updateIndent();
+ } else {
+ this._updateLastColumn();
+ }
+ }
+
+ return true;
+}
+
+qx.Proto._updateLastColumn = function()
+{
+ if (this._indentObject)
+ {
+ var vElement = this._indentObject.getElement();
+
+ if (vElement && vElement.firstChild) {
+ vElement.firstChild.src =
+ (this.BASE_URI +
+ this.getIndentSymbol(this.getTree().getUseTreeLines(), 0, 0, 0) +
+ ".gif");
+ }
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT LISTENERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousedown = function(e)
+{
+ var vOriginalTarget = e.getOriginalTarget();
+
+ switch(vOriginalTarget)
+ {
+ case this._indentObject:
+ if (this._indentObject.getElement().firstChild == e.getDomTarget())
+ {
+ this.getTree().getManager().handleMouseDown(this, e);
+ this.toggle();
+ }
+
+ break;
+
+ case this._containerObject:
+ break;
+
+ case this:
+ if (this._containerObject) {
+ break;
+ }
+
+ // no break here
+
+ default:
+ this.getTree().getManager().handleMouseDown(this, e);
+ }
+
+ e.stopPropagation();
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ var vOriginalTarget = e.getOriginalTarget();
+
+ switch(vOriginalTarget)
+ {
+ case this._indentObject:
+ case this._containerObject:
+ case this:
+ break;
+
+ default:
+ if (!this.getTree().getUseDoubleClick()) {
+ this.open();
+ }
+ }
+}
+
+qx.Proto._ondblclick = function(e)
+{
+ if (!this.getTree().getUseDoubleClick()) {
+ return;
+ }
+
+ this.toggle();
+ e.stopPropagation();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INDENT HELPER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getIndentSymbol = function(vUseTreeLines,
+ vColumn,
+ vFirstColumn,
+ vLastColumn)
+{
+ var vLevel = this.getLevel();
+ var vExcludeList = this.getTree().getExcludeSpecificTreeLines();
+ var vExclude = vExcludeList[vLastColumn - vColumn - 1];
+
+ if (vColumn == vFirstColumn)
+ {
+ if (this.hasContent() || this.getAlwaysShowPlusMinusSymbol())
+ {
+ // If tree lines were not requested, don't display them
+ if (!vUseTreeLines)
+ {
+ return this.getOpen() ? "minus" : "plus";
+ }
+
+
+ // If this is the first level under the root...
+ if (vLevel == 1) {
+ // ... and the root is not being displayed and this is the first
+ // child...
+ var vParentFolder = this.getParentFolder();
+ if (vParentFolder &&
+ !vParentFolder._horizontalLayout.getVisibility() &&
+ this.isFirstChild())
+ {
+ //... then if this is also the last (i.e. only) child, use no tree
+ // lines; otherwise, use descender lines but no ascender.
+ if (this.isLastChild() || vExclude === true)
+ {
+ return this.getOpen() ? "only_minus" : "only_plus";
+ }
+ else
+ {
+ return this.getOpen() ? "start_minus" : "start_plus";
+ }
+ }
+ }
+
+ if (vExclude === true)
+ {
+ return this.getOpen() ? "only_minus" : "only_plus";
+ }
+ else if (this.isLastChild())
+ {
+ return this.getOpen() ? "end_minus" : "end_plus";
+ }
+ else
+ {
+ return this.getOpen() ? "cross_minus" : "cross_plus";
+ }
+ }
+ else if (vUseTreeLines && ! (vExclude === true))
+ {
+ return this.isLastChild() ? "end" : "cross";
+ }
+ }
+ else
+ {
+ if (vUseTreeLines && ! this.isLastChild()) {
+ if (vExclude === true) {
+ return null;
+ }
+ return "line";
+ }
+ return null;
+ }
+}
+
+qx.Proto._updateIndent = function()
+{
+ // Intentionally bypass superclass; the _updateIndent we want is in TreeFile
+ qx.ui.treefullcontrol.TreeFile.prototype._updateIndent.call(this);
+
+ if (!this._containerObject) {
+ return;
+ }
+
+ var ch = this._containerObject.getVisibleChildren();
+ for (var i=0, l=ch.length; i (p - 5) && e < (p + 5);
+}
+
+qx.Proto._onwindowmousemove = function(e)
+{
+ if (!this.getResizeable() || this.getMode() != null) {
+ return;
+ }
+
+ var s = this._resizeSession;
+
+ if (s)
+ {
+ if (this._resizeWest)
+ {
+ s.lastWidth = qx.lang.Number.limit(s.boxWidth + s.boxLeft - Math.max(e.getPageX(), s.parentAreaOffsetLeft), s.minWidth, s.maxWidth);
+ s.lastLeft = s.boxRight - s.lastWidth - s.parentAreaOffsetLeft;
+ }
+ else if (this._resizeEast)
+ {
+ s.lastWidth = qx.lang.Number.limit(Math.min(e.getPageX(), s.parentAreaOffsetRight) - s.boxLeft, s.minWidth, s.maxWidth);
+ }
+
+ if (this._resizeNorth)
+ {
+ s.lastHeight = qx.lang.Number.limit(s.boxHeight + s.boxTop - Math.max(e.getPageY(), s.parentAreaOffsetTop), s.minHeight, s.maxHeight);
+ s.lastTop = s.boxBottom - s.lastHeight - s.parentAreaOffsetTop;
+ }
+ else if (this._resizeSouth)
+ {
+ s.lastHeight = qx.lang.Number.limit(Math.min(e.getPageY(), s.parentAreaOffsetBottom) - s.boxTop, s.minHeight, s.maxHeight);
+ }
+
+ switch(this.getResizeMethod())
+ {
+ case "opaque":
+ case "translucent":
+ if (this._resizeWest || this._resizeEast)
+ {
+ this.setWidth(s.lastWidth);
+
+ if (this._resizeWest) {
+ this.setLeft(s.lastLeft);
+ }
+ }
+
+ if (this._resizeNorth || this._resizeSouth)
+ {
+ this.setHeight(s.lastHeight);
+
+ if (this._resizeNorth) {
+ this.setTop(s.lastTop);
+ }
+ }
+
+ break;
+
+ default:
+ var o = this.getResizeMethod() == "frame" ? this._frame : this;
+
+ if (this._resizeWest || this._resizeEast)
+ {
+ o._applyRuntimeWidth(s.lastWidth);
+
+ if (this._resizeWest) {
+ o._applyRuntimeLeft(s.lastLeft);
+ }
+ }
+
+ if (this._resizeNorth || this._resizeSouth)
+ {
+ o._applyRuntimeHeight(s.lastHeight);
+
+ if (this._resizeNorth) {
+ o._applyRuntimeTop(s.lastTop);
+ }
+ }
+ }
+ }
+ else
+ {
+ var resizeMode = "";
+ var el = this.getElement();
+
+ this._resizeNorth = this._resizeSouth = this._resizeWest = this._resizeEast = false;
+
+ if (this._near(qx.dom.Location.getPageBoxTop(el), e.getPageY()))
+ {
+ resizeMode = "n";
+ this._resizeNorth = true;
+ }
+ else if (this._near(qx.dom.Location.getPageBoxBottom(el), e.getPageY()))
+ {
+ resizeMode = "s";
+ this._resizeSouth = true;
+ }
+
+ if (this._near(qx.dom.Location.getPageBoxLeft(el), e.getPageX()))
+ {
+ resizeMode += "w";
+ this._resizeWest = true;
+ }
+ else if (this._near(qx.dom.Location.getPageBoxRight(el), e.getPageX()))
+ {
+ resizeMode += "e";
+ this._resizeEast = true;
+ }
+
+ if (this._resizeNorth || this._resizeSouth || this._resizeWest || this._resizeEast)
+ {
+ this.setCursor(resizeMode + "-resize");
+ }
+ else
+ {
+ this.setCursor(null);
+ }
+ }
+
+ // stop event
+ e.stopPropagation();
+}
+
+qx.Proto._onwindowclick = function(e)
+{
+ // stop event
+ e.stopPropagation();
+};
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS: BUTTONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onbuttonmousedown = function(e) {
+ e.stopPropagation();
+}
+
+qx.Proto._onminimizebuttonclick = function(e)
+{
+ this.minimize();
+
+ // we need to be sure that the button gets the right states after clicking
+ // because the button will move and does not get the mouseup event anymore
+ this._minimizeButton.removeState("pressed");
+ this._minimizeButton.removeState("abandoned");
+ this._minimizeButton.removeState("over");
+
+ e.stopPropagation();
+}
+
+qx.Proto._onrestorebuttonclick = function(e)
+{
+ this.restore();
+
+ // we need to be sure that the button gets the right states after clicking
+ // because the button will move and does not get the mouseup event anymore
+ this._restoreButton.removeState("pressed");
+ this._restoreButton.removeState("abandoned");
+ this._restoreButton.removeState("over");
+
+ e.stopPropagation();
+}
+
+qx.Proto._onmaximizebuttonclick = function(e)
+{
+ this.maximize();
+
+ // we need to be sure that the button gets the right states after clicking
+ // because the button will move and does not get the mouseup event anymore
+ this._maximizeButton.removeState("pressed");
+ this._maximizeButton.removeState("abandoned");
+ this._maximizeButton.removeState("over");
+
+ e.stopPropagation();
+}
+
+qx.Proto._onclosebuttonclick = function(e)
+{
+ this.close();
+
+ // we need to be sure that the button gets the right states after clicking
+ // because the button will move and does not get the mouseup event anymore
+ this._closeButton.removeState("pressed");
+ this._closeButton.removeState("abandoned");
+ this._closeButton.removeState("over");
+
+ e.stopPropagation();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS: CAPTIONBAR
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._oncaptionmousedown = function(e)
+{
+ if (!e.isLeftButtonPressed() || !this.getMoveable() || this.getMode() != null) {
+ return;
+ }
+
+ // enable capturing
+ this._captionBar.setCapture(true);
+
+ // element cache
+ var el = this.getElement();
+
+ // measuring and caching of values for drag session
+ var pa = this.getParent();
+ var pl = pa.getElement();
+
+ var l = qx.dom.Location.getPageAreaLeft(pl);
+ var t = qx.dom.Location.getPageAreaTop(pl);
+ var r = qx.dom.Location.getPageAreaRight(pl);
+ var b = qx.dom.Location.getPageAreaBottom(pl);
+
+ this._dragSession =
+ {
+ offsetX : e.getPageX() - qx.dom.Location.getPageBoxLeft(el) + l,
+ offsetY : e.getPageY() - qx.dom.Location.getPageBoxTop(el) + t,
+
+ parentAvailableAreaLeft : l + 5,
+ parentAvailableAreaTop : t + 5,
+ parentAvailableAreaRight : r - 5,
+ parentAvailableAreaBottom : b - 5
+ }
+
+ // handle frame and translucently
+ switch(this.getMoveMethod())
+ {
+ case "translucent":
+ this.setOpacity(0.5);
+ break;
+
+ case "frame":
+ var f = this._frame;
+
+ if (f.getParent() != this.getParent())
+ {
+ f.setParent(this.getParent());
+ qx.ui.core.Widget.flushGlobalQueues();
+ }
+
+ f._applyRuntimeLeft(qx.dom.Location.getPageBoxLeft(el) - l);
+ f._applyRuntimeTop(qx.dom.Location.getPageBoxTop(el) - t);
+
+ f._applyRuntimeWidth(qx.dom.Dimension.getBoxWidth(el));
+ f._applyRuntimeHeight(qx.dom.Dimension.getBoxHeight(el));
+
+ f.setZIndex(this.getZIndex() + 1);
+
+ break;
+ }
+}
+
+qx.Proto._oncaptionmouseup = function(e)
+{
+ var s = this._dragSession;
+
+ if (!s) {
+ return;
+ }
+
+ // disable capturing
+ this._captionBar.setCapture(false);
+
+ // move window to last position
+ if (qx.util.Validation.isValidNumber(s.lastX)) {
+ this.setLeft(s.lastX);
+ }
+
+ if (qx.util.Validation.isValidNumber(s.lastY)) {
+ this.setTop(s.lastY);
+ }
+
+ // handle frame and translucently
+ switch(this.getMoveMethod())
+ {
+ case "translucent":
+ this.setOpacity(null);
+ break;
+
+ case "frame":
+ this._frame.setParent(null);
+ break;
+ }
+
+ // cleanup session
+ delete this._dragSession;
+}
+
+qx.Proto._oncaptionmousemove = function(e)
+{
+ var s = this._dragSession;
+
+ // pre check for active session and capturing
+ if (!s || !this._captionBar.getCapture()) {
+ return;
+ }
+
+ // pre check if we go out of the available area
+ if (!qx.lang.Number.isBetweenRange(e.getPageX(), s.parentAvailableAreaLeft, s.parentAvailableAreaRight) || !qx.lang.Number.isBetweenRange(e.getPageY(), s.parentAvailableAreaTop, s.parentAvailableAreaBottom)) {
+ return;
+ }
+
+ // use the fast and direct dom methods
+ var o = this.getMoveMethod() == "frame" ? this._frame : this;
+
+ o._applyRuntimeLeft(s.lastX = e.getPageX() - s.offsetX);
+ o._applyRuntimeTop(s.lastY = e.getPageY() - s.offsetY);
+}
+
+qx.Proto._oncaptiondblblick = function()
+{
+ if (!this._maximizeButton.getEnabled()) {
+ return;
+ }
+
+ return this.getMode() == "maximized" ? this.restore() : this.maximize();
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._layout)
+ {
+ this._layout.dispose();
+ this._layout = null;
+ }
+
+ if (this._frame)
+ {
+ this._frame.dispose();
+ this._frame = null;
+ }
+
+ if (this._captionBar)
+ {
+ this._captionBar.dispose();
+ this._captionBar = null;
+ }
+
+ if (this._captionIcon)
+ {
+ this._captionIcon.dispose();
+ this._captionIcon = null;
+ }
+
+ if (this._captionTitle)
+ {
+ this._captionTitle.dispose();
+ this._captionTitle = null;
+ }
+
+ if (this._captionFlex)
+ {
+ this._captionFlex.dispose();
+ this._captionFlex = null;
+ }
+
+ if (this._closeButton)
+ {
+ this._closeButton.dispose();
+ this._closeButton = null;
+ }
+
+ if (this._minimizeButton)
+ {
+ this._minimizeButton.dispose();
+ this._minimizeButton = null;
+ }
+
+ if (this._maximizeButton)
+ {
+ this._maximizeButton.dispose();
+ this._maximizeButton = null;
+ }
+
+ if (this._restoreButton)
+ {
+ this._restoreButton.dispose();
+ this._restoreButton = null;
+ }
+
+ if (this._pane)
+ {
+ this._pane.dispose();
+ this._pane = null;
+ }
+
+ if (this._statusBar)
+ {
+ this._statusBar.dispose();
+ this._statusBar = null;
+ }
+
+ if (this._statusText)
+ {
+ this._statusText.dispose();
+ this._statusText = null;
+ }
+
+ return qx.ui.popup.Popup.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/ColorUtil.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/ColorUtil.js
new file mode 100644
index 0000000000..3a8406f029
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/ColorUtil.js
@@ -0,0 +1,162 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.util.ColorUtil");
+
+qx.Class.rgb2hsb = function(vRed, vGreen, vBlue)
+{
+ var vHue, vSaturation, vBrightness;
+
+ vRed = parseFloat(vRed);
+ vGreen = parseFloat(vGreen);
+ vBlue = parseFloat(vBlue);
+
+ var cmax = (vRed > vGreen) ? vRed : vGreen;
+ if (vBlue > cmax) {
+ cmax = vBlue;
+ }
+
+ var cmin = (vRed < vGreen) ? vRed : vGreen;
+ if (vBlue < cmin) {
+ cmin = vBlue;
+ }
+
+ vBrightness = cmax / 255.0;
+
+ if (cmax != 0)
+ {
+ vSaturation = (cmax - cmin) / cmax;
+ }
+ else
+ {
+ vSaturation = 0;
+ }
+
+ if (vSaturation == 0)
+ {
+ vHue = 0;
+ }
+ else
+ {
+ var redc = (cmax - vRed) / (cmax - cmin);
+ var greenc = (cmax - vGreen) / (cmax - cmin);
+ var bluec = (cmax - vBlue) / (cmax - cmin);
+
+ if (vRed == cmax)
+ {
+ vHue = bluec - greenc;
+ }
+ else if (vGreen == cmax)
+ {
+ vHue = 2.0 + redc - bluec;
+ }
+ else
+ {
+ vHue = 4.0 + greenc - redc;
+ }
+
+ vHue = vHue / 6.0;
+ if (vHue < 0) vHue = vHue + 1.0;
+ }
+
+ return {
+ hue : Math.round(vHue * 360),
+ saturation : Math.round(vSaturation * 100),
+ brightness : Math.round(vBrightness * 100)
+ }
+}
+
+qx.Class.hsb2rgb = function(vHue, vSaturation, vBrightness)
+{
+ var i, f, p, q, t, vReturn;
+
+ vHue = parseFloat(vHue/360);
+ vSaturation = parseFloat(vSaturation/100);
+ vBrightness = parseFloat(vBrightness/100);
+
+ if(vHue >= 1.0) vHue %= 1.0;
+ if(vSaturation > 1.0) vSaturation = 1.0;
+ if(vBrightness > 1.0) vBrightness = 1.0;
+
+ var tov = Math.floor(255 * vBrightness);
+
+ var vReturn = {};
+
+ if(vSaturation == 0.0)
+ {
+ vReturn.red = vReturn.green = vReturn.blue = tov;
+ }
+ else
+ {
+ vHue *= 6.0;
+
+ i = Math.floor(vHue);
+
+ f = vHue - i;
+
+ p = Math.floor(tov * (1.0 - vSaturation));
+ q = Math.floor(tov * (1.0 - (vSaturation * f)));
+ t = Math.floor(tov * (1.0 - (vSaturation * (1.0 - f))));
+
+ switch(i)
+ {
+ case 0:
+ vReturn.red = tov;
+ vReturn.green = t;
+ vReturn.blue = p;
+ break;
+
+ case 1:
+ vReturn.red = q;
+ vReturn.green = tov;
+ vReturn.blue = p;
+ break;
+
+ case 2:
+ vReturn.red = p;
+ vReturn.green = tov;
+ vReturn.blue = t;
+ break;
+
+ case 3:
+ vReturn.red = p;
+ vReturn.green = q;
+ vReturn.blue = tov;
+ break;
+
+ case 4:
+ vReturn.red = t;
+ vReturn.green = p;
+ vReturn.blue = tov;
+ break;
+
+ case 5:
+ vReturn.red = tov;
+ vReturn.green = p;
+ vReturn.blue = q;
+ break;
+ }
+ }
+
+ return vReturn;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/Compare.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/Compare.js
new file mode 100644
index 0000000000..3de325d717
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/Compare.js
@@ -0,0 +1,86 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.util.Compare");
+
+qx.util.Compare.byString = function(a, b) {
+ return a==b ? 0 : a > b ? 1 : -1;
+}
+
+qx.util.Compare.byStringCaseInsensitive = function(a, b) {
+ return qx.util.Compare.byString(a.toLowerCase(), b.toLowerCase());
+}
+
+qx.util.Compare.byStringUmlautsShort = function(a, b) {
+ return qx.util.Compare.byString(qx.util.Normalization.umlautsShort(a), qx.util.Normalization.umlautsShort(b));
+}
+
+qx.util.Compare.byStringUmlautsShortCaseInsensitive = function(a, b) {
+ return qx.util.Compare.byString(qx.util.Normalization.umlautsShort(a).toLowerCase(), qx.util.Normalization.umlautsShort(b).toLowerCase());
+}
+
+qx.util.Compare.byStringUmlautsLong = function(a, b) {
+ return qx.util.Compare.byString(qx.util.Normalization.umlautsLong(a), qx.util.Normalization.umlautsLong(b));
+}
+
+qx.util.Compare.byStringUmlautsLongCaseInsensitive = function(a, b) {
+ return qx.util.Compare.byString(qx.util.Normalization.umlautsLong(a).toLowerCase(), qx.util.Normalization.umlautsLong(b).toLowerCase());
+}
+
+qx.util.Compare.byFloat = function(a, b) {
+ return a - b;
+}
+
+qx.util.Compare.byInteger = qx.util.Compare.byNumber = qx.util.Compare.byFloat;
+
+qx.util.Compare.byIntegerString = function(a, b) {
+ return parseInt(a) - parseInt(b);
+}
+
+qx.util.Compare.byFloatString = function(a, b) {
+ return parseFloat(a) - parseFloat(b);
+}
+
+qx.util.Compare.byNumberString = qx.util.Compare.byFloatString;
+
+qx.util.Compare.byIPv4 = function(a, b)
+{
+ var ipa = a.split(".", 4);
+ var ipb = b.split(".", 4);
+
+ for (var i=0; i<3; i++)
+ {
+ a = parseInt(ipa[i]);
+ b = parseInt(ipb[i]);
+
+ if (a != b) {
+ return a - b;
+ }
+ }
+
+ return parseInt(ipa[3]) - parseInt(ipb[3]);
+}
+
+qx.util.Compare.byZIndex = function(a, b) {
+ return a.getZIndex() - b.getZIndex();
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/FormUtil.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/FormUtil.js
new file mode 100644
index 0000000000..2d4913008d
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/FormUtil.js
@@ -0,0 +1,109 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(io_remote)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.util.FormUtil");
+
+qx.Class.ignoreInputTypes = [ "file", "submit", "image", "reset", "button" ];
+qx.Class.ignoreElementTypes = [ "fieldset" ];
+qx.Class.checkElementTypes = [ "radio", "checkbox" ];
+qx.Class.multiSelectType = "select-multiple";
+
+qx.Class.inputFilter = function(vNode)
+{
+ if (vNode.disabled) {
+ return false;
+ }
+
+ var vTag = (vNode.tagName || "").toLowerCase();
+
+ if (qx.lang.Array.contains(qx.util.FormUtil.ignoreElementTypes, vTag)) {
+ return false;
+ }
+
+ var vType = vNode.type.toLowerCase();
+
+ if (qx.lang.Array.contains(qx.util.FormUtil.ignoreInputTypes, vType)) {
+ return false;
+ }
+
+ if (!vNode.checked && qx.lang.Array.contains(qx.util.FormUtil.checkElementTypes, vType)) {
+ return false;
+ }
+
+ return true;
+}
+
+qx.Class.getFields = function(vForm) {
+ return Array.filter(vForm.elements, qx.util.FormUtil.inputFilter);
+}
+
+qx.Class.encodeField = function(vNode)
+{
+ var vName = vNode.name || "";
+ var vType = (vNode.type || "").toLowerCase();
+
+ if(vType === qx.util.FormUtil.multiSelectType)
+ {
+ var vValues = [];
+
+ for(var i=0; i"+"$1"+""+htag+">");
+ }
+
+ // underscores count as part of a word, so do them separately
+ re = new RegExp("\\b_(.+?)_\\b","g");
+ r = r.replace(re,"$1 ");
+
+ // jeff: so do dashes
+ re = new RegExp("[\s\n]-(.+?)-[\s\n]","g");
+ r = r.replace(re,"$1");
+
+ // links
+ re = new RegExp('"\\b(.+?)\\(\\b(.+?)\\b\\)":([^\\s]+)','g');
+ r = r.replace(re,'$1 ');
+ re = new RegExp('"\\b(.+?)\\b":([^\\s]+)','g');
+ r = r.replace(re,'$1 ');
+
+ // images
+ re = new RegExp("!\\b(.+?)\\(\\b(.+?)\\b\\)!","g");
+ r = r.replace(re,' ');
+ re = new RegExp("!\\b(.+?)\\b!","g");
+ r = r.replace(re,' ');
+
+ // block level formatting
+
+ // Jeff's hack to show single line breaks as they should.
+ // insert breaks - but you get some....stupid ones
+ re = new RegExp("(.*)\n([^#\*\n].*)","g");
+ r = r.replace(re,"$1 $2");
+
+ // remove the stupid breaks.
+ re = new RegExp("\n ","g");
+ r = r.replace(re,"\n");
+
+ lines = r.split("\n");
+ nr = "";
+
+ for (var i=0;i")+"";
+ changed = 1;
+ }
+
+ // jeff adds h#.
+ if (line.search(/^\s*h[1-6]\.\s+/) != -1)
+ {
+ re = new RegExp("h([1-6])\.(.+)","g");
+ line = line.replace(re,"$2 ");
+ changed = 1;
+ }
+
+ if (line.search(/^\s*\*\s+/) != -1)
+ {
+ // for bullet list; make up an liu tag to be fixed later
+ line = line.replace(/^\s*\*\s+/,"\t") + " ";
+ changed = 1;
+ }
+
+ if (line.search(/^\s*#\s+/) != -1)
+ {
+ // # for numeric list; make up an lio tag to be fixed later
+ line = line.replace(/^\s*#\s+/,"\t") + " ";
+ changed = 1;
+ }
+
+ if (!changed && (line.replace(/\s/g,"").length > 0))
+ {
+ line = ""+line+"
";
+ }
+
+ lines[i] = line + "\n";
+ }
+
+ // Second pass to do lists
+ inlist = 0;
+ listtype = "";
+
+ for (var i=0;i AND
+ r = r.replace(/li[o|u]>/g, "li>");
+
+ return r;
+}
\ No newline at end of file
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/Validation.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/Validation.js
new file mode 100644
index 0000000000..1fadd1d686
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/Validation.js
@@ -0,0 +1,172 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(core)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.util.Validation");
+
+/*
+ All methods use the strict comparison operators as all modern
+ browsers (needs support for JavaScript 1.3) seems to support this.
+
+ http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Operators:Comparison_Operators
+*/
+
+qx.util.Validation.isValid = function(v)
+{
+ switch(typeof v)
+ {
+ case "undefined":
+ return false;
+
+ case "object":
+ return v !== null;
+
+ case "string":
+ return v !== "";
+
+ case "number":
+ return !isNaN(v);
+
+ case "function":
+ case "boolean":
+ return true;
+ }
+
+ return false;
+}
+
+qx.util.Validation.isInvalid = function(v)
+{
+ switch(typeof v)
+ {
+ case "undefined":
+ return true;
+
+ case "object":
+ return v === null;
+
+ case "string":
+ return v === "";
+
+ case "number":
+ return isNaN(v);
+
+ case "function":
+ case "boolean":
+ return false;
+ }
+
+ return true;
+}
+
+qx.util.Validation.isValidNumber = function(v) {
+ return typeof v === "number" && !isNaN(v);
+}
+
+qx.util.Validation.isInvalidNumber = function(v) {
+ return typeof v !== "number" || isNaN(v);
+}
+
+qx.util.Validation.isValidString = function(v) {
+ return typeof v === "string" && v !== "";
+}
+
+qx.util.Validation.isInvalidString = function(v) {
+ return typeof v !== "string" || v === "";
+}
+
+qx.util.Validation.isValidArray = function(v) {
+ return typeof v === "object" && v !== null && v instanceof Array;
+}
+
+qx.util.Validation.isInvalidArray = function(v) {
+ return typeof v !== "object" || v === null || !(v instanceof Array);
+}
+
+qx.util.Validation.isValidObject = function(v) {
+ return typeof v === "object" && v !== null && !(v instanceof Array);
+}
+
+qx.util.Validation.isInvalidObject = function(v) {
+ return typeof v !== "object" || v === null || v instanceof Array;
+}
+
+qx.util.Validation.isValidNode = function(v) {
+ return typeof v === "object" && v !== null;
+}
+
+qx.util.Validation.isInvalidNode = function(v) {
+ return typeof v !== "object" || v === null;
+}
+
+qx.util.Validation.isValidElement = function(v) {
+ return typeof v === "object" && v !== null || v.nodeType !== 1;
+}
+
+qx.util.Validation.isInvalidElement = function(v) {
+ return typeof v !== "object" || v === null || v.nodeType !== 1;
+}
+
+qx.util.Validation.isValidFunction = function(v) {
+ return typeof v === "function";
+}
+
+qx.util.Validation.isInvalidFunction = function(v) {
+ return typeof v !== "function";
+}
+
+qx.util.Validation.isValidBoolean = function(v) {
+ return typeof v === "boolean";
+}
+
+qx.util.Validation.isInvalidBoolean = function(v) {
+ return typeof v !== "boolean";
+}
+
+qx.util.Validation.isValidStringOrNumber = function(v)
+{
+ switch(typeof v)
+ {
+ case "string":
+ return v !== "";
+
+ case "number":
+ return !isNaN(v);
+ }
+
+ return false;
+}
+
+qx.util.Validation.isInvalidStringOrNumber = function(v)
+{
+ switch(typeof v)
+ {
+ case "string":
+ return v === "";
+
+ case "number":
+ return isNaN(v);
+ }
+
+ return false;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/format/DateFormat.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/format/DateFormat.js
new file mode 100644
index 0000000000..7460ea4467
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/format/DateFormat.js
@@ -0,0 +1,614 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+/**
+ * A formatter and parser for dates
+ *
+ * @param format {string} The format to use. If null, the
+ * {@link #DEFAULT_DATE_TIME_FORMAT} is used.
+ */
+qx.OO.defineClass("qx.util.format.DateFormat", qx.util.format.Format,
+function(format) {
+ qx.util.format.Format.call(this);
+
+ this._format = (format != null) ? format : qx.util.format.DateFormat.DEFAULT_DATE_TIME_FORMAT;
+});
+
+
+/**
+ * Fills a number with leading zeros ("25" -> "0025").
+ *
+ * @param number {int} the number to fill.
+ * @param minSize {int} the minimum size the returned string should have.
+ * @return {string} the filled number as string.
+ */
+qx.Proto._fillNumber = function(number, minSize) {
+ var str = "" + number;
+ while (str.length < minSize) {
+ str = "0" + str;
+ }
+ return str;
+}
+
+
+/**
+ * Returns the day in year of a date.
+ *
+ * @param date {Date} the date.
+ * @return {int} the day in year.
+ */
+qx.Proto._getDayInYear = function(date) {
+ var helpDate = new Date(date.getTime());
+ var day = helpDate.getDate();
+ while (helpDate.getMonth() != 0) {
+ // Set the date to the last day of the previous month
+ helpDate.setDate(-1);
+ day += helpDate.getDate() + 1;
+ }
+ return day;
+}
+
+
+/**
+ * Returns the thursday in the same week as the date.
+ *
+ * @param date {Date} the date to get the thursday of.
+ * @return {Date} the thursday in the same week as the date.
+ */
+qx.Proto._thursdayOfSameWeek = function(date) {
+ return new Date(date.getTime() + (3 - ((date.getDay() + 6) % 7)) * 86400000);
+}
+
+
+/**
+ * Returns the week in year of a date.
+ *
+ * @param date {Date} the date to get the week in year of.
+ * @return {int} the week in year.
+ */
+qx.Proto._getWeekInYear = function(date) {
+ // This algorithm gets the correct calendar week after ISO 8601.
+ // This standard is used in almost all european countries.
+ // TODO: In the US week in year is calculated different!
+ // See http://www.merlyn.demon.co.uk/weekinfo.htm
+
+ // The following algorithm comes from http://www.salesianer.de/util/kalwoch.html
+
+ // Get the thursday of the week the date belongs to
+ var thursdayDate = this._thursdayOfSameWeek(date);
+ // Get the year the thursday (and therefor the week) belongs to
+ var weekYear = thursdayDate.getFullYear();
+ // Get the thursday of the week january 4th belongs to
+ // (which defines week 1 of a year)
+ var thursdayWeek1 = this._thursdayOfSameWeek(new Date(weekYear, 0, 4));
+ // Calculate the calendar week
+ return Math.floor(1.5 + (thursdayDate.getTime() - thursdayWeek1.getTime()) / 86400000 / 7)
+}
+
+
+/**
+ * Formats a date.
+ *
+ * Uses the same syntax as
+ *
+ * the SimpleDateFormat class in Java .
+ *
+ * @param date {Date} The date to format.
+ * @return {string} the formatted date.
+ */
+qx.Proto.format = function(date) {
+ var DateFormat = qx.util.format.DateFormat;
+
+ var fullYear = date.getFullYear();
+ var month = date.getMonth();
+ var dayOfMonth = date.getDate();
+ var dayOfWeek = date.getDay();
+ var hours = date.getHours();
+ var minutes = date.getMinutes();
+ var seconds = date.getSeconds();
+ var ms = date.getMilliseconds();
+ var timezone = date.getTimezoneOffset() / 60;
+
+ // Create the output
+ this._initFormatTree();
+ var output = "";
+ for (var i = 0; i < this._formatTree.length; i++) {
+ var currAtom = this._formatTree[i];
+
+ if (currAtom.type == "literal") {
+ output += currAtom.text;
+ } else {
+ // This is a wildcard
+ var wildcardChar = currAtom.character;
+ var wildcardSize = currAtom.size;
+
+ // Get its replacement
+ var replacement = "?";
+ switch (wildcardChar) {
+ // TODO: G - Era designator (e.g. AD). Problem: Not covered by JScript Date class
+ // TODO: W - Week in month (e.g. 2)
+ // TODO: F - Day of week in month (e.g. 2). Problem: What is this?
+
+ case 'y': // Year
+ if (wildcardSize == 2) {
+ replacement = this._fillNumber(fullYear % 100, 2);
+ } else if (wildcardSize == 4) {
+ replacement = fullYear;
+ }
+ break;
+ case 'D': // Day in year (e.g. 189)
+ replacement = this._fillNumber(this._getDayInYear(date), wildcardSize); break;
+ case 'd': // Day in month
+ replacement = this._fillNumber(dayOfMonth, wildcardSize); break;
+ case 'w': // Week in year (e.g. 27)
+ replacement = this._fillNumber(this._getWeekInYear(date), wildcardSize); break;
+ case 'E': // Day in week
+ if (wildcardSize == 2) {
+ replacement = DateFormat.SHORT_DAY_OF_WEEK_NAMES[dayOfWeek];
+ } else if (wildcardSize == 3) {
+ replacement = DateFormat.MEDIUM_DAY_OF_WEEK_NAMES[dayOfWeek];
+ } else if (wildcardSize == 4) {
+ replacement = DateFormat.FULL_DAY_OF_WEEK_NAMES[dayOfWeek];
+ }
+ break;
+ case 'M': // Month
+ if (wildcardSize == 1 || wildcardSize == 2) {
+ replacement = this._fillNumber(month + 1, wildcardSize);
+ } else if (wildcardSize == 3) {
+ replacement = DateFormat.SHORT_MONTH_NAMES[month];
+ } else if (wildcardSize == 4) {
+ replacement = DateFormat.FULL_MONTH_NAMES[month];
+ }
+ break;
+ case 'a': // am/pm marker
+ // NOTE: 0:00 is am, 12:00 is pm
+ replacement = (hours < 12) ? DateFormat.AM_MARKER : DateFormat.PM_MARKER; break;
+ case 'H': // Hour in day (0-23)
+ replacement = this._fillNumber(hours, wildcardSize); break;
+ case 'k': // Hour in day (1-24)
+ replacement = this._fillNumber((hours == 0) ? 24 : hours, wildcardSize); break;
+ case 'K': // Hour in am/pm (0-11)
+ replacement = this._fillNumber(hours % 12, wildcardSize); break;
+ case 'h': // Hour in am/pm (1-12)
+ replacement = this._fillNumber(((hours % 12) == 0) ? 12 : (hours % 12), wildcardSize); break;
+ case 'm': // Minute in hour
+ replacement = this._fillNumber(minutes, wildcardSize); break;
+ case 's': // Second in minute
+ replacement = this._fillNumber(seconds, wildcardSize); break;
+ case 'S': // Millisecond
+ replacement = this._fillNumber(ms, wildcardSize); break;
+ case 'z': // Time zone
+ if (wildcardSize == 1) {
+ replacement = "GMT" + ((timezone < 0) ? "-" : "+") + this._fillNumber(timezone) + ":00";
+ } else if (wildcardSize == 2) {
+ replacement = DateFormat.MEDIUM_TIMEZONE_NAMES[timezone];
+ } else if (wildcardSize == 3) {
+ replacement = DateFormat.FULL_TIMEZONE_NAMES[timezone];
+ }
+ break;
+ case 'Z': // RFC 822 time zone
+ replacement = ((timezone < 0) ? "-" : "+") + this._fillNumber(timezone, 2) + "00";
+ }
+ output += replacement;
+ }
+ }
+
+ return output;
+}
+
+
+/**
+ * Parses a date.
+ *
+ * Uses the same syntax as
+ *
+ * the SimpleDateFormat class in Java .
+ *
+ * @param dateStr {string} the date to parse.
+ * @return {Date} the parsed date.
+ * @throws If the format is not well formed or if the date string does not
+ * match to the format.
+ */
+qx.Proto.parse = function(dateStr) {
+ this._initParseFeed();
+
+ // Apply the regex
+ var hit = this._parseFeed.regex.exec(dateStr);
+ if (hit == null) {
+ throw new Error("Date string '" + dateStr + "' does not match the date format: " + this._format);
+ }
+
+ // Apply the rules
+ var dateValues = { year:1970, month:0, day:1, hour:0, ispm:false, min:0, sec:0, ms:0 }
+ var currGroup = 1;
+ for (var i = 0; i < this._parseFeed.usedRules.length; i++) {
+ var rule = this._parseFeed.usedRules[i];
+
+ var value = hit[currGroup];
+ if (rule.field != null) {
+ dateValues[rule.field] = parseInt(value, 10);
+ } else {
+ rule.manipulator(dateValues, value);
+ }
+
+ currGroup += (rule.groups == null) ? 1 : rule.groups;
+ }
+
+ var date = new Date(dateValues.year, dateValues.month, dateValues.day,
+ (dateValues.ispm) ? (dateValues.hour + 12) : dateValues.hour,
+ dateValues.min, dateValues.sec, dateValues.ms);
+ if (dateValues.month != date.getMonth() || dateValues.year != date.getFullYear()) {
+ // TODO: check if this is also necessary for the time components
+ throw new Error("Error parsing date '" + dateStr + "': the value for day or month is too large");
+ }
+
+ return date;
+}
+
+
+
+/**
+ * Helper method for {@link #format()} and {@link #parse()}.
+ * Parses the date format.
+ */
+qx.Proto._initFormatTree = function() {
+ if (this._formatTree != null) {
+ return;
+ }
+
+ this._formatTree = [];
+
+ var currWildcardChar;
+ var currWildcardSize;
+ var currLiteral = "";
+ var format = this._format;
+ for (var i = 0; i < format.length; i++) {
+ var currChar = format.charAt(i);
+
+ // Check whether we are currently in a wildcard
+ if (currWildcardChar != null) {
+ // Check whether the currChar belongs to that wildcard
+ if (currChar == currWildcardChar) {
+ // It does -> Raise the size
+ currWildcardSize++;
+ } else {
+ // It does not -> The current wildcard is done
+ this._formatTree.push({ type:"wildcard", character:currWildcardChar, size:currWildcardSize });
+ currWildcardChar = null;
+ }
+ }
+
+ if (currWildcardChar == null) {
+ // We are not (any more) in a wildcard -> Check what's starting here
+ if ((currChar >= 'a' && currChar <= 'z') || (currChar >= 'A' && currChar <= 'Z')) {
+ // This is a letter -> All letters are wildcards
+
+ // Add the literal
+ if (currLiteral.length > 0) {
+ this._formatTree.push({ type:"literal", text:currLiteral });
+ currLiteral = "";
+ }
+
+ // Start a new wildcard
+ currWildcardChar = currChar;
+ currWildcardSize = 1;
+ } else {
+ // This is a literal -> Add it to the current literal
+ currLiteral += currChar;
+ }
+ }
+ }
+
+ // Add the last wildcard or literal
+ if (currWildcardChar != null) {
+ this._formatTree.push({ type:"wildcard", character:currWildcardChar, size:currWildcardSize });
+ } else if (currLiteral.length > 0) {
+ this._formatTree.push({ type:"literal", text:currLiteral });
+ }
+}
+
+
+/**
+ * Initializes the parse feed.
+ *
+ * The parse contains everything needed for parsing: The regular expression
+ * (in compiled and uncompiled form) and the used rules.
+ *
+ * @return {Map} the parse feed.
+ */
+qx.Proto._initParseFeed = function() {
+ if (this._parseFeed != null) {
+ // We already have the farse feed
+ return;
+ }
+
+ var DateFormat = qx.util.format.DateFormat;
+
+ // Initialize the rules
+ this._initParseRules();
+ this._initFormatTree();
+
+ // Get the used rules and construct the regex pattern
+ var usedRules = [];
+ var pattern = "^";
+ for (var atomIdx = 0; atomIdx < this._formatTree.length; atomIdx++) {
+ var currAtom = this._formatTree[atomIdx];
+
+ if (currAtom.type == "literal") {
+ pattern += qx.lang.String.escapeRegexpChars(currAtom.text);
+ } else {
+ // This is a wildcard
+ var wildcardChar = currAtom.character;
+ var wildcardSize = currAtom.size;
+
+ // Get the rule for this wildcard
+ var wildcardRule;
+ for (var ruleIdx = 0; ruleIdx < DateFormat._parseRules.length; ruleIdx++) {
+ var rule = DateFormat._parseRules[ruleIdx];
+ if (wildcardChar == rule.pattern.charAt(0) && wildcardSize == rule.pattern.length) {
+ // We found the right rule for the wildcard
+ wildcardRule = rule;
+ break;
+ }
+ }
+
+ // Check the rule
+ if (wildcardRule == null) {
+ // We have no rule for that wildcard -> Malformed date format
+ var wildcardStr = "";
+ for (var i = 0; i < wildcardSize; i++) {
+ wildcardStr += wildcardChar;
+ }
+ throw new Error("Malformed date format: " + format + ". Wildcard "
+ + wildcardStr + " is not supported");
+ } else {
+ // Add the rule to the pattern
+ usedRules.push(wildcardRule);
+ pattern += wildcardRule.regex;
+ }
+ }
+ }
+ pattern += "$";
+
+ // Create the regex
+ var regex;
+ try {
+ regex = new RegExp(pattern);
+ }
+ catch (exc) {
+ throw new Error("Malformed date format: " + format);
+ }
+
+ // Create the this._parseFeed
+ this._parseFeed = { regex:regex, "usedRules":usedRules, pattern:pattern }
+}
+
+
+/**
+ * Initializes the static parse rules.
+ */
+qx.Proto._initParseRules = function() {
+ var DateFormat = qx.util.format.DateFormat;
+
+ if (DateFormat._parseRules != null) {
+ // The parse rules are already initialized
+ return;
+ }
+
+ DateFormat._parseRules = [];
+
+ var yearManipulator = function(dateValues, value) {
+ value = parseInt(value, 10);
+ if (value < DateFormat.ASSUME_YEAR_2000_THRESHOLD) {
+ value += 2000;
+ } else if (value < 100) {
+ value += 1900;
+ }
+
+ dateValues.year = value;
+ }
+
+ var monthManipulator = function(dateValues, value) {
+ dateValues.month = parseInt(value, 10) - 1;
+ }
+
+ var ampmManipulator = function(dateValues, value) {
+ dateValues.ispm = (value == DateFormat.PM_MARKER);
+ }
+
+ var noZeroHourManipulator = function(dateValues, value) {
+ dateValues.hour = parseInt(value, 10) % 24;
+ }
+
+ var noZeroAmPmHourManipulator = function(dateValues, value) {
+ dateValues.hour = parseInt(value, 10) % 12;
+ }
+
+ // Unsupported: w (Week in year), W (Week in month), D (Day in year),
+ // F (Day of week in month), z (time zone) reason: no setter in Date class,
+ // Z (RFC 822 time zone) reason: no setter in Date class
+
+ DateFormat._parseRules.push({ pattern:"yyyy", regex:"(\\d\\d(\\d\\d)?)",
+ groups:2, manipulator:yearManipulator } );
+ DateFormat._parseRules.push({ pattern:"yy", regex:"(\\d\\d)", manipulator:yearManipulator } );
+ // TODO: "MMMM", "MMM" (Month names)
+ DateFormat._parseRules.push({ pattern:"MM", regex:"(\\d\\d?)", manipulator:monthManipulator });
+ DateFormat._parseRules.push({ pattern:"dd", regex:"(\\d\\d?)", field:"day" });
+ DateFormat._parseRules.push({ pattern:"d", regex:"(\\d\\d?)", field:"day" });
+ // TODO: "EEEE", "EEE", "EE" (Day in week names)
+ DateFormat._parseRules.push({ pattern:"a",
+ regex:"(" + DateFormat.AM_MARKER + "|" + DateFormat.PM_MARKER + ")",
+ manipulator:ampmManipulator });
+ DateFormat._parseRules.push({ pattern:"HH", regex:"(\\d\\d?)", field:"hour" });
+ DateFormat._parseRules.push({ pattern:"H", regex:"(\\d\\d?)", field:"hour" });
+ DateFormat._parseRules.push({ pattern:"kk", regex:"(\\d\\d?)", manipulator:noZeroHourManipulator });
+ DateFormat._parseRules.push({ pattern:"k", regex:"(\\d\\d?)", manipulator:noZeroHourManipulator });
+ DateFormat._parseRules.push({ pattern:"KK", regex:"(\\d\\d?)", field:"hour" });
+ DateFormat._parseRules.push({ pattern:"K", regex:"(\\d\\d?)", field:"hour" });
+ DateFormat._parseRules.push({ pattern:"hh", regex:"(\\d\\d?)", manipulator:noZeroAmPmHourManipulator });
+ DateFormat._parseRules.push({ pattern:"h", regex:"(\\d\\d?)", manipulator:noZeroAmPmHourManipulator });
+ DateFormat._parseRules.push({ pattern:"mm", regex:"(\\d\\d?)", field:"min" });
+ DateFormat._parseRules.push({ pattern:"m", regex:"(\\d\\d?)", field:"min" });
+ DateFormat._parseRules.push({ pattern:"ss", regex:"(\\d\\d?)", field:"sec" });
+ DateFormat._parseRules.push({ pattern:"s", regex:"(\\d\\d?)", field:"sec" });
+ DateFormat._parseRules.push({ pattern:"SSS", regex:"(\\d\\d?\\d?)", field:"ms" });
+ DateFormat._parseRules.push({ pattern:"SS", regex:"(\\d\\d?\\d?)", field:"ms" });
+ DateFormat._parseRules.push({ pattern:"S", regex:"(\\d\\d?\\d?)", field:"ms" });
+}
+
+
+/**
+ * Returns a DateFomat
instance that uses the
+ * {@link #DEFAULT_DATE_TIME_FORMAT}.
+ *
+ * @return {string} the date/time instance.
+ */
+qx.Class.getDateTimeInstance = function() {
+ var DateFormat = qx.util.format.DateFormat;
+
+ if (DateFormat._dateTimeInstance == null) {
+ DateFormat._dateTimeInstance = new DateFormat();
+ }
+ return DateFormat._dateTimeInstance;
+}
+
+
+/**
+ * Returns a DateFomat
instance that uses the
+ * {@link #DEFAULT_DATE_FORMAT}.
+ *
+ * @return {string} the date instance.
+ */
+qx.Class.getDateInstance = function() {
+ var DateFormat = qx.util.format.DateFormat;
+
+ if (DateFormat._dateInstance == null) {
+ DateFormat._dateInstance = new DateFormat(DateFormat.DEFAULT_DATE_FORMAT);
+ }
+ return DateFormat._dateInstance;
+}
+
+
+/**
+ * (int) The threshold until when a year should be assumed to belong to the
+ * 21st century (e.g. 12 -> 2012). Years over this threshold but below 100 will be
+ * assumed to belong to the 20th century (e.g. 88 -> 1988). Years over 100 will be
+ * used unchanged (e.g. 1792 -> 1792).
+ */
+qx.Class.ASSUME_YEAR_2000_THRESHOLD = 30;
+
+/** {string} The short date format. */
+qx.Class.SHORT_DATE_FORMAT = "MM/dd/yyyy";
+
+/** {string} The medium date format. */
+qx.Class.MEDIUM_DATE_FORMAT = "MMM dd, yyyy";
+
+/** {string} The long date format. */
+qx.Class.LONG_DATE_FORMAT = "MMMM dd, yyyy";
+
+/** {string} The full date format. */
+qx.Class.FULL_DATE_FORMAT = "EEEE, MMMM dd, yyyy";
+
+/** {string} The short time format. */
+qx.Class.SHORT_TIME_FORMAT = "HH:mm";
+
+/** {string} The medium time format. */
+qx.Class.MEDIUM_TIME_FORMAT = qx.util.format.DateFormat.SHORT_TIME_FORMAT;
+
+/** {string} The long time format. */
+qx.Class.LONG_TIME_FORMAT = "HH:mm:ss";
+
+/** {string} The full time format. */
+qx.Class.FULL_TIME_FORMAT = "HH:mm:ss zz";
+
+/** {string} The short date-time format. */
+qx.Class.SHORT_DATE_TIME_FORMAT
+ = qx.util.format.DateFormat.SHORT_DATE_FORMAT + " "
+ + qx.util.format.DateFormat.SHORT_TIME_FORMAT;
+
+/** {string} The medium date-time format. */
+qx.Class.MEDIUM_DATE_TIME_FORMAT
+ = qx.util.format.DateFormat.MEDIUM_DATE_FORMAT + " "
+ + qx.util.format.DateFormat.MEDIUM_TIME_FORMAT;
+
+/** {string} The long date-time format. */
+qx.Class.LONG_DATE_TIME_FORMAT
+ = qx.util.format.DateFormat.LONG_DATE_FORMAT + " "
+ + qx.util.format.DateFormat.LONG_TIME_FORMAT;
+
+/** {string} The full date-time format. */
+qx.Class.FULL_DATE_TIME_FORMAT
+ = qx.util.format.DateFormat.FULL_DATE_FORMAT + " "
+ + qx.util.format.DateFormat.FULL_TIME_FORMAT;
+
+
+/** {string} The date format used for logging. */
+qx.Class.LOGGING_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+
+/** {string} The default date/time format. */
+qx.Class.DEFAULT_DATE_TIME_FORMAT = qx.util.format.DateFormat.LOGGING_DATE_TIME_FORMAT;
+
+/** {string} The default date format. */
+qx.Class.DEFAULT_DATE_FORMAT = qx.util.format.DateFormat.SHORT_DATE_FORMAT;
+
+/** {string} The am marker. */
+qx.Class.AM_MARKER = "am";
+
+/** {string} The pm marker. */
+qx.Class.PM_MARKER = "pm";
+
+/** {string[]} The full month names. */
+qx.Class.FULL_MONTH_NAMES = [
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"
+];
+
+/** {string[]} The short month names. */
+qx.Class.SHORT_MONTH_NAMES = [
+ "Jan", "Feb", "Mar", "Apr", "Mai", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+];
+
+/** {string[]} The short (two letter) day of week names. */
+qx.Class.SHORT_DAY_OF_WEEK_NAMES = [
+ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"
+];
+
+/** {string[]} The medium (three letter) day of week names. */
+qx.Class.MEDIUM_DAY_OF_WEEK_NAMES = [
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+];
+
+/** {string[]} The full day of week names. */
+qx.Class.FULL_DAY_OF_WEEK_NAMES = [
+ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
+];
+
+/** {string[]} The medium (three letter) timezone names. */
+qx.Class.MEDIUM_TIMEZONE_NAMES = [
+ "GMT" // TODO: fill up
+];
+
+/** {string[]} The full timezone names. */
+qx.Class.FULL_TIMEZONE_NAMES = [
+ "Greenwich Mean Time" // TODO: fill up
+];
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/format/Format.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/format/Format.js
new file mode 100644
index 0000000000..463d2b3595
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/format/Format.js
@@ -0,0 +1,51 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+/**
+ * Superclass for formatters and parsers.
+ */
+qx.OO.defineClass("qx.util.format.Format", qx.core.Object,
+function() {
+ qx.core.Object.call(this);
+});
+
+
+/**
+ * Formats an object.
+ *
+ * @param obj {var} The object to format.
+ * @return {string} the formatted object.
+ */
+qx.Proto.format = function(obj) {
+ throw new Error("format is abstract");
+}
+
+
+/**
+ * Parses an object.
+ *
+ * @param str {string} the string to parse.
+ * @return {var} the parsed object.
+ */
+qx.Proto.parse = function(str) {
+ throw new Error("parse is abstract");
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/format/NumberFormat.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/format/NumberFormat.js
new file mode 100644
index 0000000000..2b3f2c954a
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/format/NumberFormat.js
@@ -0,0 +1,216 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by STZ-IDA, Germany, http://www.stz-ida.de
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Til Schneider (til132)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+/**
+ * A formatter and parser for numbers.
+ */
+qx.OO.defineClass("qx.util.format.NumberFormat", qx.util.format.Format,
+function() {
+ qx.util.format.Format.call(this);
+});
+
+
+/**
+ * The minimum number of integer digits (digits before the decimal separator).
+ * Missing digits will be filled up with 0 ("19" -> "0019").
+ */
+qx.OO.addProperty({ name:"minimumIntegerDigits", type:"number", defaultValue:0, allowNull:false });
+
+/**
+ * The maximum number of integer digits (superfluos digits will be cut off
+ * ("1923" -> "23").
+ */
+qx.OO.addProperty({ name:"maximumIntegerDigits", type:"number", defaultValue:null });
+
+/**
+ * The minimum number of fraction digits (digits after the decimal separator).
+ * Missing digits will be filled up with 0 ("1.5" -> "1.500")
+ */
+qx.OO.addProperty({ name:"minimumFractionDigits", type:"number", defaultValue:0, allowNull:false });
+
+/**
+ * The maximum number of fraction digits (digits after the decimal separator).
+ * Superflous digits will cause rounding ("1.8277" -> "1.83")
+ */
+qx.OO.addProperty({ name:"maximumFractionDigits", type:"number", defaultValue:null });
+
+/** Whether thousand groupings should be used {e.g. "1,432,234.65"}. */
+qx.OO.addProperty({ name:"groupingUsed", type:"boolean", defaultValue:true, allowNull:false });
+
+/** The prefix to put before the number {"EUR " -> "EUR 12.31"}. */
+qx.OO.addProperty({ name:"prefix", type:"string", defaultValue:"", allowNull:false });
+
+/** Sets the postfix to put after the number {" %" -> "56.13 %"}. */
+qx.OO.addProperty({ name:"postfix", type:"string", defaultValue:"", allowNull:false });
+
+
+/**
+ * Formats a number.
+ *
+ * @param num {number} the number to format.
+ * @return {string} the formatted number as a string.
+ */
+qx.Proto.format = function(num) {
+ var NumberFormat = qx.util.format.NumberFormat;
+
+ var negative = (num < 0);
+ if (negative) {
+ num = -num;
+ }
+ if (this.getMaximumFractionDigits() != null) {
+ // Do the rounding
+ var mover = Math.pow(10, this.getMaximumFractionDigits());
+ num = Math.round(num * mover) / mover;
+ }
+
+ if (num != 0) { // Math.log(0) = -Infinity
+ var integerDigits = Math.max(parseInt(Math.log(num) / Math.LN10) + 1, 1);
+ } else {
+ integerDigits = 1;
+ }
+
+ var numStr = "" + num;
+
+ // Prepare the integer part
+ var integerStr = numStr.substring(0, integerDigits);
+ while (integerStr.length < this.getMinimumIntegerDigits()) {
+ integerStr = "0" + integerStr;
+ }
+ if (this.getMaximumIntegerDigits() != null && integerStr.length > this.getMaximumIntegerDigits()) {
+ // NOTE: We cut off even though we did rounding before, because there
+ // may be rounding errors ("12.24000000000001" -> "12.24")
+ integerStr = integerStr.substring(integerStr.length - this.getMaximumIntegerDigits());
+ }
+
+ // Prepare the fraction part
+ var fractionStr = numStr.substring(integerDigits + 1);
+ while (fractionStr.length < this.getMinimumFractionDigits()) {
+ fractionStr += "0";
+ }
+ if (this.getMaximumFractionDigits() != -1 && fractionStr.length > this.getMaximumFractionDigits()) {
+ // We have already rounded -> Just cut off the rest
+ fractionStr = fractionStr.substring(0, this.getMaximumFractionDigits());
+ }
+
+ // Add the thousand groupings
+ if (this.getGroupingUsed()) {
+ var origIntegerStr = integerStr;
+ integerStr = "";
+ var groupPos;
+ for (groupPos = origIntegerStr.length; groupPos > 3; groupPos -= 3) {
+ integerStr = NumberFormat.GROUPING_SEPARATOR
+ + origIntegerStr.substring(groupPos - 3, groupPos) + integerStr;
+ }
+ integerStr = origIntegerStr.substring(0, groupPos) + integerStr;
+ }
+
+ // Workaround: prefix and postfix are null even their defaultValue is "" and
+ // allowNull is set to false?!?
+ var prefix = this.getPrefix() ? this.getPrefix() : "";
+ var postfix = this.getPostfix() ? this.getPostfix() : "";
+
+ // Assemble the number
+ var str = prefix + (negative ? "-" : "") + integerStr;
+ if (fractionStr.length > 0) {
+ str += NumberFormat.DECIMAL_SEPARATOR + fractionStr;
+ }
+ str += postfix;
+
+ return str;
+}
+
+
+/**
+ * Parses a number.
+ *
+ * @param str {string} the string to parse.
+ *
+ * @return {double} the number.
+ */
+qx.Proto.parse = function(str) {
+ var NumberFormat = qx.util.format.NumberFormat;
+
+ // use the escaped separators for regexp
+ var groupSepEsc = qx.lang.String.escapeRegexpChars(NumberFormat.GROUPING_SEPARATOR);
+ var decimalSepEsc = qx.lang.String.escapeRegexpChars(NumberFormat.DECIMAL_SEPARATOR);
+
+ var regex = new RegExp(qx.lang.String.escapeRegexpChars(this.getPrefix())
+ + '(-)?([0-9' + groupSepEsc + ']+)'
+ + '(' + decimalSepEsc + '\\d+)?'
+ + qx.lang.String.escapeRegexpChars(this.getPostfix()));
+
+ var hit = regex.exec(str);
+ if (hit == null) {
+ throw new Error("Number string '" + str + "' does not match the number format");
+ }
+
+ var negative = (hit[1] == "-");
+ var integerStr = hit[2];
+ var fractionStr = hit[3];
+
+ // Remove the thousand groupings
+ integerStr = integerStr.replace(new RegExp(groupSepEsc), "");
+
+ var asStr = (negative ? "-" : "") + integerStr;
+ if (fractionStr != null && fractionStr.length != 0) {
+ // Remove the leading decimal separator from the fractions string
+ fractionStr = fractionStr.replace(new RegExp(decimalSepEsc),"");
+ asStr += "." + fractionStr;
+ }
+ return parseFloat(asStr);
+}
+
+
+/**
+ * Returns the default number format.
+ *
+ * @return {NumberFormat} the default number format.
+ */
+qx.Class.getInstance = function() {
+ var NumberFormat = qx.util.format.NumberFormat;
+ if (NumberFormat._instance == null) {
+ NumberFormat._instance = new NumberFormat();
+ }
+ return NumberFormat._instance;
+}
+
+
+/**
+ * Returns an integer number format.
+ *
+ * @return {NumberFormat} an integer number format.
+ */
+qx.Class.getIntegerInstance = function() {
+ var NumberFormat = qx.util.format.NumberFormat;
+ if (NumberFormat._integerInstance == null) {
+ NumberFormat._integerInstance = new NumberFormat();
+ NumberFormat._integerInstance.setMaximumFractionDigits(0);
+ }
+ return NumberFormat._integerInstance;
+}
+
+
+/** {string} The decimal separator. */
+qx.Class.DECIMAL_SEPARATOR = ".";
+
+/** {string} The thousand grouping separator. */
+qx.Class.GROUPING_SEPARATOR = ",";
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/FiniteStateMachine.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/FiniteStateMachine.js
new file mode 100644
index 0000000000..7c293eb76b
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/FiniteStateMachine.js
@@ -0,0 +1,1386 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by Derrell Lipman
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Derrell Lipman (derrell)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(util_fsm)
+
+************************************************************************ */
+
+/**
+ * A finite state machine.
+ *
+ * See {@see qx.util.finitestatemacine.State} for details on creating States,
+ * and {@see qx.util.finitestatemacine.Transitions} for details on creating
+ * transitions between states.
+ *
+ * *EXPERIMENTAL*
+ * The interface to the finite state machine, states, and transitions is
+ * experimental. It may change in non-backward-compatible ways as more
+ * experience is gained in its use.
+ *
+ * @param machineName {string} The name of this finite state machine
+ *
+ */
+qx.OO.defineClass("qx.util.fsm.FiniteStateMachine", qx.core.Target,
+function(machineName)
+{
+ // Call our superclass' constructor
+ qx.core.Target.call(this);
+
+ // Save the machine name
+ this.setName(machineName);
+
+ // Initialize the states object
+ this._states = { };
+
+ // Initialize the saved-states stack
+ this._savedStates = [ ];
+
+ // Initialize the pending event queue
+ this._eventQueue = [ ];
+
+ // Initialize the blocked events queue
+ this._blockedEvents = [ ];
+
+ // Create the friendlyToObject" object. Each object has as its property
+ // name, the friendly name of the object; and as its property value, the
+ // object itself.
+ this._friendlyToObject = { };
+
+ // Create the "friendlyToHash" object. Each object has as its property
+ // name, the friendly name of the object; and as its property value, the
+ // hash code of the object.
+ this._friendlyToHash = { };
+
+ // Create the "hashToFriendly" object. Each object has as its property
+ // name, the hash code of the object; and as its property value, the
+ // friendly name of the object.
+ this._hashToFriendly = { };
+
+ // Friendly names can be added to groups, for easy manipulation of enabling
+ // and disabling groups of widgets. Track which friendly names are in which
+ // group.
+ this._groupToFriendly = { };
+
+ // We also need to be able to map back from friendly name to the groups it
+ // is in.
+ this._friendlyToGroups = { };
+});
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/**
+ * The name of this finite state machine (for debug messages)
+ */
+qx.OO.addProperty(
+ {
+ name : "name",
+ type : "string"
+ });
+
+/**
+ * The current state of the finite state machine.
+ */
+qx.OO.addProperty(
+ {
+ name : "state",
+ type : "string"
+ });
+
+/**
+ * The previous state of the finite state machine, i.e. the state from which
+ * we most recently transitioned. Note that this could be the same as the
+ * current state if a successful transition brought us back to the same
+ * state.
+ */
+qx.OO.addProperty(
+ {
+ name : "previousState",
+ type : "string"
+ });
+
+/**
+ * The state to which we will be transitioning. This property is valid only
+ * during a Transition's ontransition function and a State's onexit function.
+ * At all other times, it is null.
+ */
+qx.OO.addProperty(
+ {
+ name : "nextState",
+ type : "string"
+ });
+
+
+/**
+ * The maximum number of states which may pushed onto the state-stack. It is
+ * generally a poor idea to have very many states saved on a stack. Following
+ * program logic becomes very difficult, and the code can be highly
+ * unmaintainable. The default should be more than adequate. You've been
+ * warned.
+ */
+qx.OO.addProperty(
+ {
+ name : "maxSavedStates",
+ type : "number",
+ defaultValue : 2
+ });
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+
+/**
+ * Add a state to the finite state machine.
+ *
+ * @param state {qx.util.fsm.State}
+ * An object of class qx.util.fsm.State representing a state
+ * which is to be a part of this finite state machine.
+ */
+qx.Proto.addState = function(state)
+{
+ // Ensure that we got valid state info
+ if (! state instanceof qx.util.fsm.State)
+ {
+ throw new Error("Invalid state: not an instance of " +
+ "qx.util.fsm.State");
+ }
+
+ // Retrieve the name of this state
+ var stateName = state.getName();
+
+ // Ensure that the state name doesn't already exist
+ if (stateName in this._states)
+ {
+ throw new Error("State " + state + " already exists");
+ }
+
+ // Add the new state object to the finite state machine
+ this._states[stateName] = state;
+};
+
+
+/**
+ * Replace a state in the finite state machine. This is useful if initially
+ * "dummy" states are created which load the real state table for a series of
+ * operations (and possibly also load the gui associated with the new states
+ * at the same time). Having portions of the finite state machine and their
+ * associated gui pages loaded at run time can help prevent long delays at
+ * application start-up time.
+ *
+ * @param state {qx.util.fsm.State}
+ * An object of class qx.util.fsm.State representing a state
+ * which is to be a part of this finite state machine.
+ *
+ * @param bDispose {boolean}
+ * If true , then dispose the old state object. If false , the
+ * old state object is returned for disposing by the caller.
+ *
+ * @return {Object}
+ * The old state object if it was not disposed; otherwise null.
+ */
+qx.Proto.replaceState = function(state, bDispose)
+{
+ // Ensure that we got valid state info
+ if (! state instanceof qx.util.fsm.State)
+ {
+ throw new Error("Invalid state: not an instance of " +
+ "qx.util.fsm.State");
+ }
+
+ // Retrieve the name of this state
+ var stateName = state.getName();
+
+ // Save the old state object, so we can return it to be disposed
+ var oldState = this._states[stateName];
+
+ // Replace the old state with the new state object.
+ this._states[stateName] = state;
+
+ // Did they request that the old state be disposed?
+ if (bDispose)
+ {
+ // Yup. Mark it to be disposed.
+ oldState._needDispose;
+ }
+
+ return oldState;
+};
+
+
+
+/**
+ * Add an object (typically a widget) that is to be accessed during state
+ * transitions, to the finite state machine.
+ *
+ * @param friendlyName {string}
+ * The friendly name to used for access to the object being added.
+ *
+ * @param obj {Object}
+ * The object to associate with the specified friendly name
+ *
+ * @param groupNames {Array}
+ * An optional list of group names of which this object is a member.
+ */
+qx.Proto.addObject = function(friendlyName, obj, groupNames)
+{
+ var hash = obj.toHashCode();
+ this._friendlyToHash[friendlyName] = hash;
+ this._hashToFriendly[hash] = friendlyName;
+ this._friendlyToObject[friendlyName] = obj;
+
+ // If no groupNames are specified, we're done.
+ if (! groupNames)
+ {
+ return;
+ }
+
+ // Allow either a single group name or an array of group names. If the
+ // former, we convert it to the latter to make the subsequent code simpler.
+ if (typeof(groupNames) == "string")
+ {
+ groupNames = [ groupNames ];
+ }
+
+ // For each group that this friendly name is to be a member of...
+ for (var i = 0; i < groupNames.length; i++)
+ {
+ var groupName = groupNames[i];
+
+ // If the group name doesn't yet exist...
+ if (! this._groupToFriendly[groupName])
+ {
+ // ... then create it.
+ this._groupToFriendly[groupName] = { };
+ }
+
+ // Add the friendly name to the list of names in this group
+ this._groupToFriendly[groupName][friendlyName] = true;
+
+ // If the friendly name group mapping doesn't yet exist...
+ if (! this._friendlyToGroups[friendlyName])
+ {
+ // ... then create it.
+ this._friendlyToGroups[friendlyName] = [ ];
+ }
+
+ // Append this group name to the list of groups this friendly name is in
+ this._friendlyToGroups[friendlyName] =
+ this._friendlyToGroups[friendlyName].concat(groupNames);
+ }
+};
+
+
+/**
+ * Remove an object which had previously been added by {@see #addObject}.
+ *
+ * @param friendlyName {string}
+ * The friendly name associated with an object, specifying which object is
+ * to be removed.
+ */
+qx.Proto.removeObject = function(friendlyName)
+{
+ var hash = this._friendlyToHash[friendlyName];
+
+ // Delete references to any groupos this friendly name was in
+ if (this._friendlyToGroups[friendlyName])
+ {
+ for (groupName in this._friendlyToGroups[friendlyName])
+ {
+ delete this._groupToFriendly[groupName];
+ }
+
+ delete this._friendlyToGroups[friendlyName];
+ }
+
+ // Delete the friendly name
+ delete this._hashToFriendly[hash];
+ delete this._friendlyToHash[friendlyName];
+ delete this._friendlyToObject[friendlyName];
+};
+
+
+/**
+ * Retrieve an object previously saved via {@see #addObject}, using its
+ * Friendly Name.
+ *
+ * @param friendlyName {string}
+ * The friendly name of the object to be retrieved.
+ *
+ * @return {Object}
+ * The object which has the specified friendly name, or undefined if no
+ * object has been associated with that name.
+ */
+qx.Proto.getObject = function(friendlyName)
+{
+ return this._friendlyToObject[friendlyName];
+};
+
+
+/**
+ * Get the friendly name of an object.
+ *
+ * @param obj {Object} The object for which the friendly name is desired
+ *
+ * @return {string}
+ * If the object has been previously registered via {@see #addObject}, then
+ * the friendly name of the object is returned; otherwise, null.
+ */
+qx.Proto.getFriendlyName = function(obj)
+{
+ var hash = obj.toHashCode();
+ return hash ? this._hashToFriendly[hash] : null;
+};
+
+
+/**
+ * Retrieve the list of objects which have registered, via {@see addObject} as
+ * being members of the specified group.
+ *
+ * @param groupName {string}
+ * The name of the group for which the member list is desired.
+ *
+ * @return {Array}
+ * An array containing the friendly names of any objects which are members
+ * of the specified group. The resultant array may be empty.
+ */
+qx.Proto.getGroupObjects = function(groupName)
+{
+ var a = [ ];
+
+ for (var name in this._groupToFriendly[groupName])
+ {
+ a.push(name);
+ }
+
+ return a;
+};
+
+
+/**
+ * Display all of the saved objects and their reverse mappings.
+ */
+qx.Proto.displayAllObjects = function()
+{
+ for (var friendlyName in this._friendlyToHash)
+ {
+ var hash = this._friendlyToHash[friendlyName];
+ var obj = this.getObject(friendlyName);
+ this.debug(friendlyName +
+ " => " +
+ hash);
+ this.debug(" " + hash +
+ " => " +
+ this._hashToFriendly[hash]);
+ this.debug(" " + friendlyName +
+ " => " +
+ this.getObject(friendlyName));
+ this.debug(" " + this.getObject(friendlyName) +
+ " => " +
+ this.getFriendlyName(obj));
+ }
+};
+
+
+/**
+ * Recursively display an object (as debug messages)
+ *
+ * @param obj {Object}
+ * The object to be recursively displayed
+ */
+qx.Proto.debugObject = function(obj)
+{
+ thisClass = this;
+
+ var displayObj = function(obj, level)
+ {
+ var indentStr = "";
+ for (var i = 0; i < level; i++)
+ {
+ indentStr += " ";
+ }
+
+ if (typeof(obj) != "object")
+ {
+ thisClass.debug(indentStr, obj);
+ return;
+ }
+
+ for (var prop in obj)
+ {
+ if (typeof(obj[prop]) == "object")
+ {
+ if (obj[prop] instanceof Array)
+ {
+ thisClass.debug(indentStr + prop + ": " + "Array");
+ }
+ else
+ {
+ thisClass.debug(indentStr + prop + ": " + "Object");
+ }
+
+ displayObj(obj[prop], level + 1);
+ }
+ else
+ {
+ thisClass.debug(indentStr + prop + ": " + obj[prop]);
+ }
+ }
+ }
+
+ displayObj(obj, 0);
+};
+
+
+
+/**
+ * Start (or restart, after it has terminated) the finite state machine from
+ * the starting state. The starting state is defined as the first state added
+ * to the finite state machine.
+ */
+qx.Proto.start = function()
+{
+ var stateName;
+
+ // Set the start state to be the first state which was added to the machine
+ for (stateName in this._states)
+ {
+ this.setState(stateName);
+ this.setPreviousState(null);
+ this.setNextState(null);
+ break;
+ }
+
+ if (! stateName)
+ {
+ throw new Error("Machine started with no available states");
+ }
+
+ var debugFunctions =
+ (qx.Settings.getValueOfClass("qx.util.fsm.FiniteStateMachine",
+ "debugFlags") &
+ qx.util.fsm.FiniteStateMachine.DebugFlags.FUNCTION_DETAIL);
+
+ // Run the actionsBeforeOnentry actions for the initial state
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + stateName + "#actionsBeforeOnentry");
+ }
+ this._states[stateName].getAutoActionsBeforeOnentry()(this);
+
+ // Run the entry function for the new state, if one is specified
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + stateName + "#entry");
+ }
+ this._states[stateName].getOnentry()(this, null);
+
+ // Run the actionsAfterOnentry actions for the initial state
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + stateName + "#actionsAfterOnentry");
+ }
+ this._states[stateName].getAutoActionsAfterOnentry()(this);
+
+};
+
+
+/**
+ * Save the current or previous state on the saved-state stack. A future
+ * transition can then provide, as its nextState value, the class constant:
+ *
+ * qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK
+ *
+ * which will cause the next state to be whatever is at the top of the
+ * saved-state stack, and remove that top element from the saved-state stack.
+ *
+ * @param bCurrent {boolean}
+ * When true , then push the current state onto the stack. This might
+ * be used in a transition, before the state has changed. When
+ * false , then push the previous state onto the stack. This might be
+ * used in an on entry function to save the previous state to return to.
+ */
+qx.Proto.pushState = function(bCurrent)
+{
+ // See if there's room on the state stack for a new state
+ if (this._savedStates.length >= this.getMaxSavedStates())
+ {
+ // Nope. Programmer error.
+ throw new Error("Saved-state stack is full");
+ }
+
+ if (bCurrent)
+ {
+ // Push the current state onto the saved-state stack
+ this._savedStates.push(this.getState());
+ }
+ else
+ {
+ // Push the previous state onto the saved-state stack
+ this._savedStates.push(this.getPreviousState());
+ }
+};
+
+
+/**
+ * Add the specified event to a list of events to be passed to the next state
+ * following state transition.
+ *
+ * @param event {qx.event.type.Event}
+ * The event to add to the event queue for processing after state change.
+ */
+qx.Proto.postponeEvent = function(event)
+{
+ // Add this event to the blocked event queue, so it will be passed to the
+ // next state upon transition.
+ this._blockedEvents.unshift(event);
+};
+
+
+/**
+ * Copy an event
+ *
+ * @param event {qx.event.type.Event}
+ * The event to be copied
+ *
+ * @return {qx.event.type.Event}
+ * The new copy of the provided event
+ */
+qx.Proto.copyEvent = function(event)
+{
+ var e = { };
+ for (var prop in event)
+ {
+ e[prop] = event[prop];
+ }
+
+ return e;
+};
+
+
+/**
+ * Enqueue an event for processing
+ *
+ * @param event {qx.event.type.Event}
+ * The event to be enqueued
+ *
+ * @param bAddAtHead {boolean}
+ * If true , put the event at the head of the queue for immediate
+ * processing. If false , place the event at the tail of the queue so
+ * that it receives in-order processing.
+ */
+qx.Proto.enqueueEvent = function(event, bAddAtHead)
+{
+ // Add the event to the event queue
+ if (bAddAtHead)
+ {
+ // Put event at the head of the queue
+ this._eventQueue.push(event);
+ }
+ else
+ {
+ // Put event at the tail of the queue
+ this._eventQueue.unshift(event);
+ }
+
+ if (qx.Settings.getValueOfClass("qx.util.fsm.FiniteStateMachine",
+ "debugFlags") &
+ qx.util.fsm.FiniteStateMachine.DebugFlags.EVENTS)
+ {
+ if (bAddAtHead)
+ {
+ this.debug(this.getName() + ": Pushed event: " + event.getType());
+ }
+ else
+ {
+ this.debug(this.getName() + ": Queued event: " + event.getType());
+ }
+ }
+};
+
+
+/**
+ * Event listener for all event types in the finite state machine
+ *
+ * @param event {qx.event.type.Event}
+ * The event that was dispatched.
+ */
+qx.Proto.eventListener = function(event)
+{
+ // Events are enqueued upon receipt. Some events are then processed
+ // immediately; other events get processed later. We need to allow the
+ // event dispatcher to free the source event upon our return, so we'll clone
+ // it and enqueue our clone. The source event can then be disposed upon our
+ // return.
+ var e = this.copyEvent(event);
+
+ // Enqueue the new event on the tail of the queue
+ this.enqueueEvent(e, false);
+
+ // Process events
+ this._processEvents();
+};
+
+
+/**
+ * Process all of the events on the event queue.
+ */
+qx.Proto._processEvents = function()
+{
+ // eventListener() can potentially be called while we're processing events
+ if (this._eventProcessingInProgress)
+ {
+ // We were processing already, so don't process concurrently.
+ return;
+ }
+
+ // Track that we're processing events
+ this._eventProcessingInProgress = true;
+
+ // Process each of the events on the event queue
+ while (this._eventQueue.length > 0)
+ {
+ // Pull the next event from the pending event queue
+ var event = this._eventQueue.pop();
+
+ // Run the finite state machine with this event
+ this._run(event);
+
+ // We can now dispose the event
+ event.dispose();
+ }
+
+ // We're no longer processing events
+ this._eventProcessingInProgress = false;
+};
+
+/**
+ * Run the finite state machine to process a single event.
+ *
+ * @param event {qx.event.type.Event}
+ * An event that has been dispatched. The event may be handled (if the
+ * current state handles this event type), queued (if the current state
+ * blocks this event type), or discarded (if the current state neither
+ * handles nor blocks this event type).
+ */
+qx.Proto._run = function(event)
+{
+ // For use in generated functions...
+ var fsm = this;
+
+ // State name variables
+ var thisState;
+ var nextState;
+ var prevState;
+
+ // The current State object
+ var currentState;
+
+ // The transitions available in the current State
+ var transitions;
+
+ // Events handled by the current State
+ var e;
+
+ // The action to take place upon receipt of a particular event
+ var action;
+
+ // Get the debug flags
+ var debugFlags =
+ (qx.Settings.getValueOfClass("qx.util.fsm.FiniteStateMachine",
+ "debugFlags"));
+
+ // Allow slightly faster access to determine if debug is enableda
+ var debugEvents =
+ debugFlags & qx.util.fsm.FiniteStateMachine.DebugFlags.EVENTS;
+ var debugTransitions =
+ debugFlags & qx.util.fsm.FiniteStateMachine.DebugFlags.TRANSITIONS;
+ var debugFunctions =
+ debugFlags & qx.util.fsm.FiniteStateMachine.DebugFlags.FUNCTION_DETAIL;
+ var debugObjectNotFound =
+ debugFlags & qx.util.fsm.FiniteStateMachine.DebugFlags.OBJECT_NOT_FOUND;
+
+ if (debugEvents)
+ {
+ this.debug(this.getName() + ": Process event: " + event.getType());
+ }
+
+ // Get the current state name
+ thisState = this.getState();
+
+ // Get the current State object
+ currentState = this._states[thisState];
+
+ // Get a list of the transitions available from this state
+ transitions = currentState.transitions;
+
+ // Determine how to handle this event
+ e = currentState.getEvents()[event.getType()];
+
+ // See if we actually found this event type
+ if (! e)
+ {
+ if (this.debugEvents)
+ {
+ this.debug(this.getName() + ": Event '" + event.getType() + "'" +
+ " not handled. Ignoring.");
+ }
+ return;
+ }
+
+ // We might have found a constant (PREDICATE or BLOCKED) or an object with
+ // each property name being the friendly name of a saved object, and the
+ // property value being one of the constants (PREDICATE or BLOCKED).
+ if (typeof(e) == "object")
+ {
+ // Individual objects are listed. Ensure target is a saved object
+ var friendly = this.getFriendlyName(event.getTarget());
+ if (! friendly)
+ {
+ // Nope, it doesn't seem so. Just discard it.
+ if (debugObjectNotFound)
+ {
+ this.debug(this.getName() + ": Could not find friendly name for '" +
+ event.getType() + "' on '" + event.getTarget() + "'");
+ }
+ return;
+ }
+
+ action = e[friendly];
+ }
+ else
+ {
+ action = e;
+ }
+
+ switch(action)
+ {
+ case qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE:
+ // Process this event. One of the transitions should handle it.
+ break;
+
+ case qx.util.fsm.FiniteStateMachine.EventHandling.BLOCKED:
+ // This event is blocked. Enqueue it for later, and get outta here.
+ this._blockedEvents.unshift(event);
+ return;
+
+ default:
+ // See if we've been given an explicit transition name
+ if (typeof(action) == "string")
+ {
+ // Yup! Ensure that it exists
+ if (transitions[action])
+ {
+ // Yup. Create a transitions object containing only this transition.
+ var trans = transitions[action];
+ transitions = { };
+ transitions[action] = trans;
+ }
+ else
+ {
+ throw new Error("Explicit transition " + action + " does not exist");
+ }
+
+ break;
+ }
+ }
+
+ // We handle the event. Try each transition in turn until we find one that
+ // is acceptable.
+ for (var t in transitions)
+ {
+ var trans = transitions[t];
+
+ // Does the predicate allow use of this transition?
+ switch(trans.getPredicate()(this, event))
+ {
+ case true:
+ // Transition is allowed. Proceed.
+ break;
+
+ case false:
+ // Transition is not allowed. Try next transition.
+ continue;
+
+ case null:
+ // Transition indicates not to try further transitions
+ return;
+
+ default:
+ throw new Error("Transition " + thisState + ":" + t +
+ " returned a value other than true, false, or null.");
+ return;
+ }
+
+ // We think we can transition to the next state. Set next state.
+ nextState = trans.getNextState();
+ if (typeof(nextState) == "string")
+ {
+ // We found a literal state name. Ensure it exists.
+ if (! nextState in this._states)
+ {
+ throw new Error("Attempt to transition to nonexistent state " +
+ nextState);
+ }
+
+ // It exists. Track it being the next state.
+ this.setNextState(nextState);
+ }
+ else
+ {
+ // If it's not a string, nextState must be a StateChange constant
+ switch(nextState)
+ {
+ case qx.util.fsm.FiniteStateMachine.StateChange.CURRENT_STATE:
+ // They want to remain in the same state.
+ nextState = thisState;
+ this.setNextState(nextState)
+ break;
+
+ case qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK:
+ // Switch to the state at the top of the state stack.
+ if (this._savedStates.length == 0)
+ {
+ throw new Error("Attempt to transition to POP_STATE_STACK " +
+ "while state stack is empty.");
+ }
+
+ // Pop the state stack to retrieve the state to transition to
+ nextState = this._savedStates.pop();
+ this.setNextState(nextState);
+ break;
+
+ default:
+ throw new Error("Internal error: invalid nextState");
+ break;
+ }
+ }
+
+ // Run the actionsBeforeOntransition actions for this transition
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + thisState + "#" + t +
+ "#autoActionsBeforeOntransition");
+ }
+ trans.getAutoActionsBeforeOntransition()(this);
+
+ // Run the 'ontransition' function
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + thisState + "#" + t + "#ontransition");
+ }
+ trans.getOntransition()(this, event);
+
+ // Run the autoActionsAfterOntransition actions for this transition
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + thisState + "#" + t +
+ "#autoActionsAfterOntransition");
+ }
+ trans.getAutoActionsAfterOntransition()(this);
+
+ // Run the autoActionsBeforeOnexit actions for the old state
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + thisState +
+ "#autoActionsBeforeOnexit");
+ }
+ currentState.getAutoActionsBeforeOnexit()(this);
+
+ // Run the exit function for the old state
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + thisState + "#exit");
+ }
+ currentState.getOnexit()(this, event);
+
+ // Run the autoActionsAfterOnexit actions for the old state
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + thisState + "#autoActionsAfterOnexit");
+ }
+ currentState.getAutoActionsAfterOnexit()(this);
+
+ // If this state has been replaced and we're supposed to dispose it...
+ if (currentState._needDispose)
+ {
+ // ... then dispose it now that it's no longer in use
+ currentState.dispose();
+ }
+
+ // Reset currentState to the new state object
+ currentState = this._states[this.getNextState()];
+
+ // set previousState and state, and clear nextState, for transition
+ this.setPreviousState(thisState);
+ this.setState(this.getNextState());
+ this.setNextState(null);
+ prevState = thisState;
+ thisState = nextState;
+ nextState = undefined;
+
+ // Run the autoActionsBeforeOnentry actions for the new state
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + thisState +
+ "#autoActionsBeforeOnentry");
+ }
+ currentState.getAutoActionsBeforeOnentry()(this);
+
+ // Run the entry function for the new state, if one is specified
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + thisState + "#entry");
+ }
+ currentState.getOnentry()(this, event);
+
+ // Run the autoActionsAfterOnentry actions for the new state
+ if (debugFunctions)
+ {
+ this.debug(this.getName() + "#" + thisState +
+ "#autoActionsAfterOnentry");
+ }
+ currentState.getAutoActionsAfterOnentry()(this);
+
+ // Add the blocked events to the pending event queue
+ if (this._blockedEvents.length > 0)
+ {
+ this._eventQueue.unshift(this._blockedEvents);
+ }
+
+ // The blocked event list is now empty
+ this._blockedEvents = [ ];
+
+ // Ensure that all actions have been flushed
+ qx.ui.core.Widget.flushGlobalQueues();
+
+ if (debugTransitions)
+ {
+ this.debug(this.getName() + "#" + prevState + " => " +
+ this.getName() + "#" + thisState);
+ }
+
+ // See ya!
+ return;
+ }
+
+ if (debugTransitions)
+ {
+ this.debug(this.getName() + "#" + thisState +
+ ": event '" + event.getType() + "'" +
+ ": no transition found. No state change.");
+ }
+};
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT LISTENERS
+---------------------------------------------------------------------------
+*/
+
+
+
+/*
+---------------------------------------------------------------------------
+ CLASS CONSTANTS
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Constants which may be values of the nextState member in the transitionInfo
+ * parameter of the Transition constructor.
+ */
+qx.Class.StateChange =
+{
+ /** When used as a nextState value, means remain in current state */
+ CURRENT_STATE : 1,
+
+ /** When used as a nextState value, means go to most-recently pushed state */
+ POP_STATE_STACK : 2,
+
+ /** When used as a nextState value, means terminate this state machine */
+ TERMINATE : 3
+};
+
+
+/**
+ * Constants for use in the events member of the transitionInfo parameter of
+ * the Transition constructor.
+ */
+qx.Class.EventHandling =
+{
+ /**
+ * This event is handled by this state, but the predicate of a transition
+ * will determine whether to use that transition.
+ */
+ PREDICATE : 1,
+
+ /** Enqueue this event for possible use by the next state */
+ BLOCKED : 2
+};
+
+/**
+ * Debug bitmask values. Set the debug flags from the application by or-ing
+ * together bits, akin to this:
+ *
+ * qx.Settings.setCustomOfClass(
+ * "qx.util.fsm.FiniteStateMachine",
+ * "debugFlags",
+ * (qx.util.fsm.FiniteStateMachine.DebugFlags.EVENTS |
+ * qx.util.fsm.FiniteStateMachine.DebugFlags.TRANSITIONS |
+ * qx.util.fsm.FiniteStateMachine.DebugFlags.FUNCTION_DETAIL |
+ * qx.util.fsm.FiniteStateMachine.DebugFlags.OBJECT_NOT_FOUND));
+ */
+qx.Class.DebugFlags =
+{
+ /** Show events */
+ EVENTS : 1,
+
+ /** Show transitions */
+ TRANSITIONS : 2,
+
+ /** Show individual function invocations during transitions */
+ FUNCTION_DETAIL : 4,
+
+ /** When object friendly names are referenced but not found, show message */
+ OBJECT_NOT_FOUND : 8
+};
+
+
+/*
+---------------------------------------------------------------------------
+ CLASS DEFAULT SETTINGS
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Debug flags: bitmap of DebugFlags (see Class Constants).
+ */
+qx.Settings.setDefault(
+ "debugFlags",
+ (qx.util.fsm.FiniteStateMachine.DebugFlags.EVENTS |
+ qx.util.fsm.FiniteStateMachine.DebugFlags.TRANSITIONS |
+ qx.util.fsm.FiniteStateMachine.DebugFlags.OBJECT_NOT_FOUND));
+
+
+/*
+---------------------------------------------------------------------------
+ CLASS FUNCTIONS
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Common function used by {qx.util.fsm.State} and
+ * {qx.util.fsm.Transition} for checking the value provided for
+ * auto actions.
+ *
+ * Auto-action property values passed to us look akin to:
+ *
+ *
+ * {
+ * // The name of a function.
+ * "setEnabled" :
+ * [
+ * {
+ * // The parameter value(s), thus "setEnabled(true);"
+ * "parameters" : [ true ],
+ *
+ * // The function would be called on each object:
+ * // this.getObject("obj1").setEnabled(true);
+ * // this.getObject("obj2").setEnabled(true);
+ * "objects" : [ "obj1", "obj2" ]
+ *
+ * // And similarly for each object in each specified group.
+ * "groups" : [ "group1", "group2" ],
+ * }
+ * ];
+ *
+ * "setColor" :
+ * [
+ * {
+ * "parameters" : [ "blue" ]
+ * "groups" : [ "group3", "group4" ],
+ * "objects" : [ "obj3", "obj4" ]
+ * }
+ * ];
+ * };
+ *
+ *
+ * @param actionType {string}
+ * The name of the action being validated (for debug messages)
+ *
+ * @param propValue {Object}
+ * The property value which is being validated
+ *
+ * @param propData
+ * Not used
+ */
+qx.Class._commonCheckAutoActions = function(actionType, propValue, propData)
+{
+ // Validate that we received an object property value
+ if (typeof(propValue) != "object")
+ {
+ throw new Error("Invalid " + actionType + " value: " + typeof(propValue));
+ }
+
+ // We'll create a function to do the requested actions. Initialize the
+ // string into which we'll generate the common fragment added to the
+ // function for each object.
+ var funcFragment;
+
+ // Here, we'll keep the function body. Initialize a try block.
+ var func =
+ "try" +
+ "{";
+
+ var param;
+ var objectAndGroupList;
+
+ // Retrieve the function request, e.g.
+ // "enabled" :
+ for (var f in propValue)
+ {
+ // Get the function request value object, e.g.
+ // "setEnabled" :
+ // [
+ // {
+ // "parameters" : [ true ],
+ // "objects" : [ "obj1", "obj2" ]
+ // "groups" : [ "group1", "group2" ],
+ // }
+ // ];
+ var functionRequest = propValue[f];
+
+ // The function request value should be an object
+ if (! functionRequest instanceof Array)
+ {
+ throw new Error("Invalid function request type: " +
+ "expected array, found " + typeof(functionRequest));
+ }
+
+ // For each function request...
+ for (var i = 0; i < functionRequest.length; i++)
+ {
+ // Retreive the object and group list object
+ objectAndGroupList = functionRequest[i];
+
+ // The object and group list should be an object, e.g.
+ // {
+ // "parameters" : [ true ],
+ // "objects" : [ "obj1", "obj2" ]
+ // "groups" : [ "group1", "group2" ],
+ // }
+ if (typeof(objectAndGroupList) != "object")
+ {
+ throw new Error("Invalid function request parameter type: " +
+ "expected object, found " +
+ typeof(functionRequest[param]));
+ }
+
+ // Retrieve the parameter list
+ params = objectAndGroupList["parameters"];
+
+ // If it didn't exist, ...
+ if (! params)
+ {
+ // ... use an empty array.
+ params = [ ];
+ }
+ else
+ {
+ // otherwise, ensure we got an array
+ if (! params instanceof Array)
+ {
+ throw new Error("Invalid function parameters: " +
+ "expected array, found " + typeof(params));
+ }
+ }
+
+ // Create the function to call on each object. The object on which the
+ // function is called will be prepended later.
+ funcFragment = f + "(";
+
+ // For each parameter...
+ for (var j = 0; j < params.length; j++)
+ {
+ // If this isn't the first parameter, add a separator
+ if (j != 0)
+ {
+ funcFragment += ",";
+ }
+
+ if (typeof(params[j]) == "function")
+ {
+ // If the parameter is a function, arrange for it to be called
+ // at run time.
+ funcFragment += "(" + params[j] + ")(fsm)";
+ }
+ else if (typeof(params[j]) == "string")
+ {
+ // If the parameter is a string, quote it.
+ funcFragment += '"' + params[j] + '"';
+ }
+ else
+ {
+ // Otherwise, just add the parameter's literal value
+ funcFragment += params[j];
+ }
+ }
+
+ // Complete the function call
+ funcFragment += ")";
+
+ // Get the "objects" list, e.g.
+ // "objects" : [ "obj1", "obj2" ]
+ var a = objectAndGroupList["objects"];
+
+ // Was there an "objects" list?
+ if (! a)
+ {
+ // Nope. Simplify code by creating an empty array.
+ a = [ ];
+ }
+ else if (! a instanceof Array)
+ {
+ throw new Error("Invalid 'objects' list: expected array, got " +
+ typeof(a));
+ }
+
+ for (var j = 0; j < a.length; j++)
+ {
+ // Ensure we got a string
+ if (typeof(a[j]) != "string")
+ {
+ throw new Error("Invalid friendly name in 'objects' list: " + a[j]);
+ }
+
+ func += " fsm.getObject('" + a[j] + "')." + funcFragment + ";";
+ }
+
+ // Get the "groups" list, e.g.
+ // "groups" : [ "group1, "group2" ]
+ var g = objectAndGroupList["groups"];
+
+ // Was a "groups" list found?
+ if (g)
+ {
+ // Yup. Ensure it's an array.
+ if (! g instanceof Array)
+ {
+ throw new Error("Invalid 'groups' list: expected array, got " +
+ typeof(g));
+ }
+
+ for (var groupName in g)
+ {
+ // Arrange to call the function on each object in each group
+ func +=
+ " var groupObjects = " +
+ " fsm.getGroupObjects('" + g[groupName] + "');" +
+ " for (var i = 0; i < groupObjects.length; i++)" +
+ " {" +
+ " var objName = groupObjects[i];" +
+ " fsm.getObject(objName)." + funcFragment + ";" +
+ " }";
+ }
+ }
+ }
+ }
+
+ // Terminate the try block for function invocations
+ func +=
+ "}" +
+ "catch(e)" +
+ "{" +
+ " fsm.debug(e);" +
+ "}";
+
+// o = new qx.core.Object();
+// o.debug("Dynamically created " + actionType + "(fsm) { " + func + " }");
+
+ // We've now built the entire body of a function that implements calls to
+ // each of the requested automatic actions. Create and return the function,
+ // which will become the property value.
+ return new Function("fsm", func);
+};
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ var e;
+ var s;
+
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ while (this._savedStates.length > 0)
+ {
+ s = this._savedStates.pop();
+ s = null;
+ }
+ this._savedStates = null;
+
+ while (this._eventQueue.length > 0)
+ {
+ e = this._eventQueue.pop();
+ e.dispose();
+ e = null;
+ }
+ this._eventQueue = null;
+
+ while (this._blockedEvents.length > 0)
+ {
+ e = this._blockedEvents.pop();
+ e.dispose();
+ e = null;
+ }
+
+ for (var s in this._states)
+ {
+ this._states[s].dispose();
+ this._states[s] = null;
+ delete this._states[s];
+ }
+ this._states = null;
+
+ return qx.core.Target.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/State.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/State.js
new file mode 100644
index 0000000000..fc054e304a
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/State.js
@@ -0,0 +1,613 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by Derrell Lipman
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Derrell Lipman (derrell)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(util_fsm)
+#require(qx.util.fsm.FiniteStateMachine)
+
+************************************************************************ */
+
+/**
+ * Create a new state which may be added to a finite state machine.
+ *
+ * *EXPERIMENTAL*
+ * The interface to the finite state machine, states, and transitions is
+ * experimental. It may change in non-backward-compatible ways as more
+ * experience is gained in its use.
+ *
+ * @param
+ * stateName -
+ * The name of this state. This is the name which may be referenced in
+ * objects of class qx.util.fsm.Transition, when passing of
+ * the the transition's predicate means transition to this state.
+ *
+ * @param
+ * stateInfo -
+ * An object containing any of the following properties:
+ *
+ * onentry -
+ * A function which is called upon entry to the state. Its signature is
+ * function(fsm, event) and it is saved in the onentry property of the
+ * state object. (This function is called after the Transition's action
+ * function and after the previous state's onexit function.)
+ *
+ * In the onentry function:
+ *
+ * fsm -
+ * The finite state machine object to which this state is attached.
+ *
+ * event -
+ * The event that caused the finite state machine to run
+ *
+ * onexit -
+ * A function which is called upon exit from the state. Its signature
+ * is function(fsm, event) and it is saved in the onexit property of the
+ * state object. (This function is called after the Transition's action
+ * function and before the next state's onentry function.)
+ *
+ * In the onexit function:
+ *
+ * fsm -
+ * The finite state machine object to which this state is attached.
+ *
+ * event -
+ * The event that caused the finite state machine to run
+ *
+ * autoActionsBeforeOnentry -
+ * autoActionsAfterOnentry -
+ * autoActionsBeforeOnexit -
+ * autoActionsAfterOnexit -
+ * Automatic actions which take place at the time specified by the
+ * property name. In all cases, the action takes place immediately
+ * before or after the specified function.
+ *
+ * The property value for each of these properties is an object which
+ * describes some number of functions to invoke on a set of specified
+ * objects (typically widgets).
+ *
+ * An example, using autoActionsBeforeOnentry, might look like this:
+ *
+ * "autoActionsBeforeOnentry" :
+ * {
+ * // The name of a function.
+ * "enabled" :
+ * [
+ * {
+ * // The parameter value, thus "setEnabled(true);"
+ * "parameters" : [ true ],
+ *
+ * // The function would be called on each object:
+ * // this.getObject("obj1").setEnabled(true);
+ * // this.getObject("obj2").setEnabled(true);
+ * "objects" : [ "obj1", "obj2" ],
+ *
+ * // And similarly for each object in each specified group.
+ * "groups" : [ "group1", "group2" ]
+ * }
+ * ],
+ *
+ * // The name of another function.
+ * "visible" :
+ * [
+ * {
+ * // The parameter value, thus "setEnabled(true);"
+ * "parameters" : [ false ],
+ *
+ * // The function would be called on each object and group, as
+ * // described above.
+ * "objects" : [ "obj3", "obj4" ],
+ * "groups" : [ "group3", "group4" ]
+ * }
+ * ]
+ * };
+ *
+ *
+ * events (required) -
+ * A description to the finite state machine of how to handle a
+ * particular event, optionally associated with a specific target object
+ * on which the event was dispatched. This should be an object
+ * containing one property for each event which is either handled or
+ * blocked. The property name should be the event name. The property
+ * value should be one of:
+ *
+ * (a) qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE
+ *
+ * (b) qx.util.fsm.FiniteStateMachine.EventHandling.BLOCKED
+ *
+ * (c) a string containing the name of an explicit Transition to use
+ *
+ * (d) an object where each property name is the Friendly Name of an
+ * object (meaning that this rule applies if both the event and
+ * the event's target object's Friendly Name match), and its
+ * property value is one of (a), (b) or (c), above.
+ *
+ * This object is saved in the events property of the state object.
+ *
+ * Additional properties may be provided in stateInfo. They will not be
+ * used by the finite state machine, but will be available via
+ * this.getUserData("") during the state's onentry and
+ * onexit functions.
+ */
+qx.OO.defineClass("qx.util.fsm.State", qx.core.Object,
+function(stateName, stateInfo)
+{
+ // Call our superclass' constructor
+ qx.core.Object.call(this, true);
+
+ // Save the state name
+ this.setName(stateName);
+
+ // Ensure they passed in an object
+ if (typeof(stateInfo) != "object")
+ {
+ throw new Error("State info must be an object");
+ }
+
+ // Save data from the stateInfo object
+ for (var field in stateInfo)
+ {
+ // If we find one of our properties, call its setter.
+ switch(field)
+ {
+ case "onentry":
+ this.setOnentry(stateInfo[field]);
+ break;
+
+ case "onexit":
+ this.setOnexit(stateInfo[field]);
+ break;
+
+ case "autoActionsBeforeOnentry":
+ this.setAutoActionsBeforeOnentry(stateInfo[field]);
+ break;
+
+ case "autoActionsAfterOnentry":
+ this.setAutoActionsAfterOnentry(stateInfo[field]);
+ break;
+
+ case "autoActionsBeforeOnexit":
+ this.setAutoActionsBeforeOnexit(stateInfo[field]);
+ break;
+
+ case "autoActionsAfterOnexit":
+ this.setAutoActionsAfterOnexit(stateInfo[field]);
+ break;
+
+ case "events":
+ this.setEvents(stateInfo[field]);
+ break;
+
+ default:
+ // Anything else is user-provided data for their own use. Save it.
+ this.setUserData(field, stateInfo[field]);
+
+ // Log it in case it was a typo and they intended a built-in field
+ this.debug("State " + stateName + ": " +
+ "Adding user-provided field to state: " + field);
+
+ break;
+ }
+ }
+
+
+ // Check for required but missing properties
+ if (! this.getEvents())
+ {
+ throw new Error("The events object must be provided in new state info");
+ }
+
+
+ // Initialize the transition list
+ this.transitions = { };
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/**
+ * The name of this state. This name may be used as a Transition's nextState
+ * value, or an explicit next state in the 'events' handling list in a State.
+ */
+qx.OO.addProperty(
+ {
+ name : "name",
+ type : "string"
+ });
+
+/**
+ * The onentry function for this state. This is documented in the
+ * constructor, and is typically provided through the constructor's stateInfo
+ * object, but it is also possible (but highly NOT recommended) to change this
+ * dynamically.
+ */
+qx.OO.addProperty(
+ {
+ name : "onentry",
+ defaultValue : function(fsm, event) { }
+ });
+
+/**
+ * The onexit function for this state. This is documented in the constructor,
+ * and is typically provided through the constructor's stateInfo object, but
+ * it is also possible (but highly NOT recommended) to change this
+ * dynamically.
+ */
+qx.OO.addProperty(
+ {
+ name : "onexit",
+ defaultValue : function(fsm, event) { }
+ });
+
+/**
+ * Automatic actions to take prior to calling the state's onentry function.
+ *
+ * The value passed to setAutoActionsBeforeOnentry() should like something
+ * akin to:
+ *
+ * "autoActionsBeforeOnentry" :
+ * {
+ * // The name of a function. This would become "setEnabled("
+ * "enabled" :
+ * [
+ * {
+ * // The parameter value, thus "setEnabled(true);"
+ * "parameters" : [ true ],
+ *
+ * // The function would be called on each object:
+ * // this.getObject("obj1").setEnabled(true);
+ * // this.getObject("obj2").setEnabled(true);
+ * "objects" : [ "obj1", "obj2" ]
+ *
+ * // And similarly for each object in each specified group.
+ * "groups" : [ "group1", "group2" ],
+ * }
+ * ];
+ * };
+ */
+qx.OO.addProperty(
+ {
+ name : "autoActionsBeforeOnentry",
+ defaultValue : function(fsm, event) { }
+ });
+
+/**
+ * Automatic actions to take after return from the state's onentry function.
+ *
+ * The value passed to setAutoActionsAfterOnentry() should like something akin
+ * to:
+ *
+ * "autoActionsAfterOnentry" :
+ * {
+ * // The name of a function. This would become "setEnabled("
+ * "enabled" :
+ * [
+ * {
+ * // The parameter value, thus "setEnabled(true);"
+ * "parameters" : [ true ],
+ *
+ * // The function would be called on each object:
+ * // this.getObject("obj1").setEnabled(true);
+ * // this.getObject("obj2").setEnabled(true);
+ * "objects" : [ "obj1", "obj2" ]
+ *
+ * // And similarly for each object in each specified group.
+ * "groups" : [ "group1", "group2" ],
+ * }
+ * ];
+ * };
+ */
+qx.OO.addProperty(
+ {
+ name : "autoActionsAfterOnentry",
+ defaultValue : function(fsm, event) { }
+ });
+
+/**
+ * Automatic actions to take prior to calling the state's onexit function.
+ *
+ * The value passed to setAutoActionsBeforeOnexit() should like something akin
+ * to:
+ *
+ * "autoActionsBeforeOnexit" :
+ * {
+ * // The name of a function. This would become "setEnabled("
+ * "enabled" :
+ * [
+ * {
+ * // The parameter value, thus "setEnabled(true);"
+ * "parameters" : [ true ],
+ *
+ * // The function would be called on each object:
+ * // this.getObject("obj1").setEnabled(true);
+ * // this.getObject("obj2").setEnabled(true);
+ * "objects" : [ "obj1", "obj2" ]
+ *
+ * // And similarly for each object in each specified group.
+ * "groups" : [ "group1", "group2" ],
+ * }
+ * ];
+ * };
+ */
+qx.OO.addProperty(
+ {
+ name : "autoActionsBeforeOnexit",
+ defaultValue : function(fsm, event) { }
+ });
+
+
+/**
+ * Automatic actions to take after returning from the state's onexit function.
+ *
+ * The value passed to setAutoActionsAfterOnexit() should like something akin
+ * to:
+ *
+ * "autoActionsBeforeOnexit" :
+ * {
+ * // The name of a function. This would become "setEnabled("
+ * "enabled" :
+ * [
+ * {
+ * // The parameter value, thus "setEnabled(true);"
+ * "parameters" : [ true ],
+ *
+ * // The function would be called on each object:
+ * // this.getObject("obj1").setEnabled(true);
+ * // this.getObject("obj2").setEnabled(true);
+ * "objects" : [ "obj1", "obj2" ]
+ *
+ * // And similarly for each object in each specified group.
+ * "groups" : [ "group1", "group2" ],
+ * }
+ * ];
+ * };
+ */
+qx.OO.addProperty(
+ {
+ name : "autoActionsAfterOnexit",
+ defaultValue : function(fsm, event) { }
+ });
+
+
+/**
+ * The object representing handled and blocked events for this state. This is
+ * documented in the constructor, and is typically provided through the
+ * constructor's stateInfo object, but it is also possible (but highly NOT
+ * recommended) to change this dynamically.
+ */
+qx.OO.addProperty(
+ {
+ name : "events"
+ });
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._checkName = function(propValue, propData)
+{
+ // Ensure that we got a valid state name
+ if (typeof(propValue) != "string" || propValue.length < 1)
+ {
+ throw new Error("Invalid state name");
+ }
+
+ return propValue;
+};
+
+qx.Proto._checkOnentry = function(propValue, propData)
+{
+ // Validate the onentry function
+ switch(typeof(propValue))
+ {
+ case "undefined":
+ // None provided. Convert it to a null function
+ return function(fsm, event) {};
+
+ case "function":
+ // We're cool. No changes required
+ return propValue;
+
+ default:
+ throw new Error("Invalid onentry type: " + typeof(propValue));
+ return null;
+ }
+};
+
+qx.Proto._checkOnexit = function(propValue, propData)
+{
+ // Validate the onexit function
+ switch(typeof(propValue))
+ {
+ case "undefined":
+ // None provided. Convert it to a null function
+ return function(fsm, event) {};
+
+ case "function":
+ // We're cool. No changes required
+ return propValue;
+
+ default:
+ throw new Error("Invalid onexit type: " + typeof(propValue));
+ return null;
+ }
+};
+
+qx.Proto._checkEvents = function(propValue, propData)
+{
+ // Validate that events is an object
+ if (typeof(propValue) != "object")
+ {
+ throw new Error("events must be an object");
+ }
+
+ // Confirm that each property is a valid value
+ // The property value should be one of:
+ //
+ // (a) qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE
+ //
+ // (b) qx.util.fsm.FiniteStateMachine.EventHandling.BLOCKED
+ //
+ // (c) a string containing the name of an explicit Transition to use
+ //
+ // (d) an object where each property name is the Friendly Name of an
+ // object (meaning that this rule applies if both the event and
+ // the event's target object's Friendly Name match), and its
+ // property value is one of (a), (b) or (c), above.
+ for (var e in propValue)
+ {
+ var action = propValue[e];
+ if (typeof(action) == "number" &&
+ action != qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE &&
+ action != qx.util.fsm.FiniteStateMachine.EventHandling.BLOCKED)
+ {
+ throw new Error("Invalid numeric value in events object: " +
+ e + ": " + action);
+ }
+ else if (typeof(action) == "object")
+ {
+ for (action_e in action)
+ {
+ if (typeof(action[action_e]) == "number" &&
+ action != qx.util.fsm.FiniteStateMachine.EventHandling.PREDICATE &&
+ action != qx.util.fsm.FiniteStateMachine.EventHandling.BLOCKED)
+ {
+ throw new Error("Invalid numeric value in events object " +
+ "(" + e + "): " +
+ action_e + ": " + action[action_e]);
+ }
+ else if (typeof(action[action_e]) != "string")
+ {
+ throw new Error("Invalid value in events object " +
+ "(" + e + "): " +
+ action_e + ": " + action[action_e]);
+ }
+ }
+ }
+ else if (typeof(action) != "string")
+ {
+ throw new Error("Invalid value in events object: " +
+ e + ": " + propValue[e]);
+ }
+ }
+
+ // We're cool. No changes required.
+ return propValue;
+};
+
+qx.Proto._checkAutoActionsBeforeOnentry = function(propValue, propData)
+{
+ return qx.util.fsm.FiniteStateMachine._commonCheckAutoActions(
+ "autoActionsBeforeOnentry",
+ propValue,
+ propData);
+};
+
+qx.Proto._checkAutoActionsAfterOnentry = function(propValue, propData)
+{
+ return qx.util.fsm.FiniteStateMachine._commonCheckAutoActions(
+ "autoActionsAfterOnentry",
+ propValue,
+ propData);
+};
+
+qx.Proto._checkAutoActionsBeforeOnexit = function(propValue, propData)
+{
+ return qx.util.fsm.FiniteStateMachine._commonCheckAutoActions(
+ "autoActionsBeforeOnexit",
+ propValue,
+ propData);
+};
+
+qx.Proto._checkAutoActionsAfterOnexit = function(propValue, propData)
+{
+ return qx.util.fsm.FiniteStateMachine._commonCheckAutoActions(
+ "autoActionsAfterOnexit",
+ propValue,
+ propData);
+};
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Add a transition to a state
+ *
+ * @param trans {qx.util.fsm.Transition}
+ * An object of class qx.util.fsm.Transition representing a
+ * transition which is to be a part of this state.
+ */
+qx.Proto.addTransition = function(trans)
+{
+ // Ensure that we got valid transition info
+ if (! trans instanceof qx.util.fsm.Transition)
+ {
+ throw new Error("Invalid transition: not an instance of " +
+ "qx.util.fsm.Transition");
+ }
+
+ // Add the new transition object to the state
+ this.transitions[trans.getName()] = trans;
+};
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT LISTENERS
+---------------------------------------------------------------------------
+*/
+
+
+
+/*
+---------------------------------------------------------------------------
+ CLASS CONSTANTS
+---------------------------------------------------------------------------
+*/
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ return qx.core.Object.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/Transition.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/Transition.js
new file mode 100644
index 0000000000..e417e23298
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/Transition.js
@@ -0,0 +1,384 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2006 by Derrell Lipman
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Derrell Lipman (derrell)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(util_fsm)
+#require(qx.util.fsm.FiniteStateMachine)
+
+************************************************************************ */
+
+/**
+ * Create a new possible transition from one state to another.
+ *
+ * *EXPERIMENTAL*
+ * The interface to the finite state machine, states, and transitions is
+ * experimental. It may change in non-backward-compatible ways as more
+ * experience is gained in its use.
+ *
+ * @param transitionName {string}
+ * The name of this transition, used in debug messages.
+ *
+ * @param transitionInfo {Object}
+ * An object optionally containing any of the following properties:
+ *
+ * predicate -
+ * A function which is called to determine whether this transition is
+ * acceptable. An acceptable transition will cause the transition's
+ * "ontransition" function to be run, the current state's "onexit"
+ * function to be run, and the new state's "onentry" function to be run.
+ *
+ * The predicate function's signature is function(fsm, event) and it is
+ * saved in the predicate property of the transition object. In the
+ * predicate function:
+ *
+ * fsm -
+ * The finite state machine object to which this state is attached.
+ *
+ * event -
+ * The event that caused a run of the finite state machine
+ *
+ * The predicate function should return one of the following three
+ * values:
+ *
+ * - true means the transition is acceptable
+ *
+ * - false means the transition is not acceptable, and the next
+ * transition (if one exists) should be tried to determine if it is
+ * acceptable
+ *
+ * - null means that the transition determined that no further
+ * transitions should be tried. This might be used when the
+ * transition ascertained that the event is for a target that is not
+ * available in the current state, and the event has called
+ * fsm.queueEvent() to have the event delivered upon state
+ * transition.
+ *
+ * It is possible to create a default predicate -- one that will cause a
+ * transition to be acceptable always -- by either not providing a
+ * predicate property, or by explicitely either setting the predicate
+ * property to 'true' or setting it to a function that unconditionally
+ * returns 'true'. This default transition should, of course, always be
+ * the last transition added to a state, since no transition added after
+ * it will ever be tried.
+ *
+ * nextState -
+ * The state to which we transition, if the predicate returns true
+ * (meaning the transition is acceptable). The value of nextState may
+ * be:
+ *
+ * - a string, the state name of the state to transition to
+ *
+ * - One of the constants:
+ * - qx.util.fsm.FiniteStateMachine.StateChange.CURRENT_STATE:
+ * Remain in whatever is the current state
+ * - qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK:
+ * Transition to the state at the top of the saved-state stack,
+ * and remove the top element from the saved-state stack.
+ * Elements are added to the saved-state stack using
+ * fsm.pushState(). It is an error if no state exists on the
+ * saved-state stack.
+ * - qx.util.fsm.FiniteStateMachine.StateChange.TERMINATE:
+ * TBD
+ *
+ * autoActionsBeforeOntransition -
+ * autoActionsAfterOntransition -
+ * Automatic actions which take place at the time specified by the
+ * property name. In all cases, the action takes place immediately
+ * before or after the specified function.
+ *
+ * The property value for each of these properties is an object which
+ * describes some number of functions to invoke on a set of specified
+ * objects (typically widgets).
+ *
+ * See {@see qx.util.fsm.State} for an example of autoActions.
+ *
+ * ontransition -
+ * A function which is called if the predicate function for this
+ * transition returns true. Its signature is function(fsm, event) and
+ * it is saved in the ontransition property of the transition object.
+ * In the ontransition function:
+ *
+ * fsm -
+ * The finite state machine object to which this state is attached.
+ *
+ * event -
+ * The event that caused a run of the finite state machine
+ *
+ * Additional properties may be provided in transInfo. They will not be
+ * used by the finite state machine, but will be available via
+ * this.getUserData("") during the transition's predicate
+ * and ontransition functions.
+ */
+qx.OO.defineClass("qx.util.fsm.Transition", qx.core.Object,
+function(transitionName, transitionInfo)
+{
+ // Call our superclass' constructor
+ qx.core.Object.call(this, true);
+
+ // Save the state name
+ this.setName(transitionName);
+
+ // Save data from the transitionInfo object
+ for (var field in transitionInfo)
+ {
+ // If we find one of our properties, call its setter.
+ switch(field)
+ {
+ case "predicate":
+ this.setPredicate(transitionInfo[field]);
+ break;
+
+ case "nextState":
+ this.setNextState(transitionInfo[field]);
+ break;
+
+ case "autoActionsBeforeOntransition":
+ this.setAutoActionsBeforeOntransition(transitionInfo[field]);
+ break;
+
+ case "autoActionsAfterOntransition":
+ this.setAutoActionsAfterOntransition(transitionInfo[field]);
+ break;
+
+ case "ontransition":
+ this.setOntransition(transitionInfo[field]);
+ break;
+
+ default:
+ // Anything else is user-provided data for their own use. Save it.
+ this.setUserData(field, transitionInfo[field]);
+
+ // Log it in case it was a typo and they intended a built-in field
+ this.debug("Transition " + transitionName + ": " +
+ "Adding user-provided field to transition: " + field);
+
+ break;
+ }
+ }
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/**
+ * The name of this transition
+ */
+qx.OO.addProperty(
+ {
+ name : "name",
+ type : "string"
+ });
+
+/**
+ * The predicate function for this transition. This is documented in the
+ * constructor, and is typically provided through the constructor's
+ * transitionInfo object, but it is also possible (but highly NOT recommended)
+ * to change this dynamically.
+ */
+qx.OO.addProperty(
+ {
+ name : "predicate",
+ defaultValue : function(fsm, event) { return true; }
+ });
+
+/**
+ * The state to transition to, if the predicate determines that this
+ * transition is acceptable. This is documented in the constructor, and is
+ * typically provided through the constructor's transitionInfo object, but it
+ * is also possible (but highly NOT recommended) to change this dynamically.
+ */
+qx.OO.addProperty(
+ {
+ name : "nextState",
+ defaultValue : qx.util.fsm.FiniteStateMachine.StateChange.CURRENT_STATE
+ });
+
+/**
+ * Automatic actions to take prior to calling the transition's ontransition
+ * function. This is documented in the constructor, and is typically provided
+ * through the constructor's transitionInfo object, but it is also possible
+ * (but highly NOT recommended) to change this dynamically.
+ */
+qx.OO.addProperty(
+ {
+ name : "autoActionsBeforeOntransition",
+ defaultValue : function(fsm, event) { }
+ });
+
+/**
+ * Automatic actions to take immediately after calling the transition's
+ * ontransition function. This is documented in the constructor, and is
+ * typically provided through the constructor's transitionInfo object, but it
+ * is also possible (but highly NOT recommended) to change this dynamically.
+ */
+qx.OO.addProperty(
+ {
+ name : "autoActionsAfterOntransition",
+ defaultValue : function(fsm, event) { }
+ });
+
+
+/**
+ * The function run when the transition is accepted. This is documented in
+ * the constructor, and is typically provided through the constructor's
+ * transitionInfo object, but it is also possible (but highly NOT recommended)
+ * to change this dynamically.
+ */
+qx.OO.addProperty(
+ {
+ name : "ontransition",
+ defaultValue : function(fsm, event) { }
+ });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._checkName = function(propValue, propData)
+{
+ // Ensure that we got a valid state name
+ if (typeof(propValue) != "string" || propValue.length < 1)
+ {
+ throw new Error("Invalid transition name");
+ }
+
+ return propValue;
+};
+
+qx.Proto._checkPredicate = function(propValue, propData)
+{
+ // Validate the predicate. Convert all valid types to function.
+ switch(typeof(propValue))
+ {
+ case "undefined":
+ // No predicate means predicate passes
+ return function(fsm, event) { return true; };
+
+ case "boolean":
+ // Convert boolean predicate to a function which returns that value
+ return function(fsm, event) { return propValue; };
+
+ case "function":
+ // Use user-provided function.
+ return propValue;
+
+ default:
+ throw new Error("Invalid transition predicate type: " +
+ typeof(propValue));
+ break;
+ }
+};
+
+qx.Proto._checkNextState = function(propValue, propData)
+{
+ // Validate nextState. It must be a string or a number.
+ switch(typeof(propValue))
+ {
+ case "string":
+ return propValue;
+
+ case "number":
+ // Ensure that it's one of the possible state-change constants
+ switch(propValue)
+ {
+ case qx.util.fsm.FiniteStateMachine.StateChange.CURRENT_STATE:
+ case qx.util.fsm.FiniteStateMachine.StateChange.POP_STATE_STACK:
+ case qx.util.fsm.FiniteStateMachine.StateChange.TERMINATE:
+ return propValue;
+
+ default:
+ throw new Error("Invalid transition nextState value: " +
+ propValue +
+ ": nextState must be an explicit state name, " +
+ "or one of the Fsm.StateChange constants");
+ }
+ break;
+
+ default:
+ throw new Error("Invalid transition nextState type: " + typeof(propValue));
+ break;
+ }
+};
+
+qx.Proto._checkOntransition = function(propValue, propData)
+{
+ // Validate the ontransition function. Convert undefined to function.
+ switch(typeof(propValue) )
+ {
+ case "undefined":
+ // No provided function just means do nothing. Use a null function.
+ return function(fsm, event) { };
+
+ case "function":
+ // Use user-provided function.
+ return propValue;
+
+ default:
+ throw new Error("Invalid ontransition type: " + typeof(propValue));
+ break;
+ }
+};
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT LISTENERS
+---------------------------------------------------------------------------
+*/
+
+
+
+/*
+---------------------------------------------------------------------------
+ CLASS CONSTANTS
+---------------------------------------------------------------------------
+*/
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ return qx.core.Object.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/example.txt b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/example.txt
new file mode 100644
index 0000000000..bb92f70083
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/util/fsm/example.txt
@@ -0,0 +1,210 @@
+var fsm;
+var state;
+var trans;
+
+// Create a new finite state machine called "Test Machine"
+fsm = new qx.util.finitestatemachine.Fsm("Test machine");
+
+// State S1
+state = new qx.util.finitestatemachine.State(
+ // State name
+ "S1",
+
+ // Object with state information
+ {
+ // Function called on entry to this state
+ "onentry" :
+ function(fsm, event)
+ {
+ alert("Previous state: " + fsm.getPreviousState());
+ };
+
+ // Function called on exit from this state
+ "onexit" :
+ function(fsm, event)
+ {
+ alert("Next state: " + fsm.getNextState());
+ };
+
+ // Automatic actions to take place before a (possibly) new state's onentry
+ // function is called.
+ "autoActionsBeforeOnentry" :
+ {
+ // The name of a function.
+ "setEnabled" :
+ [
+ {
+ // The parameter value(s), thus "setEnabled(true);"
+ "parameters" : [ true ],
+
+ // The function would be called on each object:
+ // this.getObject("obj1").setEnabled(true);
+ // this.getObject("obj2").setEnabled(true);
+ "objects" : [ "obj1", "obj2" ]
+
+ // And similarly for each object in each specified group.
+ "groups" : [ "group1", "group2" ],
+ }
+ ];
+
+ "setColor" :
+ [
+ {
+ "parameters" : [ "blue" ]
+ "groups" : [ "group3", "group4" ],
+ "objects" : [ "obj3", "obj4" ]
+ }
+ ];
+ };
+
+ // also available, in same format as actionsBeforeOnentry:
+ // "actionsAfterOnentry",
+ // "actionsBeforeOnexit"
+ // "actionsAfterOnexit"
+
+ // Events handled by this state, or queued for processing by a future state
+ "events" :
+ {
+ // The event type "compete" is handled by one of the transitions in this
+ // state. The transitions will be searched in order of their addition
+ // to the state, until the predicate for a transition returns true (or
+ // no predicate is specified for the transition, which is an implicit
+ // "true") That transition will be used.
+ "complete" : qx.util.finitestatemachine.Fsm.EventHandling.PREDICATE,
+
+ // The event type "interval" has two objects specified by their
+ // "friendly name". The action when an event of type "interval" occurs
+ // depends on which object was the target of the event.
+ "interval" :
+ {
+ // If the target of the event was the object to which we have given
+ // the friendly name "flash" then use a transition specified by name
+ "flash" : "S1_S3_interval_flash",
+
+ // If the target of the event was the object to which we have given
+ // the friendly name "timeout", then enqueue this event for possible
+ // processing by a future state.
+ "timeout" : qx.util.finitestatemachine.Fsm.EventHandling.BLOCKED
+ },
+
+ // The event type "execute", too, has two objects specified by their
+ // "friendly name".
+ "execute" :
+ {
+ // If the target of the event was the object to which we have given
+ // the friend name "ok", search the transitions in order looking for
+ // one where the predicate is true
+ "ok" : qx.util.finitestatemachine.Fsm.EventHandling.PREDICATE
+
+ // If the target of the event was the object to which we have given
+ // the friendly name "restart", then enqueue this event for possible
+ // processing by a future state.
+ "restart" : qx.util.finitestatemachine.Fsm.EventHandling.BLOCKED
+ }
+
+ // all events other than those which are handled or blocked are ignored.
+ };
+ });
+
+// Add State S1 to the finite state machine.
+fsm.addState(state);
+
+// Transition from S1 to S2 due to event 1
+trans = new qx.util.finitestatemachine.Transition(
+ // Transition name
+ "S1_S2_ev1",
+
+ // Object with transition information
+ {
+ // return TRUE to pass
+ "predicate" :
+ function(fsm, event)
+ {
+ var type = event.getType();
+ if (type == "somethingWeCareAbout")
+ {
+ return true;
+ }
+ else if (type == "somethingToHandleInAnotherState")
+ {
+ // reattempt event delivery following state transition
+ fsm.postponeEvent(event);
+
+ // do no further transition attempts for this event for now
+ return null;
+ }
+ else
+ {
+ return false;
+ }
+ },
+
+ // if event matches and predicate passes, pop the state stack and go to
+ // the state which was found at the top of the stack. States are added to
+ // the state stack by calling fsm.pushState() during a state's onexit
+ // function or by a transition's action function.
+ "nextState" : qx.util.finintestatemachine.Fsm.StateChange.POP_STATE_STACK,
+
+ // action taken during transisition
+ "action" :
+ function(fsm, event)
+ {
+ // save current state so a future transition can get back to
+ // this saved state
+ fsm.pushState();
+ }
+ });
+state.addTransition(trans);
+
+// Default transition (any event): remain in current state
+trans = new qx.util.finitestatemachine.Transition(
+ "S1_S1_default",
+ {
+ // true or undefined : always pass
+ "predicate" :
+ function(fsm, event)
+ {
+ // This predicate does not pass, and we return null to tell the finite
+ // state machine that no additional transitions in the transition list
+ // should be tested. (Note that the next transition is the one
+ // explicitly called for by the "interval" event on the object with
+ // friendly name "flash". We do not want a predicate search to find
+ // it.
+ return null;
+ },
+
+ // return to current state
+ "nextState" : qx.util.finitestatemacine.CURRENT_STATE,
+ });
+state.addTransition(trans);
+
+// Transition from S1 to S2 due to event 2. Since the previous transition
+// returned null in its predicate function, the only way to get to this
+// transition is when it is called out explicitly in the state's event list.
+// This one was specified for the "interval" event on the object with friendly
+// name "flash".
+trans = new qx.util.finitestatememachine.Transition(
+ "S1_S3_interval_flash",
+ {
+ // No predicate or a value of 'true' means that the predicate passes as if
+ // a predicate function returned true.
+ "predicate" : true,
+
+ // if event matches, go to this state
+ "nextState" : "S2",
+
+ // action taken during transisition
+ "action" :
+ function(fsm, event)
+ {
+ alert(this.getName() + "action function");
+ }
+ });
+state.addTransition(trans);
+
+// We would, of course, need to add state S2 since it is specified in a
+// nextState property. That is left as an exercise for the reader.
+
+
+// Initialize and start the machine running
+fsm.start();
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/xml/Core.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/xml/Core.js
new file mode 100644
index 0000000000..baf3bc1c1d
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/xml/Core.js
@@ -0,0 +1,77 @@
+/* ************************************************************************
+
+ qooxdoo - the new era of web development
+
+ http://qooxdoo.org
+
+ Copyright:
+ 2004-2006 by 1&1 Internet AG, Germany, http://www.1and1.org
+
+ License:
+ LGPL 2.1: http://www.gnu.org/licenses/lgpl.html
+
+ Authors:
+ * Sebastian Werner (wpbasti)
+ * Andreas Ecker (ecker)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.xml.Core");
+
+// Create a XML dom node
+qx.xml.Core.createXmlDom = function()
+{
+ // The Mozilla style
+ if (document.implementation && document.implementation.createDocument) {
+ return document.implementation.createDocument("", "", null);
+ }
+
+ // The Microsoft style
+ if (window.ActiveXObject) {
+ /*
+ According to information on the Microsoft XML Team's WebLog
+ it is recommended to check for availability of MSXML versions 6.0 and 3.0.
+ Other versions are included for completeness, 5.0 is excluded as it is
+ "off-by-default" in IE7 (which could trigger a goldbar).
+
+ http://blogs.msdn.com/xmlteam/archive/2006/10/23/using-the-right-version-of-msxml-in-internet-explorer.aspx
+ http://msdn.microsoft.com/library/default.asp?url=/library/en-us/xmlsdk/html/aabe29a2-bad2-4cea-8387-314174252a74.asp
+
+ See similar code in qx.lang.XmlEmu, qx.io.remote.XmlHttpTransport
+ */
+ var vServers =
+ [
+ "MSXML2.DOMDocument.6.0",
+ "MSXML2.DOMDocument.3.0",
+ "MSXML2.DOMDocument.4.0",
+ "MSXML2.DOMDocument", // v3.0
+ "MSXML.DOMDocument", // v2.x
+ "Microsoft.XMLDOM" // v2.x
+ ];
+
+ var vObject;
+
+ for (var i=0, l=vServers.length; i
+
+
+