summaryrefslogtreecommitdiff
path: root/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui
diff options
context:
space:
mode:
authorDerrell Lipman <derrell@samba.org>2007-01-03 20:17:37 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 14:36:09 -0500
commit626bb8efb0c825f332c937ffaaadc9b402079539 (patch)
tree1c95f69d157b24f64edff470143f5f55a09cfca6 /webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui
parenteeddcf8cc8eb655d7c40f1fd5f7fd422529f4f98 (diff)
downloadsamba-626bb8efb0c825f332c937ffaaadc9b402079539.tar.gz
samba-626bb8efb0c825f332c937ffaaadc9b402079539.tar.bz2
samba-626bb8efb0c825f332c937ffaaadc9b402079539.zip
r20517: re-add cleaned-up webapps
(This used to be commit 5a3d6ad0b7cf0ecf8b57b4088b19f7d4291c990b)
Diffstat (limited to 'webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui')
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Atom.js397
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/HorizontalSpacer.js31
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Image.js611
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Inline.js37
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Label.js546
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/Terminator.js187
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/basic/VerticalSpacer.js31
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/ColorPopup.js387
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js1312
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/DateChooser.js518
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ClientDocument.js450
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ClientDocumentBlocker.js39
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/Parent.js1207
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/ScrollBar.js260
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/core/Widget.js5703
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Flash.js468
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Gallery.js556
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/GalleryList.js400
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/HtmlEmbed.js112
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/IconHtmlEmbed.js134
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/Iframe.js430
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/LinkEmbed.js88
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/NodeEmbed.js48
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/TextEmbed.js121
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/Button.js200
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/CheckBox.js210
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ComboBox.js826
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ComboBoxEx.js1044
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/InputCheckSymbol.js93
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/List.js383
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ListItem.js115
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/PasswordField.js31
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/RadioButton.js185
-rwxr-xr-xwebapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/RepeatButton.js127
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/Spinner.js683
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/TextArea.js53
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/TextField.js538
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/CheckGroupBox.js39
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/GroupBox.js156
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/RadioGroupBox.js39
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/BoxLayout.js273
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/CanvasLayout.js45
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/DockLayout.js116
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/FlowLayout.js106
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/GridLayout.js864
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/HorizontalBoxLayout.js29
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/VerticalBoxLayout.js29
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellHtml.js37
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellIconHtml.js39
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellImage.js57
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellLink.js40
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ContentCellText.js40
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/Header.js294
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/HeaderCell.js255
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/HeaderSeparator.js30
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ListView.js373
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/listview/ListViewPane.js556
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Button.js354
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/CheckBox.js85
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Layout.js56
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Menu.js907
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/RadioButton.js118
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menu/Separator.js76
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menubar/Button.js28
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/menubar/MenuBar.js28
-rwxr-xr-xwebapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractBar.js129
-rwxr-xr-xwebapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractButton.js219
-rwxr-xr-xwebapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPage.js75
-rwxr-xr-xwebapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPageView.js84
-rwxr-xr-xwebapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/AbstractPane.js27
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Bar.js75
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Button.js120
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/ButtonView.js98
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Page.js30
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/buttonview/Pane.js51
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Bar.js33
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Button.js189
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Page.js30
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/Pane.js33
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/pageview/tabview/TabView.js86
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/Popup.js329
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/PopupAtom.js51
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/ToolTip.js255
-rwxr-xr-xwebapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/resizer/Resizer.js417
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/HorizontalSplitPane.js58
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/SplitPane.js759
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/splitpane/VerticalSplitPane.js58
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/AbstractDataCellRenderer.js127
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/AbstractTableModel.js150
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/BooleanDataCellRenderer.js48
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/CellEditorFactory.js62
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/CheckBoxCellEditorFactory.js43
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DataCellRenderer.js80
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DataRowRenderer.js54
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultDataCellRenderer.js189
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultDataRowRenderer.js106
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/DefaultHeaderCellRenderer.js63
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/HeaderCellRenderer.js69
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/IconDataCellRenderer.js182
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/IconHeaderCellRenderer.js84
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/RemoteTableModel.js435
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SelectionManager.js163
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SelectionModel.js427
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/SimpleTableModel.js335
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/Table.js1062
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TableColumnModel.js399
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TableModel.js243
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePane.js486
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneHeader.js276
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneModel.js179
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TablePaneScroller.js1331
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/TextFieldCellEditorFactory.js58
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Button.js47
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/CheckBox.js86
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/MenuButton.js258
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Part.js82
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/PartHandle.js35
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/RadioButton.js116
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Separator.js35
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/ToolBar.js242
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/AbstractTreeElement.js502
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/Tree.js398
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/TreeFile.js62
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/TreeFolder.js605
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/AbstractTreeElement.js529
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/Tree.js539
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeFile.js81
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeFolder.js651
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeRowStructure.js260
-rw-r--r--webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/window/Window.js1441
130 files changed, 39456 insertions, 0 deletions
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.
+ * <p>
+ * 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+|<([^>])+>|&amp;|&lt;|&gt;|&quot;|&nbsp;|&#[0-9]+;|&#x[0-9a-fA-F];]/gi, qx.ui.basic.Label._htmlToText);
+}
+
+qx.ui.basic.Label._htmlToText = function(s)
+{
+ switch(s)
+ {
+ case "&amp;":
+ return "&";
+
+ case "&lt;":
+ return "<";
+
+ case "&gt;":
+ return ">";
+
+ case "&quot;":
+ return '"';
+
+ case "&nbsp;":
+ return String.fromCharCode(160);
+
+ default:
+ if (s.substring(0, 3) == "&#x") {
+ 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 (/^<BR/gi.test(s)) {
+ return "\n";
+ }
+
+ return "";
+ }
+}
+
+qx.ui.basic.Label.textToHtml = function(s) {
+ return String(s).replace(/&|<|>|\n|\u00A0/g, qx.ui.basic.Label._textToHtml);
+}
+
+qx.ui.basic.Label._textToHtml = function(s)
+{
+ switch(s)
+ {
+ case "&":
+ return "&amp;";
+
+ case "<":
+ return "&lt;";
+
+ case ">":
+ return "&gt;";
+
+ case "\n":
+ return "<br/>";
+
+ 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 ? "(<span style=\"text-decoration:underline\">" + propValue + "</span>)" : "";
+ 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<vSplitLength; vWordIterator++)
+ {
+ vSplitTemp.push(vSplitString[vWordIterator]);
+
+ var vLabelText = vSplitTemp.join(" ") + vPost;
+ if (vUseInnerText) {
+ qx.dom.Element.setTextContent(vMeasureNode, vLabelText);
+ } else {
+ vMeasureNode.innerHTML = vLabelText;
+ }
+
+ if ((vMeasureNode.scrollWidth > 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<vCharaterLength; vCharaterIterator++)
+ {
+ vSplitTemp.push(vCharaterString.charAt(vCharaterIterator));
+
+ var vLabelText = vSplitTemp.join("") + vPost;
+ if (vUseInnerText) {
+ qx.dom.Element.setTextContent(vMeasureNode, vLabelText);
+ } else {
+ vMeasureNode.innerHTML = vLabelText;
+ }
+
+ if (vMeasureNode.scrollWidth > 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 + "<span style=\"text-decoration:underline\">" + RegExp.$7 + "</span>" + 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; i<this._fieldNumber; i++)
+ {
+ field = new qx.ui.basic.Terminator;
+
+ field.setBorder(qx.renderer.border.BorderPresets.getInstance().thinInset);
+ field.setBackgroundColor(table.values[i] || null);
+ field.setDimension(this._fieldWidth, this._fieldHeight);
+
+ field.addEventListener("mousedown", this._onFieldMouseDown, this);
+ field.addEventListener("mouseover", this._onFieldMouseOver, this);
+
+ boxLayout.add(field);
+ }
+ }
+}
+
+qx.Proto._createPreview = function()
+{
+ this._previewBox = new qx.ui.groupbox.GroupBox("Preview (Old/New)");
+ this._previewLayout = new qx.ui.layout.HorizontalBoxLayout;
+ this._selectedPreview = new qx.ui.basic.Terminator;
+ this._currentPreview = new qx.ui.basic.Terminator;
+
+ this._previewLayout.setHeight("auto");
+ this._previewLayout.setWidth("100%");
+ this._previewLayout.setSpacing(4);
+ this._previewLayout.add(this._selectedPreview, this._currentPreview);
+
+ this._previewBox.setHeight("auto");
+ this._previewBox.add(this._previewLayout);
+
+ this._layout.add(this._previewBox);
+
+ this._selectedPreview.setBorder(qx.renderer.border.BorderPresets.getInstance().inset);
+ this._selectedPreview.setWidth("1*");
+ this._selectedPreview.setHeight(24);
+
+ this._currentPreview.setBorder(qx.renderer.border.BorderPresets.getInstance().inset);
+ this._currentPreview.setWidth("1*");
+ this._currentPreview.setHeight(24);
+}
+
+qx.Proto._createSelectorBtn = function()
+{
+ this._selectorButton = new qx.ui.form.Button("Open ColorSelector");
+ this._selectorButton.setWidth(null);
+ this._selectorButton.setAllowStretchX(true);
+ this._selectorButton.addEventListener("execute", this._onSelectorButtonExecute, this);
+
+ this._layout.add(this._selectorButton);
+}
+
+qx.Proto._createColorSelector = function()
+{
+ if (this._colorSelector) {
+ return;
+ }
+
+ this._colorSelectorWindow = new qx.ui.window.Window("Color Selector");
+ this._colorSelectorWindow.setMinWidth(null);
+ this._colorSelectorWindow.setMinHeight(null);
+ this._colorSelectorWindow.setResizeable(false);
+ this._colorSelectorWindow.auto();
+
+ this._colorSelector = new qx.ui.component.ColorSelector;
+ this._colorSelector.setBorder(null);
+ this._colorSelector.setLocation(0, 0);
+ this._colorSelector.addEventListener("dialogok", this._onColorSelectorOk, this);
+ this._colorSelector.addEventListener("dialogcancel", this._onColorSelectorCancel, this);
+
+ this._colorSelectorWindow.add(this._colorSelector);
+ this._colorSelectorWindow.addToDocument();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyValue = function(propValue, propOldValue, propData)
+{
+ if (propValue === null)
+ {
+ this.setRed(null);
+ this.setGreen(null);
+ this.setBlue(null);
+ }
+ else
+ {
+ this.setRed(propValue.getRed());
+ this.setGreen(propValue.getGreen());
+ this.setBlue(propValue.getBlue());
+ };
+
+ this._selectedPreview.setBackgroundColor(propValue);
+ this._rotatePreviousColors();
+
+ return true;
+}
+
+qx.Proto._rotatePreviousColors = function()
+{
+ var vRecentTable = this._tables[this._recentTableId].values;
+ var vRecentBox = this._boxes[this._recentTableId];
+
+ if (!vRecentTable) {
+ return;
+ }
+
+ var newValue = this.getValue();
+
+ if (!newValue) {
+ return;
+ }
+
+ // use style compatible value (like the incoming value from the user or as RGB value string)
+ newValue = newValue.getStyle();
+
+ // Modifying incoming table
+ var vIndex = vRecentTable.indexOf(newValue);
+
+ if (vIndex != -1) {
+ qx.lang.Array.removeAt(vRecentTable, vIndex);
+ } else if (vRecentTable.length == this._fieldNumber) {
+ vRecentTable.shift();
+ }
+
+ vRecentTable.push(newValue);
+
+ // Sync to visible fields
+ var vFields = vRecentBox.getFrameObject().getFirstChild().getChildren();
+ for (var i=0; i<vFields.length; i++) {
+ vFields[i].setBackgroundColor(vRecentTable[i] || null);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onFieldMouseDown = function(e) {
+ this.setValue(this._currentPreview.getBackgroundColor());
+}
+
+qx.Proto._onFieldMouseOver = function(e) {
+ this._currentPreview.setBackgroundColor(e.getTarget().getBackgroundColor());
+}
+
+qx.Proto._onAutomaticBtnExecute = function(e) {
+ this.setValue(null);
+ this.hide();
+}
+
+qx.Proto._onSelectorButtonExecute = function(e)
+{
+ this._createColorSelector();
+
+ this._colorSelectorWindow.setTop(qx.dom.Location.getPageBoxTop(this._selectorButton.getElement()) + 10);
+ this._colorSelectorWindow.setLeft(qx.dom.Location.getPageBoxLeft(this._selectorButton.getElement()) + 100);
+
+ this.hide();
+
+ this._colorSelectorWindow.open();
+}
+
+qx.Proto._onColorSelectorOk = function(e)
+{
+ var sel = this._colorSelector;
+ this.setValue(qx.renderer.color.ColorCache([sel.getRed(), sel.getGreen(), sel.getBlue()]));
+ this._colorSelectorWindow.close();
+}
+
+qx.Proto._onColorSelectorCancel = function(e) {
+ this._colorSelectorWindow.close();
+}
+
+qx.Proto._onBeforeAppear = function(e) {
+ this._currentPreview.setBackgroundColor(null);
+}
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this._tables = null;
+ this._boxes = null;
+
+ if (this._layout)
+ {
+ this._layout.dispose();
+ this._layout = null;
+ }
+
+ if (this._automaticBtn)
+ {
+ this._automaticBtn.dispose();
+ this._automaticBtn = null;
+ }
+
+ if (this._previewBox)
+ {
+ this._previewBox.dispose();
+ this._previewBox = null;
+ }
+
+ if (this._previewLayout)
+ {
+ this._previewLayout.dispose();
+ this._previewLayout = null;
+ }
+
+ if (this._selectedPreview)
+ {
+ this._selectedPreview.dispose();
+ this._selectedPreview = null;
+ }
+
+ if (this._currentPreview)
+ {
+ this._currentPreview.dispose();
+ this._currentPreview = null;
+ }
+
+ if (this._selectorButton)
+ {
+ this._selectorButton.dispose();
+ this._selectorButton = null;
+ }
+
+ if (this._colorSelectorWindow)
+ {
+ this._colorSelectorWindow.dispose();
+ this._colorSelectorWindow = null;
+ }
+
+ if (this._colorSelector)
+ {
+ this._colorSelector.dispose();
+ this._colorSelector = null;
+ }
+
+ return qx.ui.popup.Popup.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js
new file mode 100644
index 0000000000..2a53f20a5d
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/ColorSelector.js
@@ -0,0 +1,1312 @@
+/* ************************************************************************
+
+ 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 typical color selector as known from native applications.
+ *
+ * Includes support for RGB and HSB color areas.
+ *
+ * @event dialogok {qx.event.type.Event}
+ * @event dialogcancel {qx.event.type.Event}
+ */
+qx.OO.defineClass("qx.ui.component.ColorSelector", qx.ui.layout.VerticalBoxLayout,
+function(vPreviousRed, vPreviousGreen, vPreviousBlue)
+{
+ qx.ui.layout.VerticalBoxLayout.call(this);
+
+ // ********************************************
+ // CREATE CHILDREN
+ // ********************************************
+
+ // 1. Base Structure (Vertical Split)
+ this._createControlBar();
+ this._createButtonBar();
+
+ // 2. Panes (Horizontal Split)
+ this._createControlPane();
+ this._createHueSaturationPane();
+ this._createBrightnessPane();
+
+ // 3. Control Pane Content
+ this._createPresetFieldSet();
+ this._createInputFieldSet();
+ this._createPreviewFieldSet();
+
+ // 4. Input FieldSet Content
+ this._createHexField();
+ this._createRgbSpinner();
+ this._createHsbSpinner();
+
+ // 5. Preview FieldSet Content
+ this._createPreviewContent();
+
+
+ // ********************************************
+ // INIT COLORS
+ // ********************************************
+
+ if (arguments.length == 3) {
+ this.setPreviousColor(vPreviousRed, vPreviousGreen, vPreviousBlue);
+ }
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "colorselector" });
+
+qx.OO.addProperty({ name : "red", type : "number", defaultValue : 255 });
+qx.OO.addProperty({ name : "green", type : "number", defaultValue : 255 });
+qx.OO.addProperty({ name : "blue", type : "number", defaultValue : 255 });
+
+qx.OO.addProperty({ name : "hue", type : "number", defaultValue : 0 });
+qx.OO.addProperty({ name : "saturation", type : "number", defaultValue : 0 });
+qx.OO.addProperty({ name : "brightness", type : "number", defaultValue : 100 });
+
+/*
+---------------------------------------------------------------------------
+ LOCALIZATION SUPPORT
+---------------------------------------------------------------------------
+*/
+
+qx.Settings.setDefault("labelOK", "OK");
+qx.Settings.setDefault("labelCancel", "Cancel");
+qx.Settings.setDefault("labelPresets", "Presets");
+qx.Settings.setDefault("labelDetails", "Details");
+qx.Settings.setDefault("labelPreview", "Preview (Old/New)");
+qx.Settings.setDefault("labelRGB", "RGB");
+qx.Settings.setDefault("labelHSB", "HSB");
+qx.Settings.setDefault("labelHex", "Hex");
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CONTEXT HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._updateContext = null;
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CREATE #1: BASE STRUCTURE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._createControlBar = function()
+{
+ this._controlBar = new qx.ui.layout.HorizontalBoxLayout;
+ this._controlBar.setHeight("auto");
+ this._controlBar.setParent(this);
+}
+
+qx.Proto._createButtonBar = function()
+{
+ this._btnbar = new qx.ui.layout.HorizontalBoxLayout;
+ this._btnbar.setHeight("auto");
+ this._btnbar.setSpacing(4);
+ this._btnbar.setHorizontalChildrenAlign("right");
+ this._btnbar.setPadding(2, 4);
+ this.add(this._btnbar);
+
+ this._btncancel = new qx.ui.form.Button(this.getSetting("labelCancel"), "icon/16/button-cancel.png");
+ this._btnok = new qx.ui.form.Button(this.getSetting("labelOK"), "icon/16/button-ok.png");
+
+ this._btncancel.addEventListener("execute", this._onButtonCancelExecute, this);
+ this._btnok.addEventListener("execute", this._onButtonOkExecute, this);
+
+ this._btnbar.add(this._btncancel, this._btnok);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CREATE #2: PANES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._createControlPane = function()
+{
+ this._controlPane = new qx.ui.layout.VerticalBoxLayout;
+ this._controlPane.setWidth("auto");
+ this._controlPane.setPadding(4);
+ this._controlPane.setPaddingBottom(7);
+ this._controlPane.setParent(this._controlBar);
+}
+
+qx.Proto._createHueSaturationPane = function()
+{
+ this._hueSaturationPane = new qx.ui.layout.CanvasLayout;
+ this._hueSaturationPane.setWidth("auto");
+ this._hueSaturationPane.setPadding(6, 4);
+ this._hueSaturationPane.setParent(this._controlBar);
+
+ this._hueSaturationPane.addEventListener("mousewheel", this._onHueSaturationPaneMouseWheel, this);
+
+ this._hueSaturationField = new qx.ui.basic.Image("widget/colorselector/huesaturation-field.jpg");
+ this._hueSaturationField.setBorder(qx.renderer.border.BorderPresets.getInstance().thinInset);
+ this._hueSaturationField.setMargin(5);
+ this._hueSaturationField.setParent(this._hueSaturationPane);
+
+ this._hueSaturationField.addEventListener("mousedown", this._onHueSaturationFieldMouseDown, this);
+
+ this._hueSaturationHandle = new qx.ui.basic.Image("widget/colorselector/huesaturation-handle.gif");
+ this._hueSaturationHandle.setLocation(0, 256);
+ this._hueSaturationHandle.setParent(this._hueSaturationPane);
+
+ this._hueSaturationHandle.addEventListener("mousedown", this._onHueSaturationHandleMouseDown, this);
+ this._hueSaturationHandle.addEventListener("mouseup", this._onHueSaturationHandleMouseUp, this);
+ this._hueSaturationHandle.addEventListener("mousemove", this._onHueSaturationHandleMouseMove, this);
+}
+
+qx.Proto._createBrightnessPane = function()
+{
+ this._brightnessPane = new qx.ui.layout.CanvasLayout;
+ this._brightnessPane.setWidth("auto");
+ this._brightnessPane.setPadding(6, 4);
+ this._brightnessPane.setParent(this._controlBar);
+
+ this._brightnessPane.addEventListener("mousewheel", this._onBrightnessPaneMouseWheel, this);
+
+ this._brightnessField = new qx.ui.basic.Image("widget/colorselector/brightness-field.jpg");
+ this._brightnessField.setBorder(qx.renderer.border.BorderPresets.getInstance().thinInset);
+ this._brightnessField.setMargin(5, 7);
+ this._brightnessField.setParent(this._brightnessPane);
+
+ this._brightnessField.addEventListener("mousedown", this._onBrightnessFieldMouseDown, this);
+
+ this._brightnessHandle = new qx.ui.basic.Image("widget/colorselector/brightness-handle.gif");
+ this._brightnessHandle.setLocation(0, 0);
+ this._brightnessHandle.setParent(this._brightnessPane);
+
+ this._brightnessHandle.addEventListener("mousedown", this._onBrightnessHandleMouseDown, this);
+ this._brightnessHandle.addEventListener("mouseup", this._onBrightnessHandleMouseUp, this);
+ this._brightnessHandle.addEventListener("mousemove", this._onBrightnessHandleMouseMove, this);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CREATE #3: CONTROL PANE CONTENT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._createPresetFieldSet = function()
+{
+ this._presetFieldSet = new qx.ui.groupbox.GroupBox("Presets");
+ this._presetFieldSet.setHeight("auto");
+ this._presetFieldSet.setParent(this._controlPane);
+
+ this._presetGrid = new qx.ui.layout.GridLayout;
+ this._presetGrid.setHorizontalSpacing(2);
+ this._presetGrid.setVerticalSpacing(2);
+ this._presetGrid.setColumnCount(11);
+ this._presetGrid.setRowCount(4);
+ this._presetGrid.setColumnWidth(0, 18);
+ this._presetGrid.setColumnWidth(1, 18);
+ this._presetGrid.setColumnWidth(2, 18);
+ this._presetGrid.setColumnWidth(3, 18);
+ this._presetGrid.setColumnWidth(4, 18);
+ this._presetGrid.setColumnWidth(5, 18);
+ this._presetGrid.setColumnWidth(6, 18);
+ this._presetGrid.setColumnWidth(7, 18);
+ this._presetGrid.setColumnWidth(8, 18);
+ this._presetGrid.setColumnWidth(9, 18);
+
+ this._presetGrid.setRowHeight(0, 16);
+ this._presetGrid.setRowHeight(1, 16);
+ this._presetFieldSet.add(this._presetGrid);
+
+ this._presetTable = [ "maroon", "red", "orange", "yellow", "olive", "purple", "fuchsia", "lime", "green", "navy", "blue", "aqua", "teal", "black", "#333", "#666", "#999", "#BBB", "#EEE", "white" ];
+
+ var colorField;
+
+ for (var i=0; i<2; i++)
+ {
+ for (var j=0; j<10; j++)
+ {
+ colorField = new qx.ui.basic.Terminator;
+ colorField.setBorder(qx.renderer.border.BorderPresets.getInstance().thinInset);
+ colorField.setBackgroundColor(this._presetTable[i*10+j]);
+ colorField.addEventListener("mousedown", this._onColorFieldClick, this);
+
+ this._presetGrid.add(colorField, j, i);
+ }
+ }
+}
+
+qx.Proto._createInputFieldSet = function()
+{
+ this._inputFieldSet = new qx.ui.groupbox.GroupBox(this.getSetting("labelDetails"));
+ this._inputFieldSet.setHeight("auto");
+ this._inputFieldSet.setParent(this._controlPane);
+
+ this._inputLayout = new qx.ui.layout.VerticalBoxLayout;
+ this._inputLayout.setHeight("auto");
+ this._inputLayout.setSpacing(10);
+ this._inputLayout.setParent(this._inputFieldSet.getFrameObject());
+}
+
+qx.Proto._createPreviewFieldSet = function()
+{
+ this._previewFieldSet = new qx.ui.groupbox.GroupBox(this.getSetting("labelPreview"));
+ this._previewFieldSet.setHeight("1*");
+ this._previewFieldSet.setParent(this._controlPane);
+
+ this._previewLayout = new qx.ui.layout.HorizontalBoxLayout;
+ this._previewLayout.setHeight("100%");
+ this._previewLayout.setLocation(0, 0);
+ this._previewLayout.setRight(0);
+ this._previewLayout.setSpacing(10);
+ this._previewLayout.setParent(this._previewFieldSet.getFrameObject());
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CREATE #4: INPUT FIELDSET CONTENT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._createHexField = function()
+{
+ this._hexLayout = new qx.ui.layout.HorizontalBoxLayout;
+ this._hexLayout.setHeight("auto");
+ this._hexLayout.setSpacing(4);
+ this._hexLayout.setVerticalChildrenAlign("middle");
+ this._hexLayout.setParent(this._inputLayout);
+
+ this._hexLabel = new qx.ui.basic.Label(this.getSetting("labelHex"));
+ this._hexLabel.setWidth(25);
+ this._hexLabel.setParent(this._hexLayout);
+
+ this._hexHelper = new qx.ui.basic.Label("#");
+ this._hexHelper.setParent(this._hexLayout);
+
+ this._hexField = new qx.ui.form.TextField("FFFFFF");
+ this._hexField.setWidth(50);
+ this._hexField.setFont('11px "Bitstream Vera Sans Mono", monospace');
+ this._hexField.setParent(this._hexLayout);
+
+ this._hexField.addEventListener("changeValue", this._onHexFieldChange, this);
+}
+
+qx.Proto._createRgbSpinner = function()
+{
+ this._rgbSpinLayout = new qx.ui.layout.HorizontalBoxLayout;
+ this._rgbSpinLayout.setHeight("auto");
+ this._rgbSpinLayout.setSpacing(4);
+ this._rgbSpinLayout.setVerticalChildrenAlign("middle");
+ this._rgbSpinLayout.setParent(this._inputLayout);
+
+ this._rgbSpinLabel = new qx.ui.basic.Label(this.getSetting("labelRGB"));
+ this._rgbSpinLabel.setWidth(25);
+ this._rgbSpinLabel.setParent(this._rgbSpinLayout);
+
+ this._rgbSpinRed = new qx.ui.form.Spinner(0, 255, 255);
+ this._rgbSpinRed.setWidth(50);
+
+ this._rgbSpinGreen = new qx.ui.form.Spinner(0, 255, 255);
+ this._rgbSpinGreen.setWidth(50);
+
+ this._rgbSpinBlue = new qx.ui.form.Spinner(0, 255, 255);
+ this._rgbSpinBlue.setWidth(50);
+
+ this._rgbSpinLayout.add(this._rgbSpinRed, this._rgbSpinGreen, this._rgbSpinBlue);
+
+ this._rgbSpinRed.addEventListener("change", this._setRedFromSpinner, this);
+ this._rgbSpinGreen.addEventListener("change", this._setGreenFromSpinner, this);
+ this._rgbSpinBlue.addEventListener("change", this._setBlueFromSpinner, this);
+}
+
+qx.Proto._createHsbSpinner = function()
+{
+ this._hsbSpinLayout = new qx.ui.layout.HorizontalBoxLayout;
+ this._hsbSpinLayout.setHeight("auto");
+ this._hsbSpinLayout.setSpacing(4);
+ this._hsbSpinLayout.setVerticalChildrenAlign("middle");
+ this._hsbSpinLayout.setParent(this._inputLayout);
+
+ this._hsbSpinLabel = new qx.ui.basic.Label(this.getSetting("labelHSB"));
+ this._hsbSpinLabel.setWidth(25);
+ this._hsbSpinLayout.add(this._hsbSpinLabel);
+
+ this._hsbSpinHue = new qx.ui.form.Spinner(0, 0, 360);
+ this._hsbSpinHue.setWidth(50);
+
+ this._hsbSpinSaturation = new qx.ui.form.Spinner(0, 0, 100);
+ this._hsbSpinSaturation.setWidth(50);
+
+ this._hsbSpinBrightness = new qx.ui.form.Spinner(0, 100, 100);
+ this._hsbSpinBrightness.setWidth(50);
+
+ this._hsbSpinLayout.add(this._hsbSpinHue, this._hsbSpinSaturation, this._hsbSpinBrightness);
+
+ this._hsbSpinHue.addEventListener("change", this._setHueFromSpinner, this);
+ this._hsbSpinSaturation.addEventListener("change", this._setSaturationFromSpinner, this);
+ this._hsbSpinBrightness.addEventListener("change", this._setBrightnessFromSpinner, this);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CREATE #5: PREVIEW CONTENT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._createPreviewContent = function()
+{
+ this._oldColorPreview = new qx.ui.basic.Terminator;
+ this._oldColorPreview.setBorder(qx.renderer.border.BorderPresets.getInstance().thinInset);
+ this._oldColorPreview.setWidth("1*");
+ this._oldColorPreview.setBackgroundImage("static/image/dotted_white.gif");
+ this._oldColorPreview.setParent(this._previewLayout);
+
+ this._newColorPreview = new qx.ui.basic.Terminator;
+ this._newColorPreview.setBorder(qx.renderer.border.BorderPresets.getInstance().thinInset);
+ this._newColorPreview.setWidth("1*");
+ this._newColorPreview.setBackgroundColor("white");
+ this._newColorPreview.setParent(this._previewLayout);
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ RGB MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyRed = function(propValue, propOldValue, propData)
+{
+ if (this._updateContext === null) {
+ this._updateContext = "redModifier";
+ }
+
+ if (this._updateContext !== "rgbSpinner") {
+ this._rgbSpinRed.setValue(propValue);
+ }
+
+ if (this._updateContext !== "hexField") {
+ this._setHexFromRgb();
+ }
+
+ switch(this._updateContext)
+ {
+ case "rgbSpinner":
+ case "hexField":
+ case "redModifier":
+ this._setHueFromRgb();
+ }
+
+ this._setPreviewFromRgb();
+
+ if (this._updateContext === "redModifier") {
+ this._updateContext = null;
+ }
+
+ return true;
+}
+
+qx.Proto._modifyGreen = function(propValue, propOldValue, propData)
+{
+ if (this._updateContext === null) {
+ this._updateContext = "greenModifier";
+ }
+
+ if (this._updateContext !== "rgbSpinner") {
+ this._rgbSpinGreen.setValue(propValue);
+ }
+
+ if (this._updateContext !== "hexField") {
+ this._setHexFromRgb();
+ }
+
+ switch(this._updateContext)
+ {
+ case "rgbSpinner":
+ case "hexField":
+ case "greenModifier":
+ this._setHueFromRgb();
+ }
+
+ this._setPreviewFromRgb();
+
+ if (this._updateContext === "greenModifier") {
+ this._updateContext = null;
+ }
+
+ return true;
+}
+
+qx.Proto._modifyBlue = function(propValue, propOldValue, propData)
+{
+ if (this._updateContext === null) {
+ this._updateContext = "blueModifier";
+ }
+
+ if (this._updateContext !== "rgbSpinner") {
+ this._rgbSpinBlue.setValue(propValue);
+ }
+
+ if (this._updateContext !== "hexField") {
+ this._setHexFromRgb();
+ }
+
+ switch(this._updateContext)
+ {
+ case "rgbSpinner":
+ case "hexField":
+ case "blueModifier":
+ this._setHueFromRgb();
+ }
+
+ this._setPreviewFromRgb();
+
+ if (this._updateContext === "blueModifier") {
+ this._updateContext = null;
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HSB MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyHue = function(propValue, propOldValue, propData)
+{
+ if (this._updateContext === null) {
+ this._updateContext = "hueModifier";
+ }
+
+ if (this._updateContext !== "hsbSpinner") {
+ this._hsbSpinHue.setValue(propValue);
+ }
+
+ if (this._updateContext !== "hueSaturationField")
+ {
+ if (this._hueSaturationHandle.isCreated())
+ {
+ this._hueSaturationHandle._applyRuntimeLeft(Math.round(propValue / 1.40625) + this._hueSaturationPane.getPaddingLeft());
+ }
+ else
+ {
+ this._hueSaturationHandle.setLeft(Math.round(propValue / 1.40625));
+ }
+ }
+
+ switch(this._updateContext)
+ {
+ case "hsbSpinner":
+ case "hueSaturationField":
+ case "hueModifier":
+ this._setRgbFromHue();
+ }
+
+ if (this._updateContext === "hueModifier") {
+ this._updateContext = null;
+ }
+
+ return true;
+}
+
+qx.Proto._modifySaturation = function(propValue, propOldValue, propData)
+{
+ if (this._updateContext === null) {
+ this._updateContext = "saturationModifier";
+ }
+
+ if (this._updateContext !== "hsbSpinner") {
+ this._hsbSpinSaturation.setValue(propValue);
+ }
+
+ if (this._updateContext !== "hueSaturationField")
+ {
+ if (this._hueSaturationHandle.isCreated())
+ {
+ this._hueSaturationHandle._applyRuntimeTop(256 - Math.round(propValue * 2.56) + this._hueSaturationPane.getPaddingTop());
+ }
+ else
+ {
+ this._hueSaturationHandle.setTop(256 - Math.round(propValue * 2.56));
+ }
+ }
+
+ switch(this._updateContext)
+ {
+ case "hsbSpinner":
+ case "hueSaturationField":
+ case "saturationModifier":
+ this._setRgbFromHue();
+ }
+
+ if (this._updateContext === "saturationModifier") {
+ this._updateContext = null;
+ }
+
+ return true;
+}
+
+qx.Proto._modifyBrightness = function(propValue, propOldValue, propData)
+{
+ if (this._updateContext === null) {
+ this._updateContext = "brightnessModifier";
+ }
+
+ if (this._updateContext !== "hsbSpinner") {
+ this._hsbSpinBrightness.setValue(propValue);
+ }
+
+ if (this._updateContext !== "brightnessField")
+ {
+ var topValue = 256 - Math.round(propValue * 2.56);
+
+ if (this._brightnessHandle.isCreated())
+ {
+ this._brightnessHandle._applyRuntimeTop(topValue + this._brightnessPane.getPaddingTop());
+ }
+ else
+ {
+ this._brightnessHandle.setTop(topValue);
+ }
+ }
+
+ switch(this._updateContext)
+ {
+ case "hsbSpinner":
+ case "brightnessField":
+ case "brightnessModifier":
+ this._setRgbFromHue();
+ }
+
+ if (this._updateContext === "brightnessModifier") {
+ this._updateContext = null;
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ BRIGHTNESS IMPLEMENTATION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onBrightnessHandleMouseDown = function(e)
+{
+ // Activate Capturing
+ this._brightnessHandle.setCapture(true);
+
+ // Calculate subtract: Position of Brightness Field - Current Mouse Offset
+ this._brightnessSubtract = qx.dom.Location.getPageOuterTop(this._brightnessField.getElement()) + (e.getPageY() - qx.dom.Location.getPageBoxTop(this._brightnessHandle.getElement()));
+
+ // Block field event handling
+ e.setPropagationStopped(true);
+}
+
+qx.Proto._onBrightnessHandleMouseUp = function(e)
+{
+ // Disabling capturing
+ this._brightnessHandle.setCapture(false);
+}
+
+qx.Proto._onBrightnessHandleMouseMove = function(e)
+{
+ // Update if captured currently (through previous mousedown)
+ if (this._brightnessHandle.getCapture()) {
+ this._setBrightnessOnFieldEvent(e);
+ }
+}
+
+qx.Proto._onBrightnessFieldMouseDown = function(e)
+{
+ // Calculate substract: Half height of handler
+ this._brightnessSubtract = qx.dom.Location.getPageOuterTop(this._brightnessField.getElement()) + Math.round(qx.dom.Dimension.getBoxHeight(this._brightnessHandle.getElement()) / 2);
+
+ // Update
+ this._setBrightnessOnFieldEvent(e);
+
+ // Afterwards: Activate Capturing for handle
+ this._brightnessHandle.setCapture(true);
+}
+
+qx.Proto._onBrightnessPaneMouseWheel = function(e) {
+ this.setBrightness(qx.lang.Number.limit(this.getBrightness() + e.getWheelDelta(), 0, 100));
+}
+
+qx.Proto._setBrightnessOnFieldEvent = function(e)
+{
+ var vValue = qx.lang.Number.limit(e.getPageY() - this._brightnessSubtract, 0, 256);
+
+ this._updateContext = "brightnessField";
+
+ if (this._brightnessHandle.isCreated())
+ {
+ this._brightnessHandle._applyRuntimeTop(vValue + this._brightnessPane.getPaddingTop());
+ }
+ else
+ {
+ this._brightnessHandle.setTop(vValue);
+ }
+
+ this.setBrightness(100-Math.round(vValue / 2.56));
+
+ this._updateContext = null;
+}
+
+qx.Proto._onButtonOkExecute = function(e) {
+ this.createDispatchEvent("dialogok");
+}
+
+qx.Proto._onButtonCancelExecute = function(e) {
+ this.createDispatchEvent("dialogcancel");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HUE/SATURATION IMPLEMENTATION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onHueSaturationHandleMouseDown = function(e)
+{
+ // Activate Capturing
+ this._hueSaturationHandle.setCapture(true);
+
+ // Calculate subtract: Position of HueSaturation Field - Current Mouse Offset
+ this._hueSaturationSubtractTop = qx.dom.Location.getPageOuterTop(this._hueSaturationField.getElement()) + (e.getPageY() - qx.dom.Location.getPageBoxTop(this._hueSaturationHandle.getElement()));
+ this._hueSaturationSubtractLeft = qx.dom.Location.getPageOuterLeft(this._hueSaturationField.getElement()) + (e.getPageX() - qx.dom.Location.getPageBoxLeft(this._hueSaturationHandle.getElement()));
+
+ // Block field event handling
+ e.setPropagationStopped(true);
+}
+
+qx.Proto._onHueSaturationHandleMouseUp = function(e)
+{
+ // Disabling capturing
+ this._hueSaturationHandle.setCapture(false);
+}
+
+qx.Proto._onHueSaturationHandleMouseMove = function(e)
+{
+ // Update if captured currently (through previous mousedown)
+ if (this._hueSaturationHandle.getCapture()) {
+ this._setHueSaturationOnFieldEvent(e);
+ }
+}
+
+qx.Proto._onHueSaturationFieldMouseDown = function(e)
+{
+ // Calculate substract: Half width/height of handler
+ this._hueSaturationSubtractTop = qx.dom.Location.getPageOuterTop(this._hueSaturationField.getElement()) + Math.round(qx.dom.Dimension.getBoxHeight(this._hueSaturationHandle.getElement()) / 2);
+ this._hueSaturationSubtractLeft = qx.dom.Location.getPageOuterLeft(this._hueSaturationField.getElement()) + Math.round(qx.dom.Dimension.getBoxWidth(this._hueSaturationHandle.getElement()) / 2);
+
+ // Update
+ this._setHueSaturationOnFieldEvent(e);
+
+ // Afterwards: Activate Capturing for handle
+ this._hueSaturationHandle.setCapture(true);
+}
+
+qx.Proto._onHueSaturationPaneMouseWheel = function(e) {
+ this.setSaturation(qx.lang.Number.limit(this.getSaturation() + e.getWheelDelta(), 0, 100));
+}
+
+qx.Proto._setHueSaturationOnFieldEvent = function(e)
+{
+ var vTop = qx.lang.Number.limit(e.getPageY() - this._hueSaturationSubtractTop, 0, 256);
+ var vLeft = qx.lang.Number.limit(e.getPageX() - this._hueSaturationSubtractLeft, 0, 256);
+
+ if (this._hueSaturationHandle.isCreated())
+ {
+ this._hueSaturationHandle._applyRuntimeTop(vTop + this._hueSaturationPane.getPaddingTop());
+ this._hueSaturationHandle._applyRuntimeLeft(vLeft + this._hueSaturationPane.getPaddingLeft());
+ }
+ else
+ {
+ this._hueSaturationHandle.setTop(vTop);
+ this._hueSaturationHandle.setLeft(vLeft);
+ }
+
+ this._updateContext = "hueSaturationField";
+
+ this.setSaturation(100-Math.round(vTop / 2.56));
+ this.setHue(Math.round(vLeft * 1.40625));
+
+ this._updateContext = null;
+}
+
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ RGB SPINNER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._setRedFromSpinner = function()
+{
+ if (this._updateContext !== null) {
+ return;
+ }
+
+ this._updateContext = "rgbSpinner";
+ this.setRed(this._rgbSpinRed.getValue());
+ this._updateContext = null;
+}
+
+qx.Proto._setGreenFromSpinner = function()
+{
+ if (this._updateContext !== null) {
+ return;
+ }
+
+ this._updateContext = "rgbSpinner";
+ this.setGreen(this._rgbSpinGreen.getValue());
+ this._updateContext = null;
+}
+
+qx.Proto._setBlueFromSpinner = function()
+{
+ if (this._updateContext !== null) {
+ return;
+ }
+
+ this._updateContext = "rgbSpinner";
+ this.setBlue(this._rgbSpinBlue.getValue());
+ this._updateContext = null;
+}
+
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HSB SPINNER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._setHueFromSpinner = function()
+{
+ if (this._updateContext !== null) {
+ return;
+ }
+
+ this._updateContext = "hsbSpinner";
+ this.setHue(this._hsbSpinHue.getValue());
+ this._updateContext = null;
+}
+
+qx.Proto._setSaturationFromSpinner = function()
+{
+ if (this._updateContext !== null) {
+ return;
+ }
+
+ this._updateContext = "hsbSpinner";
+ this.setSaturation(this._hsbSpinSaturation.getValue());
+ this._updateContext = null;
+}
+
+qx.Proto._setBrightnessFromSpinner = function()
+{
+ if (this._updateContext !== null) {
+ return;
+ }
+
+ this._updateContext = "hsbSpinner";
+ this.setBrightness(this._hsbSpinBrightness.getValue());
+ this._updateContext = null;
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HEX FIELD
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onHexFieldChange = function(e)
+{
+ if (this._updateContext !== null) {
+ return;
+ }
+
+ var vValue = this._hexField.getValue().toLowerCase();
+
+ var vRed = 0;
+ var vGreen = 0;
+ var vBlue = 0;
+
+ switch(vValue.length)
+ {
+ case 3:
+ vRed = qx.renderer.color.Color.m_rgb[vValue.charAt(0)];
+ vGreen = qx.renderer.color.Color.m_rgb[vValue.charAt(1)];
+ vBlue = qx.renderer.color.Color.m_rgb[vValue.charAt(2)];
+
+ vRed = (vRed * 16) + vRed;
+ vGreen = (vGreen * 16) + vGreen;
+ vBlue = (vBlue * 16) + vBlue;
+
+ break;
+
+ case 6:
+ vRed = (qx.renderer.color.Color.m_rgb[vValue.charAt(0)] * 16) + qx.renderer.color.Color.m_rgb[vValue.charAt(1)];
+ vGreen = (qx.renderer.color.Color.m_rgb[vValue.charAt(2)] * 16) + qx.renderer.color.Color.m_rgb[vValue.charAt(3)];
+ vBlue = (qx.renderer.color.Color.m_rgb[vValue.charAt(4)] * 16) + qx.renderer.color.Color.m_rgb[vValue.charAt(5)];
+
+ break;
+
+ default:
+ return false;
+ }
+
+ this._updateContext = "hexField";
+
+ this.setRed(vRed);
+ this.setGreen(vGreen);
+ this.setBlue(vBlue);
+
+ this._updateContext = null;
+}
+
+qx.Proto._setHexFromRgb = function() {
+ this._hexField.setValue(qx.lang.String.pad(this.getRed().toString(16).toUpperCase(), 2) + qx.lang.String.pad(this.getGreen().toString(16).toUpperCase(), 2) + qx.lang.String.pad(this.getBlue().toString(16).toUpperCase(), 2));
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ COLOR FIELD
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onColorFieldClick = function(e)
+{
+ var vColor = e.getTarget().getBackgroundColor();
+
+ if (!vColor) {
+ return this.error("Missing backgroundColor value for field: " + e.getTarget());
+ }
+
+ this.setRed(vColor.getRed());
+ this.setGreen(vColor.getGreen());
+ this.setBlue(vColor.getBlue());
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ RGB/HSB SYNC
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._setHueFromRgb = function()
+{
+ switch(this._updateContext)
+ {
+ case "hsbSpinner":
+ case "hueSaturationField":
+ case "brightnessField":
+ break;
+
+ default:
+ var vHsb = qx.util.ColorUtil.rgb2hsb(this.getRed(), this.getGreen(), this.getBlue());
+
+ this.setHue(vHsb.hue);
+ this.setSaturation(vHsb.saturation);
+ this.setBrightness(vHsb.brightness);
+ }
+}
+
+qx.Proto._setRgbFromHue = function()
+{
+ switch(this._updateContext)
+ {
+ case "rgbSpinner":
+ case "hexField":
+ break;
+
+ default:
+ var vRgb = qx.util.ColorUtil.hsb2rgb(this.getHue(), this.getSaturation(), this.getBrightness());
+
+ this.setRed(vRgb.red);
+ this.setGreen(vRgb.green);
+ this.setBlue(vRgb.blue);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PREVIEW SYNC
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._setPreviewFromRgb = function()
+{
+ if (this._newColorPreview.isCreated())
+ {
+ // faster (omit qx.renderer.color.Color instances)
+ this._newColorPreview._style.backgroundColor = qx.renderer.color.Color.rgb2style(this.getRed(), this.getGreen(), this.getBlue());
+ }
+ else
+ {
+ this._newColorPreview.setBackgroundColor([this.getRed(), this.getGreen(), this.getBlue()]);
+ }
+}
+
+qx.Proto.setPreviousColor = function(vRed, vGreen, vBlue)
+{
+ this._oldColorPreview.setBackgroundImage(null);
+ this._oldColorPreview.setBackgroundColor([vRed, vGreen, vBlue]);
+
+ this.setRed(vRed);
+ this.setGreen(vGreen);
+ this.setBlue(vBlue);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (this._controlBar)
+ {
+ this._controlBar.dispose();
+ this._controlBar = null;
+ }
+
+ if (this._btnbar)
+ {
+ this._btnbar.dispose();
+ this._btnbar = null;
+ }
+
+ if (this._btncancel)
+ {
+ this._btncancel.dispose();
+ this._btncancel = null;
+ }
+
+ if (this._btnok)
+ {
+ this._btnok.dispose();
+ this._btnok = null;
+ }
+
+ if (this._controlPane)
+ {
+ this._controlPane.dispose();
+ this._controlPane = null;
+ }
+
+ if (this._hueSaturationPane)
+ {
+ this._hueSaturationPane.removeEventListener("mousewheel", this._onHueSaturationPaneMouseWheel, this);
+ this._hueSaturationPane.dispose();
+ this._hueSaturationPane = null;
+ }
+
+ if (this._hueSaturationField)
+ {
+ this._hueSaturationField.removeEventListener("mousedown", this._onHueSaturationFieldMouseDown, this);
+ this._hueSaturationField.dispose();
+ this._hueSaturationField = null;
+ }
+
+ if (this._hueSaturationHandle)
+ {
+ this._hueSaturationHandle.removeEventListener("mousedown", this._onHueSaturationHandleMouseDown, this);
+ this._hueSaturationHandle.removeEventListener("mouseup", this._onHueSaturationHandleMouseUp, this);
+ this._hueSaturationHandle.removeEventListener("mousemove", this._onHueSaturationHandleMouseMove, this);
+ this._hueSaturationHandle.dispose();
+ this._hueSaturationHandle = null;
+ }
+
+ if (this._brightnessPane)
+ {
+ this._brightnessPane.removeEventListener("mousewheel", this._onBrightnessPaneMouseWheel, this);
+ this._brightnessPane.dispose();
+ this._brightnessPane = null;
+ }
+
+ if (this._brightnessField)
+ {
+ this._brightnessField.removeEventListener("mousedown", this._onBrightnessFieldMouseDown, this);
+ this._brightnessField.dispose();
+ this._brightnessField = null;
+ }
+
+ if (this._brightnessHandle)
+ {
+ this._brightnessHandle.removeEventListener("mousedown", this._onBrightnessHandleMouseDown, this);
+ this._brightnessHandle.removeEventListener("mouseup", this._onBrightnessHandleMouseUp, this);
+ this._brightnessHandle.removeEventListener("mousemove", this._onBrightnessHandleMouseMove, this);
+ this._brightnessHandle.dispose();
+ this._brightnessHandle = null;
+ }
+
+ if (this._presetFieldSet)
+ {
+ this._presetFieldSet.dispose();
+ this._presetFieldSet = null;
+ }
+
+ if (this._presetGrid)
+ {
+ this._presetGrid.dispose();
+ this._presetGrid = null;
+ }
+
+ this._presetTable = null;
+
+ if (this._inputFieldSet)
+ {
+ this._inputFieldSet.dispose();
+ this._inputFieldSet = null;
+ }
+
+ if (this._inputLayout)
+ {
+ this._inputLayout.dispose();
+ this._inputLayout = null;
+ }
+
+ if (this._previewFieldSet)
+ {
+ this._previewFieldSet.dispose();
+ this._previewFieldSet = null;
+ }
+
+ if (this._previewLayout)
+ {
+ this._previewLayout.dispose();
+ this._previewLayout = null;
+ }
+
+ if (this._hexLayout)
+ {
+ this._hexLayout.dispose();
+ this._hexLayout = null;
+ }
+
+ if (this._hexLabel)
+ {
+ this._hexLabel.dispose();
+ this._hexLabel = null;
+ }
+
+ if (this._hexHelper)
+ {
+ this._hexHelper.dispose();
+ this._hexHelper = null;
+ }
+
+ if (this._hexField)
+ {
+ this._hexField.addEventListener("changeValue", this._onHexFieldChange, this);
+ this._hexField.dispose();
+ this._hexField = null;
+ }
+
+ if (this._rgbSpinLayout)
+ {
+ this._rgbSpinLayout.dispose();
+ this._rgbSpinLayout = null;
+ }
+
+ if (this._rgbSpinLabel)
+ {
+ this._rgbSpinLabel.dispose();
+ this._rgbSpinLabel = null;
+ }
+
+ if (this._rgbSpinRed)
+ {
+ this._rgbSpinRed.removeEventListener("change", this._setRedFromSpinner, this);
+ this._rgbSpinRed.dispose();
+ this._rgbSpinRed = null;
+ }
+
+ if (this._rgbSpinGreen)
+ {
+ this._rgbSpinGreen.removeEventListener("change", this._setGreenFromSpinner, this);
+ this._rgbSpinGreen.dispose();
+ this._rgbSpinGreen = null;
+ }
+
+ if (this._rgbSpinBlue)
+ {
+ this._rgbSpinBlue.removeEventListener("change", this._setBlueFromSpinner, this);
+ this._rgbSpinBlue.dispose();
+ this._rgbSpinBlue = null;
+ }
+
+ if (this._hsbSpinLayout)
+ {
+ this._hsbSpinLayout.dispose();
+ this._hsbSpinLayout = null;
+ }
+
+ if (this._hsbSpinLabel)
+ {
+ this._hsbSpinLabel.dispose();
+ this._hsbSpinLabel = null;
+ }
+
+ if (this._hsbSpinHue)
+ {
+ this._hsbSpinHue.removeEventListener("change", this._setHueFromSpinner, this);
+ this._hsbSpinHue.dispose();
+ this._hsbSpinHue = null;
+ }
+
+ if (this._hsbSpinSaturation)
+ {
+ this._hsbSpinSaturation.removeEventListener("change", this._setSaturationFromSpinner, this);
+ this._hsbSpinSaturation.dispose();
+ this._hsbSpinSaturation = null;
+ }
+
+ if (this._hsbSpinBrightness)
+ {
+ this._hsbSpinBrightness.removeEventListener("change", this._setBrightnessFromSpinner, this);
+ this._hsbSpinBrightness.dispose();
+ this._hsbSpinBrightness = null;
+ }
+
+ if (this._oldColorPreview)
+ {
+ this._oldColorPreview.dispose();
+ this._oldColorPreview = null;
+ }
+
+ if (this._newColorPreview)
+ {
+ this._newColorPreview.dispose();
+ this._newColorPreview = null;
+ }
+
+ return qx.ui.layout.VerticalBoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/DateChooser.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/DateChooser.js
new file mode 100644
index 0000000000..fdfb2af65e
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/component/DateChooser.js
@@ -0,0 +1,518 @@
+/* ************************************************************************
+
+ 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)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#require(qx.util.format.DateFormat)
+
+************************************************************************ */
+
+/**
+ * Shows calendar and allows choosing a date.
+ *
+ * @param date {Date ? null} The initial date to show. If <code>null</code>
+ * 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<vLength; i++)
+ {
+ var vChild = vChildren[i];
+ if (vChild._isDisplayable) {
+ vVisible.push(vChild);
+ }
+ }
+
+ return vVisible;
+}
+
+/*!
+ Get length of visible children
+*/
+qx.Proto.getVisibleChildrenLength = function() {
+ return this.getVisibleChildren().length;
+}
+
+/*!
+ Check if the widget has any visible children
+*/
+qx.Proto.hasVisibleChildren = function() {
+ return this.getVisibleChildrenLength() > 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<l; i++)
+ {
+ vWidget = arguments[i];
+
+ if (!(vWidget instanceof qx.ui.core.Parent) && !(vWidget instanceof qx.ui.basic.Terminator))
+ {
+ throw new Error("Invalid Widget: " + vWidget);
+ }
+ else
+ {
+ vWidget.setParent(this);
+ }
+ }
+
+ return this;
+}
+
+qx.Proto.addAt = function(vChild, vIndex)
+{
+ if (qx.util.Validation.isInvalidNumber(vIndex) || vIndex == -1) {
+ throw new Error("Not a valid index for addAt(): " + vIndex);
+ }
+
+ if (vChild.getParent() == this)
+ {
+ var vChildren = this.getChildren();
+ var vOldIndex = vChildren.indexOf(vChild);
+
+ if (vOldIndex != vIndex)
+ {
+ if (vOldIndex != -1) {
+ qx.lang.Array.removeAt(vChildren, vOldIndex);
+ }
+
+ qx.lang.Array.insertAt(vChildren, vChild, vIndex);
+
+ if (this._initialLayoutDone)
+ {
+ this._invalidateVisibleChildren();
+ this.getLayoutImpl().updateChildrenOnMoveChild(vChild, vIndex, vOldIndex);
+ }
+ }
+ }
+ else
+ {
+ vChild._insertIndex = vIndex;
+ vChild.setParent(this);
+ }
+}
+
+qx.Proto.addAtBegin = function(vChild) {
+ return this.addAt(vChild, 0);
+}
+
+qx.Proto.addAtEnd = function(vChild)
+{
+ // we need to fix here, when the child is already inside myself, but
+ // want to change its position
+ var vLength = this.getChildrenLength();
+ return this.addAt(vChild, vChild.getParent() == this ? vLength - 1 : vLength);
+}
+
+/*!
+ Add a widget before another already inserted child
+*/
+qx.Proto.addBefore = function(vChild, vBefore)
+{
+ var vChildren = this.getChildren();
+ var vTargetIndex = vChildren.indexOf(vBefore);
+
+ if (vTargetIndex == -1) {
+ throw new Error("Child to add before: " + vBefore + " is not inside this parent.");
+ }
+
+ var vSourceIndex = vChildren.indexOf(vChild);
+
+ if (vSourceIndex == -1 || vSourceIndex > 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<l; i++)
+ {
+ vWidget = arguments[i];
+
+ if (!(vWidget instanceof qx.ui.core.Parent) && !(vWidget instanceof qx.ui.basic.Terminator))
+ {
+ throw new Error("Invalid Widget: " + vWidget);
+ }
+ else if (vWidget.getParent() == this)
+ {
+ vWidget.setParent(null);
+ }
+ }
+}
+
+qx.Proto.removeAt = function(vIndex)
+{
+ var vChild = this.getChildren()[vIndex];
+
+ if (vChild)
+ {
+ delete vChild._insertIndex;
+
+ vChild.setParent(null);
+ }
+}
+
+/*!
+ Remove all childrens.
+*/
+qx.Proto.removeAll = function()
+{
+ var cs = this.getChildren();
+ var co = cs[0];
+
+ while (co)
+ {
+ this.remove(co);
+ co = cs[0];
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN MANAGMENT: FIRST CHILD
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getFirstChild = function() {
+ return qx.lang.Array.getFirst(this.getChildren());
+}
+
+qx.Proto.getFirstVisibleChild = function() {
+ return qx.lang.Array.getFirst(this.getVisibleChildren());
+}
+
+qx.Proto.getFirstActiveChild = function(vIgnoreClasses) {
+ return qx.ui.core.Widget.getActiveSiblingHelper(null, this, 1, vIgnoreClasses, "first");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN MANAGMENT: LAST CHILD
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getLastChild = function() {
+ return qx.lang.Array.getLast(this.getChildren());
+}
+
+qx.Proto.getLastVisibleChild = function() {
+ return qx.lang.Array.getLast(this.getVisibleChildren());
+}
+
+qx.Proto.getLastActiveChild = function(vIgnoreClasses) {
+ return qx.ui.core.Widget.getActiveSiblingHelper(null, this, -1, vIgnoreClasses, "last");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN MANAGMENT: LOOP UTILS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.forEachChild = function(vFunc)
+{
+ var ch=this.getChildren(), chc, i=-1;
+ while(chc=ch[++i]) {
+ vFunc.call(chc, i);
+ }
+}
+
+qx.Proto.forEachVisibleChild = function(vFunc)
+{
+ var ch=this.getVisibleChildren(), chc, i=-1;
+ while(chc=ch[++i]) {
+ vFunc.call(chc, i);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEAR/DISAPPEAR MESSAGES FOR CHILDREN
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._beforeAppear = function()
+{
+ qx.ui.core.Widget.prototype._beforeAppear.call(this);
+
+ this.forEachVisibleChild(function() {
+ if (this.isAppearRelevant()) {
+ this._beforeAppear();
+ }
+ });
+}
+
+qx.Proto._afterAppear = function()
+{
+ qx.ui.core.Widget.prototype._afterAppear.call(this);
+
+ this.forEachVisibleChild(function() {
+ if (this.isAppearRelevant()) {
+ this._afterAppear();
+ }
+ });
+}
+
+qx.Proto._beforeDisappear = function()
+{
+ qx.ui.core.Widget.prototype._beforeDisappear.call(this);
+
+ this.forEachVisibleChild(function() {
+ if (this.isAppearRelevant()) {
+ this._beforeDisappear();
+ }
+ });
+}
+
+qx.Proto._afterDisappear = function()
+{
+ qx.ui.core.Widget.prototype._afterDisappear.call(this);
+
+ this.forEachVisibleChild(function() {
+ if (this.isAppearRelevant()) {
+ this._afterDisappear();
+ }
+ });
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INSERTDOM/REMOVEDOM MESSAGES FOR CHILDREN
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._beforeInsertDom = function()
+{
+ qx.ui.core.Widget.prototype._beforeInsertDom.call(this);
+
+ this.forEachVisibleChild(function() {
+ if (this.isAppearRelevant()) {
+ this._beforeInsertDom();
+ }
+ });
+}
+
+qx.Proto._afterInsertDom = function()
+{
+ qx.ui.core.Widget.prototype._afterInsertDom.call(this);
+
+ this.forEachVisibleChild(function() {
+ if (this.isAppearRelevant()) {
+ this._afterInsertDom();
+ }
+ });
+}
+
+qx.Proto._beforeRemoveDom = function()
+{
+ qx.ui.core.Widget.prototype._beforeRemoveDom.call(this);
+
+ this.forEachVisibleChild(function() {
+ if (this.isAppearRelevant()) {
+ this._beforeRemoveDom();
+ }
+ });
+}
+
+qx.Proto._afterRemoveDom = function()
+{
+ qx.ui.core.Widget.prototype._afterRemoveDom.call(this);
+
+ this.forEachVisibleChild(function() {
+ if (this.isAppearRelevant()) {
+ this._afterRemoveDom();
+ }
+ });
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPLAYBLE HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._handleDisplayableCustom = function(vDisplayable, vParent, vHint)
+{
+ this.forEachChild(function() {
+ this._handleDisplayable();
+ });
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ STATE QUEUE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._addChildrenToStateQueue = function()
+{
+ this.forEachVisibleChild(function() {
+ this.addToStateQueue();
+ });
+}
+
+qx.Proto.recursiveAddToStateQueue = function()
+{
+ this.addToStateQueue();
+
+ this.forEachVisibleChild(function() {
+ this.recursiveAddToStateQueue();
+ });
+}
+
+qx.Proto._recursiveAppearanceThemeUpdate = function(vNewAppearanceTheme, vOldAppearanceTheme)
+{
+ qx.ui.core.Widget.prototype._recursiveAppearanceThemeUpdate.call(this, vNewAppearanceTheme, vOldAppearanceTheme);
+
+ this.forEachVisibleChild(function() {
+ this._recursiveAppearanceThemeUpdate(vNewAppearanceTheme, vOldAppearanceTheme);
+ });
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN QUEUE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._addChildToChildrenQueue = function(vChild)
+{
+ if (!vChild._isInParentChildrenQueue && !vChild._isDisplayable) {
+ this.warn("Ignoring invisible child: " + vChild);
+ }
+
+ if (!vChild._isInParentChildrenQueue && vChild._isDisplayable)
+ {
+ qx.ui.core.Widget.addToGlobalLayoutQueue(this);
+
+ if (!this._childrenQueue) {
+ this._childrenQueue = {};
+ }
+
+ this._childrenQueue[vChild.toHashCode()] = vChild;
+ }
+}
+
+qx.Proto._removeChildFromChildrenQueue = function(vChild)
+{
+ if (this._childrenQueue && vChild._isInParentChildrenQueue)
+ {
+ delete this._childrenQueue[vChild.toHashCode()];
+
+ if (qx.lang.Object.isEmpty(this._childrenQueue)) {
+ qx.ui.core.Widget.removeFromGlobalLayoutQueue(this);
+ }
+ }
+}
+
+qx.Proto._flushChildrenQueue = function()
+{
+ if (!qx.lang.Object.isEmpty(this._childrenQueue))
+ {
+ this.getLayoutImpl().flushChildrenQueue(this._childrenQueue);
+ delete this._childrenQueue;
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LAYOUT QUEUE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._addChildrenToLayoutQueue = function(p)
+{
+ this.forEachChild(function() {
+ this.addToLayoutChanges(p);
+ });
+}
+
+qx.Proto._layoutChild = function(vChild)
+{
+ if (!vChild._isDisplayable)
+ {
+ this.warn("Want to render an invisible child: " + vChild + " -> 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<chl; i++) {
+ if (qx.dom.ElementFromPoint.getElementAbsolutePointChecker(ch[i].getElement(), x, y)) {
+ return ch[i].getWidgetFromPointHelper(x, y);
+ }
+ }
+
+ return this;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CLONE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._cloneRecursive = function(cloneInstance)
+{
+ var ch = this.getChildren();
+ var chl = ch.length;
+ var cloneChild;
+
+ for (var i=0; i<chl; i++)
+ {
+ cloneChild = ch[i].clone(true);
+ cloneInstance.add(cloneChild);
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ REMAPPING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._remappingChildTable = [ "add", "remove", "addAt", "addAtBegin", "addAtEnd", "removeAt", "addBefore", "addAfter", "removeAll" ];
+qx.Proto._remapStart = "return this._remappingChildTarget.";
+qx.Proto._remapStop = ".apply(this._remappingChildTarget, arguments)";
+
+qx.Proto.remapChildrenHandlingTo = function(vTarget)
+{
+ var t = this._remappingChildTable;
+
+ this._remappingChildTarget = vTarget;
+
+ for (var i=0, l=t.length, s; i<l; i++) {
+ s = t[i]; this[s] = new Function(qx.ui.core.Parent.prototype._remapStart + s + qx.ui.core.Parent.prototype._remapStop);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (this._layoutImpl)
+ {
+ this._layoutImpl.dispose();
+ this._layoutImpl = null;
+ }
+
+ for (var i in this._childrenQueue) {
+ delete this._childrenQueue[i];
+ }
+
+ this._childrenQueue = null;
+ this._remappingChildTable = null;
+ this._remappingChildTarget = null;
+
+ if (this._children)
+ {
+ var chl = this._children.length;
+
+ for (var i=chl-1; 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:
+ <ul><li>default</li>
+ <li>crosshair</li>
+ <li>pointer (hand is the ie name and will mapped to pointer in non-ie).</li>
+ <li>move</li>
+ <li>n-resize</li>
+ <li>ne-resize</li>
+ <li>e-resize</li>
+ <li>se-resize</li>
+ <li>s-resize</li>
+ <li>sw-resize</li>
+ <li>w-resize</li>
+ <li>nw-resize</li>
+ <li>text</li>
+ <li>wait</li>
+ <li>help </li>
+ <li>url([file]) = self defined cursor, file should be an ANI- or CUR-type</li>
+ </ul>
+*/
+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<vLength; i++)
+ {
+ vWidget = vQueue[i];
+
+ vWidget.flushWidgetQueue();
+ delete vWidget._isInGlobalWidgetQueue;
+ }
+
+ vQueue.splice(0, vLength);
+ }
+}
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ELEMENT QUEUE
+
+ Contains the widgets which should be (dom-)created
+---------------------------------------------------------------------------
+*/
+
+qx.ui.core.Widget._globalElementQueue = [];
+
+qx.ui.core.Widget.addToGlobalElementQueue = function(vWidget)
+{
+ if (!vWidget._isInGlobalElementQueue && vWidget._isDisplayable)
+ {
+ qx.ui.core.Widget._globalElementQueue.push(vWidget);
+ vWidget._isInGlobalElementQueue = true;
+ }
+}
+
+qx.ui.core.Widget.removeFromGlobalElementQueue = function(vWidget)
+{
+ if (vWidget._isInGlobalElementQueue)
+ {
+ qx.lang.Array.remove(qx.ui.core.Widget._globalElementQueue, vWidget);
+ delete vWidget._isInGlobalElementQueue;
+ }
+}
+
+qx.ui.core.Widget.flushGlobalElementQueue = function()
+{
+ var vQueue=qx.ui.core.Widget._globalElementQueue, vLength, vWidget;
+
+ while ((vLength=vQueue.length) > 0)
+ {
+ for (var i=0; i<vLength; i++)
+ {
+ vWidget = vQueue[i];
+
+ vWidget._createElementImpl();
+ delete vWidget._isInGlobalElementQueue;
+ }
+
+ vQueue.splice(0, vLength);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ STATE QUEUE
+
+ Contains the widgets which recently changed their state
+---------------------------------------------------------------------------
+*/
+
+qx.ui.core.Widget._globalStateQueue = [];
+
+qx.ui.core.Widget.addToGlobalStateQueue = function(vWidget)
+{
+ if (!vWidget._isInGlobalStateQueue && vWidget._isDisplayable)
+ {
+ qx.ui.core.Widget._globalStateQueue.push(vWidget);
+ vWidget._isInGlobalStateQueue = true;
+ }
+}
+
+qx.ui.core.Widget.removeFromGlobalStateQueue = function(vWidget)
+{
+ if (vWidget._isInGlobalStateQueue)
+ {
+ qx.lang.Array.remove(qx.ui.core.Widget._globalStateQueue, vWidget);
+ delete vWidget._isInGlobalStateQueue;
+ }
+}
+
+qx.ui.core.Widget.flushGlobalStateQueue = function()
+{
+ var vQueue=qx.ui.core.Widget._globalStateQueue, vLength, vWidget;
+
+ while ((vLength=vQueue.length) > 0)
+ {
+ for (var i=0; i<vLength; i++)
+ {
+ vWidget = vQueue[i];
+
+ vWidget._applyStateAppearance();
+
+ delete vWidget._isInGlobalStateQueue;
+ }
+
+ vQueue.splice(0, vLength);
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ JOBS QUEUE
+
+ Contains the widgets which need a update after they were visible before
+---------------------------------------------------------------------------
+*/
+
+qx.ui.core.Widget._globalJobQueue = [];
+
+qx.ui.core.Widget.addToGlobalJobQueue = function(vWidget)
+{
+ if (!vWidget._isInGlobalJobQueue && vWidget._isDisplayable)
+ {
+ qx.ui.core.Widget._globalJobQueue.push(vWidget);
+ vWidget._isInGlobalJobQueue = true;
+ }
+}
+
+qx.ui.core.Widget.removeFromGlobalJobQueue = function(vWidget)
+{
+ if (vWidget._isInGlobalJobQueue)
+ {
+ qx.lang.Array.remove(qx.ui.core.Widget._globalJobQueue, vWidget);
+ delete vWidget._isInGlobalJobQueue;
+ }
+}
+
+qx.ui.core.Widget.flushGlobalJobQueue = function()
+{
+ var vQueue=qx.ui.core.Widget._globalJobQueue, vLength, vWidget;
+
+ while ((vLength=vQueue.length) > 0)
+ {
+ for (var i=0; i<vLength; i++)
+ {
+ vWidget = vQueue[i];
+
+ vWidget._flushJobQueue(vWidget._jobQueue);
+ delete vWidget._isInGlobalJobQueue;
+ }
+
+ vQueue.splice(0, vLength);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LAYOUT QUEUE
+
+ Contains the parents (qx.ui.core.Parent) of the children which needs layout updates
+---------------------------------------------------------------------------
+*/
+
+qx.ui.core.Widget._globalLayoutQueue = [];
+
+qx.ui.core.Widget.addToGlobalLayoutQueue = function(vParent)
+{
+ if (!vParent._isInGlobalLayoutQueue && vParent._isDisplayable)
+ {
+ qx.ui.core.Widget._globalLayoutQueue.push(vParent);
+ vParent._isInGlobalLayoutQueue = true;
+ }
+}
+
+qx.ui.core.Widget.removeFromGlobalLayoutQueue = function(vParent)
+{
+ if (vParent._isInGlobalLayoutQueue)
+ {
+ qx.lang.Array.remove(qx.ui.core.Widget._globalLayoutQueue, vParent);
+ delete vParent._isInGlobalLayoutQueue;
+ }
+}
+
+qx.ui.core.Widget.flushGlobalLayoutQueue = function()
+{
+ var vQueue=qx.ui.core.Widget._globalLayoutQueue, vLength, vParent;
+
+ while ((vLength=vQueue.length) > 0)
+ {
+ for (var i=0; i<vLength; i++)
+ {
+ vParent = vQueue[i];
+
+ vParent._flushChildrenQueue();
+ delete vParent._isInGlobalLayoutQueue;
+ }
+
+ vQueue.splice(0, vLength);
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPLAY QUEUE
+
+ Contains the widgets which should initially become visible
+---------------------------------------------------------------------------
+*/
+
+qx.ui.core.Widget._fastGlobalDisplayQueue = [];
+qx.ui.core.Widget._lazyGlobalDisplayQueues = {};
+
+qx.ui.core.Widget.addToGlobalDisplayQueue = function(vWidget)
+{
+ if (!vWidget._isInGlobalDisplayQueue && vWidget._isDisplayable)
+ {
+ var vParent = vWidget.getParent();
+
+ if (vParent.isSeeable())
+ {
+ var vKey = vParent.toHashCode();
+
+ if (qx.ui.core.Widget._lazyGlobalDisplayQueues[vKey])
+ {
+ qx.ui.core.Widget._lazyGlobalDisplayQueues[vKey].push(vWidget);
+ }
+ else
+ {
+ qx.ui.core.Widget._lazyGlobalDisplayQueues[vKey] = [vWidget];
+ }
+ }
+ else
+ {
+ qx.ui.core.Widget._fastGlobalDisplayQueue.push(vWidget);
+ }
+
+ vWidget._isInGlobalDisplayQueue = true;
+ }
+}
+
+qx.ui.core.Widget.removeFromGlobalDisplayQueue = function(vWidget) {}
+
+qx.ui.core.Widget.flushGlobalDisplayQueue = function()
+{
+ var vKey, vLazyQueue, vWidget, vFragment;
+
+ var vFastQueue = qx.ui.core.Widget._fastGlobalDisplayQueue;
+ var vLazyQueues = qx.ui.core.Widget._lazyGlobalDisplayQueues;
+
+
+
+
+ /* -----------------------------------------------
+ Flush display queues
+ ----------------------------------------------- */
+
+ // Work on fast queue
+ for (var i=0, l=vFastQueue.length; i<l; i++)
+ {
+ vWidget = vFastQueue[i];
+ vWidget.getParent()._getTargetNode().appendChild(vWidget.getElement());
+ }
+
+
+ // Work on lazy queues: Inline widgets
+ if (qx.OO.isAvailable("qx.ui.basic.Inline"))
+ {
+ for (vKey in vLazyQueues)
+ {
+ vLazyQueue = vLazyQueues[vKey];
+
+ for (var i=0; i<vLazyQueue.length; i++)
+ {
+ vWidget = vLazyQueue[i];
+
+ if (vWidget instanceof qx.ui.basic.Inline)
+ {
+ vWidget._beforeInsertDom();
+
+ try
+ {
+ document.getElementById(vWidget.getInlineNodeId()).appendChild(vWidget.getElement());
+ }
+ catch(ex)
+ {
+ vWidget.debug("Could not append to inline id: " + vWidget.getInlineNodeId(), ex);
+ }
+
+ vWidget._afterInsertDom();
+ vWidget._afterAppear();
+
+ // Remove inline widget from queue and fix iterator position
+ qx.lang.Array.remove(vLazyQueue, vWidget);
+ i--;
+
+ // Reset display queue flag
+ delete vWidget._isInGlobalDisplayQueue;
+ }
+ }
+ }
+ }
+
+
+ // Work on lazy queues: Other widgets
+ for (vKey in vLazyQueues)
+ {
+ vLazyQueue = vLazyQueues[vKey];
+
+ // Speed enhancement: Choose a fairly small arbitrary value for the number
+ // of elements that should be added to the parent individually. If more
+ // than this number of elements is to be added to the parent, we'll create
+ // a document fragment, add the elements to the document fragment, and
+ // then add the whole fragment to the parent en mass (assuming that
+ // creation of a document fragment is supported by the browser).
+ if (document.createDocumentFragment && vLazyQueue.length >= 3)
+ {
+ // creating new document fragment
+ vFragment = document.createDocumentFragment();
+
+ // appending all widget elements to fragment
+ for (var i=0, l=vLazyQueue.length; i<l; i++)
+ {
+ vWidget = vLazyQueue[i];
+
+ vWidget._beforeInsertDom();
+ vFragment.appendChild(vWidget.getElement());
+ }
+
+ // append all fragment data at once to
+ // the already visible parent widget element
+ vLazyQueue[0].getParent()._getTargetNode().appendChild(vFragment);
+
+ for (var i=0, l=vLazyQueue.length; i<l; i++)
+ {
+ vWidget = vLazyQueue[i];
+ vWidget._afterInsertDom();
+ }
+ }
+ else
+ {
+ // appending all widget elements (including previously added children)
+ // to the already visible parent widget element
+ for (var i=0, l=vLazyQueue.length; i<l; i++)
+ {
+ vWidget = vLazyQueue[i];
+
+ vWidget._beforeInsertDom();
+ vWidget.getParent()._getTargetNode().appendChild(vWidget.getElement());
+ vWidget._afterInsertDom();
+ }
+ }
+ }
+
+
+
+
+
+
+ /* -----------------------------------------------
+ Cleanup and appear signals
+ ----------------------------------------------- */
+
+ // Only need to do this with the lazy queues
+ // because through the recursion from qx.ui.core.Parent
+ // all others get also informed.
+ for (vKey in vLazyQueues)
+ {
+ vLazyQueue = vLazyQueues[vKey];
+
+ for (var i=0, l=vLazyQueue.length; i<l; i++)
+ {
+ vWidget = vLazyQueue[i];
+
+ if (vWidget.getVisibility()) {
+ vWidget._afterAppear();
+ }
+
+ // Reset display queue flag
+ delete vWidget._isInGlobalDisplayQueue;
+ }
+
+ delete vLazyQueues[vKey];
+ }
+
+ // Reset display queue flag for widgets in fastQueue
+ for (var i=0, l=vFastQueue.length; i<l; i++) {
+ delete vFastQueue[i]._isInGlobalDisplayQueue;
+ }
+
+ // Remove fast queue entries
+ qx.lang.Array.removeAll(vFastQueue);
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ GLOBAL HELPERS
+---------------------------------------------------------------------------
+*/
+
+qx.ui.core.Widget.getActiveSiblingHelperIgnore = function(vIgnoreClasses, vInstance)
+{
+ for (var j=0; j<vIgnoreClasses.length; j++) {
+ if (vInstance instanceof vIgnoreClasses[j]) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+qx.ui.core.Widget.getActiveSiblingHelper = function(vObject, vParent, vCalc, vIgnoreClasses, vMode)
+{
+ if (!vIgnoreClasses) {
+ vIgnoreClasses = [];
+ }
+
+ var vChilds = vParent.getChildren();
+ var vPosition = qx.util.Validation.isInvalid(vMode) ? vChilds.indexOf(vObject) + vCalc : vMode == "first" ? 0 : vChilds.length-1;
+ var vInstance = vChilds[vPosition];
+
+ while(!vInstance.isEnabled() || qx.ui.core.Widget.getActiveSiblingHelperIgnore(vIgnoreClasses, vInstance))
+ {
+ vPosition += vCalc;
+ vInstance = vChilds[vPosition];
+
+ if (!vInstance) {
+ return null;
+ }
+ }
+
+ return vInstance;
+}
+
+
+
+
+
+
+
+/* ************************************************************************
+ Instance data, properties and methods
+************************************************************************ */
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ If the widget is visible and rendered on the screen.
+*/
+qx.Proto.isMaterialized = function() {
+ var el=this._element;
+ return (this._initialLayoutDone &&
+ this._isDisplayable &&
+ qx.dom.Style.getStyleProperty(el, "display") != "none" &&
+ qx.dom.Style.getStyleProperty(el, "visibility") != "hidden" &&
+ el.offsetWidth > 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<chl; i++) {
+ ch[i].addToLayoutChanges("parentPaddingLeft");
+ }
+ }
+
+ if (vQueue.paddingRight) {
+ for (var i=0; i<chl; i++) {
+ ch[i].addToLayoutChanges("parentPaddingRight");
+ }
+ }
+
+ if (vQueue.paddingTop) {
+ for (var i=0; i<chl; i++) {
+ ch[i].addToLayoutChanges("parentPaddingTop");
+ }
+ }
+
+ if (vQueue.paddingBottom) {
+ for (var i=0; i<chl; i++) {
+ ch[i].addToLayoutChanges("parentPaddingBottom");
+ }
+ }
+ }
+
+ if (vRecomputeInnerWidth) {
+ this._recomputeInnerWidth();
+ }
+
+ if (vRecomputeInnerHeight) {
+ this._recomputeInnerHeight();
+ }
+
+ if (this._initialLayoutDone)
+ {
+ if (vLayoutImpl) {
+ vLayoutImpl.updateChildrenOnJobQueueFlush(vQueue);
+ }
+ }
+ }
+ catch(ex)
+ {
+ this.error("Flushing job queue (childrensignals#5) failed", ex);
+ }
+
+
+
+ /* --------------------------------------------------------------------------------
+ 5. Cleanup
+ -------------------------------------------------------------------------------- */
+
+ delete this._jobQueue;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ METHODS TO GIVE THE LAYOUTERS INFORMATION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._isWidthEssential = qx.util.Return.returnTrue;
+qx.Proto._isHeightEssential = qx.util.Return.returnTrue;
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPLY LAYOUT STYLES
+---------------------------------------------------------------------------
+*/
+
+qx.ui.core.Widget.initApplyMethods = function()
+{
+ var f = "_applyRuntime";
+ var r = "_resetRuntime";
+ var s = "this._style.";
+ var e = "=''";
+ var v = "=v+'px'";
+ var vpar = "v";
+
+ var props = ["left", "right", "top", "bottom", "width", "height",
+ "minWidth", "maxWidth", "minHeight", "maxHeight"];
+ var propsup = ["Left", "Right", "Top", "Bottom", "Width", "Height",
+ "MinWidth", "MaxWidth", "MinHeight", "MaxHeight"];
+
+ for (var i=0, fn=f+"Margin", rn=r+"Margin", sp=s+"margin"; i<4; i++)
+ {
+ qx.Proto[fn+propsup[i]] = new Function(vpar, sp + propsup[i] + v);
+ qx.Proto[rn+propsup[i]] = new Function(sp + propsup[i] + e);
+ }
+
+ var pad = "padding";
+ var upad = "Padding";
+
+ if (qx.sys.Client.getInstance().isGecko())
+ {
+ for (var i=0, fn=f+upad, rn=r+upad, sp=s+pad; i<4; i++)
+ {
+ qx.Proto[fn+propsup[i]] = new Function(vpar, sp + propsup[i] + v);
+ qx.Proto[rn+propsup[i]] = new Function(sp + propsup[i] + e);
+ }
+ }
+ else
+ {
+ // need to use setStyleProperty to keep compatibility with enhanced cross browser borders
+ var s1="this.setStyleProperty('padding";
+ var s2="', v+'px')";
+ var s3="this.removeStyleProperty('padding";
+ var s4="')";
+
+ for (var i=0, fn=f+upad, rn=r+upad, sp=s+pad; i<4; i++)
+ {
+ qx.Proto[fn+propsup[i]] = new Function(vpar, s1 + propsup[i] + s2);
+ qx.Proto[rn+propsup[i]] = new Function(s3 + propsup[i] + s4);
+ }
+ }
+
+ /*
+ Use optimized method for internet explorer
+ to omit string concat and directly setup
+ the new layout property.
+
+ We could not use this to reset the value however.
+ It seems that is just doesn't work this way. And the
+ left/top always get priority. Tried: "", null, "auto".
+ Nothing helps.
+
+ Now I've switched back to the conventional method
+ to reset the value. This seems to work again.
+ */
+ if (qx.sys.Client.getInstance().isMshtml())
+ {
+ for (var i=0, tpos="pos", vset="=v"; i<6; i++)
+ {
+ // to debug the values which will be applied use this instead of the
+ // first line:
+ // qx.Proto[f+propsup[i]] = new Function(vpar, "this.debug('v: ' + v); " + s + tpos + propsup[i] + vset);
+
+ qx.Proto[f+propsup[i]] = new Function(vpar, s + tpos + propsup[i] + vset);
+ qx.Proto[r+propsup[i]] = new Function(s + props[i] + e);
+ }
+ }
+ else
+ {
+ for (var i=0; i<10; i++)
+ {
+ // to debug the values which will be applied use this instead of the
+ // first line:
+ // qx.Proto[f+propsup[i]] = new Function(vpar, "this.debug('v: ' + v); " + s + props[i] + v);
+
+ qx.Proto[f+propsup[i]] = new Function(vpar, s + props[i] + v);
+ qx.Proto[r+propsup[i]] = new Function(s + props[i] + e);
+ }
+ }
+}
+
+qx.ui.core.Widget.initApplyMethods();
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DIMENSION CACHE
+---------------------------------------------------------------------------
+*/
+
+/*
+ Add basic setter/getters
+*/
+
+qx.OO.addCachedProperty({ name : "innerWidth", defaultValue : null });
+qx.OO.addCachedProperty({ name : "innerHeight", defaultValue : null });
+qx.OO.addCachedProperty({ name : "boxWidth", defaultValue : null });
+qx.OO.addCachedProperty({ name : "boxHeight", defaultValue : null });
+qx.OO.addCachedProperty({ name : "outerWidth", defaultValue : null });
+qx.OO.addCachedProperty({ name : "outerHeight", defaultValue : null });
+
+qx.Proto._computeBoxWidthFallback = function() {
+ return 0;
+}
+
+qx.Proto._computeBoxHeightFallback = function() {
+ return 0;
+}
+
+qx.Proto._computeBoxWidth = function() {
+ var vLayoutImpl = this.getParent().getLayoutImpl();
+ return Math.max(0,
+ qx.lang.Number.limit(vLayoutImpl.computeChildBoxWidth(this),
+ this.getMinWidthValue(),
+ this.getMaxWidthValue()));
+}
+
+qx.Proto._computeBoxHeight = function() {
+ var vLayoutImpl = this.getParent().getLayoutImpl();
+ return Math.max(0,
+ qx.lang.Number.limit(vLayoutImpl.computeChildBoxHeight(this),
+ this.getMinHeightValue(),
+ this.getMaxHeightValue()));
+}
+
+qx.Proto._computeOuterWidth = function() {
+ return Math.max(0,
+ (this.getMarginLeft() +
+ this.getBoxWidth() +
+ this.getMarginRight()));
+}
+
+qx.Proto._computeOuterHeight = function() {
+ return Math.max(0,
+ (this.getMarginTop() +
+ this.getBoxHeight() +
+ this.getMarginBottom()));
+}
+
+qx.Proto._computeInnerWidth = function() {
+ return Math.max(0, this.getBoxWidth() - this.getFrameWidth());
+}
+
+qx.Proto._computeInnerHeight = function() {
+ return Math.max(0, this.getBoxHeight() - this.getFrameHeight());
+}
+
+qx.Proto.getNeededWidth = function() {
+ var vLayoutImpl = this.getParent().getLayoutImpl();
+ return Math.max(0, vLayoutImpl.computeChildNeededWidth(this));
+}
+
+qx.Proto.getNeededHeight = function() {
+ var vLayoutImpl = this.getParent().getLayoutImpl();
+ return Math.max(0, vLayoutImpl.computeChildNeededHeight(this));
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ RECOMPUTE FLEX VALUES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._recomputeFlexX = function()
+{
+ if (!this.getHasFlexX()) {
+ return false;
+ }
+
+ if (this._computedWidthTypeFlex)
+ {
+ this._computedWidthValue = null;
+ this.addToLayoutChanges("width");
+ }
+
+ return true;
+}
+
+qx.Proto._recomputeFlexY = function()
+{
+ if (!this.getHasFlexY()) {
+ return false;
+ }
+
+ if (this._computedHeightTypeFlex)
+ {
+ this._computedHeightValue = null;
+ this.addToLayoutChanges("height");
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ RECOMPUTE PERCENTS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._recomputePercentX = function()
+{
+ if (!this.getHasPercentX()) {
+ return false;
+ }
+
+ if (this._computedWidthTypePercent)
+ {
+ this._computedWidthValue = null;
+ this.addToLayoutChanges("width");
+ }
+
+ if (this._computedMinWidthTypePercent)
+ {
+ this._computedMinWidthValue = null;
+ this.addToLayoutChanges("minWidth");
+ }
+
+ if (this._computedMaxWidthTypePercent)
+ {
+ this._computedMaxWidthValue = null;
+ this.addToLayoutChanges("maxWidth");
+ }
+
+ if (this._computedLeftTypePercent)
+ {
+ this._computedLeftValue = null;
+ this.addToLayoutChanges("left");
+ }
+
+ if (this._computedRightTypePercent)
+ {
+ this._computedRightValue = null;
+ this.addToLayoutChanges("right");
+ }
+
+ return true;
+}
+
+qx.Proto._recomputePercentY = function()
+{
+ if (!this.getHasPercentY()) {
+ return false;
+ }
+
+ if (this._computedHeightTypePercent)
+ {
+ this._computedHeightValue = null;
+ this.addToLayoutChanges("height");
+ }
+
+ if (this._computedMinHeightTypePercent)
+ {
+ this._computedMinHeightValue = null;
+ this.addToLayoutChanges("minHeight");
+ }
+
+ if (this._computedMaxHeightTypePercent)
+ {
+ this._computedMaxHeightValue = null;
+ this.addToLayoutChanges("maxHeight");
+ }
+
+ if (this._computedTopTypePercent)
+ {
+ this._computedTopValue = null;
+ this.addToLayoutChanges("top");
+ }
+
+ if (this._computedBottomTypePercent)
+ {
+ this._computedBottomValue = null;
+ this.addToLayoutChanges("bottom");
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ RECOMPUTE RANGES
+---------------------------------------------------------------------------
+*/
+
+if (qx.sys.Client.getInstance().isMshtml() || qx.sys.Client.getInstance().isOpera())
+{
+ qx.Proto._recomputeRangeX = function()
+ {
+ if (this._computedLeftTypeNull || this._computedRightTypeNull) {
+ return false;
+ }
+
+ this.addToLayoutChanges("width");
+ return true;
+ }
+
+ qx.Proto._recomputeRangeY = function()
+ {
+ if (this._computedTopTypeNull || this._computedBottomTypeNull) {
+ return false;
+ }
+
+ this.addToLayoutChanges("height");
+ return true;
+ }
+}
+else
+{
+ qx.Proto._recomputeRangeX = function() {
+ return !(this._computedLeftTypeNull || this._computedRightTypeNull);
+ }
+
+ qx.Proto._recomputeRangeY = function() {
+ return !(this._computedTopTypeNull || this._computedBottomTypeNull);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ RECOMPUTE STRETCHING
+---------------------------------------------------------------------------
+*/
+
+if (qx.sys.Client.getInstance().isMshtml() || qx.sys.Client.getInstance().isOpera())
+{
+ qx.Proto._recomputeStretchingX = function()
+ {
+ if (this.getAllowStretchX() && this._computedWidthTypeNull)
+ {
+ this._computedWidthValue = null;
+ this.addToLayoutChanges("width");
+
+ return true;
+ }
+
+ return false;
+ }
+
+ qx.Proto._recomputeStretchingY = function()
+ {
+ if (this.getAllowStretchY() && this._computedHeightTypeNull)
+ {
+ this._computedHeightValue = null;
+ this.addToLayoutChanges("height");
+
+ return true;
+ }
+
+ return false;
+ }
+}
+else
+{
+ qx.Proto._recomputeStretchingX = function()
+ {
+ if (this.getAllowStretchX() && this._computedWidthTypeNull) {
+ return true;
+ }
+
+ return false;
+ }
+
+ qx.Proto._recomputeStretchingY = function()
+ {
+ if (this.getAllowStretchY() && this._computedHeightTypeNull) {
+ return true;
+ }
+
+ return false;
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INTELLIGENT GETTERS FOR STANDALONE DIMENSIONS: HELPERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computeValuePixel = function(v) {
+ return Math.round(v);
+}
+
+qx.Proto._computeValuePixelLimit = function(v) {
+ return Math.max(0, this._computeValuePixel(v));
+}
+
+qx.Proto._computeValuePercentX = function(v) {
+ return Math.round(this.getParent().getInnerWidthForChild(this) * v * 0.01);
+}
+
+qx.Proto._computeValuePercentXLimit = function(v) {
+ return Math.max(0, this._computeValuePercentX(v));
+}
+
+qx.Proto._computeValuePercentY = function(v) {
+ return Math.round(this.getParent().getInnerHeightForChild(this) * v * 0.01);
+}
+
+qx.Proto._computeValuePercentYLimit = function(v) {
+ return Math.max(0, this._computeValuePercentY(v));
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INTELLIGENT GETTERS FOR STANDALONE DIMENSIONS: X-AXIS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getWidthValue = function()
+{
+ if (this._computedWidthValue != null) {
+ return this._computedWidthValue;
+ }
+
+ switch(this._computedWidthType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ return this._computedWidthValue = this._computeValuePixelLimit(this._computedWidthParsed);
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ return this._computedWidthValue = this._computeValuePercentXLimit(this._computedWidthParsed);
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ return this._computedWidthValue = this.getPreferredBoxWidth();
+
+ case qx.ui.core.Widget.TYPE_FLEX:
+ try{
+ this.getParent().getLayoutImpl().computeChildrenFlexWidth();
+ } catch (e){
+ if (this.getParent().getLayoutImpl()["computeChildrenFlexWidth"] == null){
+ throw new Error("Widget " + this + ": having flex size but parent layout does not support it");
+ } else {
+ throw e;
+ }
+ }
+ return this._computedWidthValue = this._computedWidthFlexValue;
+ }
+
+ return null;
+}
+
+qx.Proto.getMinWidthValue = function()
+{
+ if (this._computedMinWidthValue != null) {
+ return this._computedMinWidthValue;
+ }
+
+ switch(this._computedMinWidthType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ return this._computedWidthValue = this._computeValuePixelLimit(this._computedMinWidthParsed);
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ return this._computedWidthValue = this._computeValuePercentXLimit(this._computedMinWidthParsed);
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ return this._computedMinWidthValue = this.getPreferredBoxWidth();
+ }
+
+ return null;
+}
+
+qx.Proto.getMaxWidthValue = function()
+{
+ if (this._computedMaxWidthValue != null) {
+ return this._computedMaxWidthValue;
+ }
+
+ switch(this._computedMaxWidthType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ return this._computedWidthValue = this._computeValuePixelLimit(this._computedMaxWidthParsed);
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ return this._computedWidthValue = this._computeValuePercentXLimit(this._computedMaxWidthParsed);
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ return this._computedMaxWidthValue = this.getPreferredBoxWidth();
+ }
+
+ return null;
+}
+
+qx.Proto.getLeftValue = function()
+{
+ if (this._computedLeftValue != null) {
+ return this._computedLeftValue;
+ }
+
+ switch(this._computedLeftType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ return this._computedLeftValue = this._computeValuePixel(this._computedLeftParsed);
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ return this._computedLeftValue = this._computeValuePercentX(this._computedLeftParsed);
+ }
+
+ return null;
+}
+
+qx.Proto.getRightValue = function()
+{
+ if (this._computedRightValue != null) {
+ return this._computedRightValue;
+ }
+
+ switch(this._computedRightType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ return this._computedRightValue = this._computeValuePixel(this._computedRightParsed);
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ return this._computedRightValue = this._computeValuePercentX(this._computedRightParsed);
+ }
+
+ return null;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INTELLIGENT GETTERS FOR STANDALONE DIMENSIONS: Y-AXIS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getHeightValue = function()
+{
+ if (this._computedHeightValue != null) {
+ return this._computedHeightValue;
+ }
+
+ switch(this._computedHeightType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ return this._computedHeightValue = this._computeValuePixelLimit(this._computedHeightParsed);
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ return this._computedHeightValue = this._computeValuePercentYLimit(this._computedHeightParsed);
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ return this._computedHeightValue = this.getPreferredBoxHeight();
+
+ case qx.ui.core.Widget.TYPE_FLEX:
+ try{
+ this.getParent().getLayoutImpl().computeChildrenFlexHeight();
+ } catch (e){
+ if (this.getParent().getLayoutImpl()["computeChildrenFlexHeight"] == null){
+ throw new Error("Widget " + this + ": having flex size but parent layout does not support it");
+ } else {
+ throw e;
+ }
+ }
+ return this._computedHeightValue = this._computedHeightFlexValue;
+ }
+
+ return null;
+}
+
+qx.Proto.getMinHeightValue = function()
+{
+ if (this._computedMinHeightValue != null) {
+ return this._computedMinHeightValue;
+ }
+
+ switch(this._computedMinHeightType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ return this._computedMinHeightValue = this._computeValuePixelLimit(this._computedMinHeightParsed);
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ return this._computedMinHeightValue = this._computeValuePercentYLimit(this._computedMinHeightParsed);
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ return this._computedMinHeightValue = this.getPreferredBoxHeight();
+ }
+
+ return null;
+}
+
+qx.Proto.getMaxHeightValue = function()
+{
+ if (this._computedMaxHeightValue != null) {
+ return this._computedMaxHeightValue;
+ }
+
+ switch(this._computedMaxHeightType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ return this._computedMaxHeightValue = this._computeValuePixelLimit(this._computedMaxHeightParsed);
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ return this._computedMaxHeightValue = this._computeValuePercentYLimit(this._computedMaxHeightParsed);
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ return this._computedMaxHeightValue = this.getPreferredBoxHeight();
+ }
+
+ return null;
+}
+
+qx.Proto.getTopValue = function()
+{
+ if (this._computedTopValue != null) {
+ return this._computedTopValue;
+ }
+
+ switch(this._computedTopType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ return this._computedTopValue = this._computeValuePixel(this._computedTopParsed);
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ return this._computedTopValue = this._computeValuePercentY(this._computedTopParsed);
+ }
+
+ return null;
+}
+
+qx.Proto.getBottomValue = function()
+{
+ if (this._computedBottomValue != null) {
+ return this._computedBottomValue;
+ }
+
+ switch(this._computedBottomType)
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ return this._computedBottomValue = this._computeValuePixel(this._computedBottomParsed);
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ return this._computedBottomValue = this._computeValuePercentY(this._computedBottomParsed);
+ }
+
+ return null;
+}
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ FRAME DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addCachedProperty({ name : "frameWidth", defaultValue : null, addToQueueRuntime : true });
+qx.OO.addCachedProperty({ name : "frameHeight", defaultValue : null, addToQueueRuntime : true });
+
+qx.Proto._computeFrameWidth = function()
+{
+ var fw = this._cachedBorderLeft + this.getPaddingLeft() + this.getPaddingRight() + this._cachedBorderRight;
+
+ switch(this.getOverflow())
+ {
+ case "scroll":
+ case "scrollY":
+ qx.ui.core.Widget.initOverflow();
+ fw += qx.ui.core.Widget.SCROLLBAR_SIZE;
+ break;
+
+ case "auto":
+ // This seems to be really hard to implement
+ // this.debug("Check Auto Scroll-X: " + this.getPreferredBoxHeight() + " :: " + this.getBoxHeight());
+ break;
+ }
+
+ return fw;
+}
+
+qx.Proto._computeFrameHeight = function()
+{
+ var fh = this._cachedBorderTop + this.getPaddingTop() + this.getPaddingBottom() + this._cachedBorderBottom;
+
+ switch(this.getOverflow())
+ {
+ case "scroll":
+ case "scrollX":
+ qx.ui.core.Widget.initOverflow();
+ fh += qx.ui.core.Widget.SCROLLBAR_SIZE;
+ break;
+
+ case "auto":
+ // This seems to be really hard to implement
+ // this.debug("Check Auto Scroll-Y: " + this.getPreferredBoxWidth() + " :: " + this.getBoxWidth());
+ break;
+ }
+
+ return fh;
+}
+
+qx.Proto._invalidateFrameDimensions = function()
+{
+ this._invalidateFrameWidth();
+ this._invalidateFrameHeight();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PREFERRED DIMENSIONS: INNER
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addCachedProperty({ name : "preferredInnerWidth", defaultValue : null, addToQueueRuntime : true });
+qx.OO.addCachedProperty({ name : "preferredInnerHeight", defaultValue : null, addToQueueRuntime : true });
+
+qx.Proto._invalidatePreferredInnerDimensions = function()
+{
+ this._invalidatePreferredInnerWidth();
+ this._invalidatePreferredInnerHeight();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PREFERRED DIMENSIONS: BOX
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addCachedProperty({ name : "preferredBoxWidth", defaultValue : null });
+qx.OO.addCachedProperty({ name : "preferredBoxHeight", defaultValue : null });
+
+qx.Proto._computePreferredBoxWidth = function()
+{
+ try {
+ return Math.max(0, this.getPreferredInnerWidth() + this.getFrameWidth());
+ } catch(ex) {
+ this.error("_computePreferredBoxWidth failed", ex);
+ }
+}
+
+qx.Proto._computePreferredBoxHeight = function()
+{
+ try {
+ return Math.max(0, this.getPreferredInnerHeight() + this.getFrameHeight());
+ } catch(ex) {
+ this.error("_computePreferredBoxHeight failed", ex);
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LAYOUT QUEUE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._initialLayoutDone = false;
+
+qx.Proto.addToLayoutChanges = function(p)
+{
+ if (this._isDisplayable) {
+ this.getParent()._addChildToChildrenQueue(this);
+ }
+
+ return this._layoutChanges[p] = true;
+}
+
+qx.Proto.addToQueue = function(p) {
+ this._initialLayoutDone ? this.addToJobQueue(p) : this.addToLayoutChanges(p);
+}
+
+qx.Proto.addToQueueRuntime = function(p) {
+ return !this._initialLayoutDone || this.addToJobQueue(p);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ BORDER/MARGIN/PADDING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyBorderX = function(vChild, vChanges, vStyle)
+{
+ var vBorder = vChild.getBorder();
+ vBorder ? vBorder._applyWidgetX(vChild) : qx.renderer.border.Border._resetBorderX(vChild);
+}
+
+qx.Proto._applyBorderY = function(vChild, vChanges, vStyle)
+{
+ var vBorder = vChild.getBorder();
+ vBorder ? vBorder._applyWidgetY(vChild) : qx.renderer.border.Border._resetBorderY(vChild);
+}
+
+qx.Proto._applyPaddingX = qx.util.Return.returnTrue;
+qx.Proto._applyPaddingY = qx.util.Return.returnTrue;
+
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LAYOUT AUTO/PERCENT CACHE
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addCachedProperty({ name : "hasPercentX", defaultValue : false });
+qx.OO.addCachedProperty({ name : "hasPercentY", defaultValue : false });
+qx.OO.addCachedProperty({ name : "hasAutoX", defaultValue : false });
+qx.OO.addCachedProperty({ name : "hasAutoY", defaultValue : false });
+qx.OO.addCachedProperty({ name : "hasFlexX", defaultValue : false });
+qx.OO.addCachedProperty({ name : "hasFlexY", defaultValue : false });
+
+qx.Proto._computeHasPercentX = function() {
+ return (this._computedLeftTypePercent ||
+ this._computedWidthTypePercent ||
+ this._computedMinWidthTypePercent ||
+ this._computedMaxWidthTypePercent ||
+ this._computedRightTypePercent);
+}
+
+qx.Proto._computeHasPercentY = function() {
+ return (this._computedTopTypePercent ||
+ this._computedHeightTypePercent ||
+ this._computedMinHeightTypePercent ||
+ this._computedMaxHeightTypePercent ||
+ this._computedBottomTypePercent);
+}
+
+qx.Proto._computeHasAutoX = function() {
+ return (this._computedWidthTypeAuto ||
+ this._computedMinWidthTypeAuto ||
+ this._computedMaxWidthTypeAuto);
+}
+
+qx.Proto._computeHasAutoY = function() {
+ return (this._computedHeightTypeAuto ||
+ this._computedMinHeightTypeAuto ||
+ this._computedMaxHeightTypeAuto);
+}
+
+qx.Proto._computeHasFlexX = function() {
+ return this._computedWidthTypeFlex;
+}
+
+qx.Proto._computeHasFlexY = function() {
+ return this._computedHeightTypeFlex;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LAYOUT TYPE INDENTIFY HELPER METHODS
+---------------------------------------------------------------------------
+*/
+
+qx.ui.core.Widget.TYPE_NULL = 0;
+qx.ui.core.Widget.TYPE_PIXEL = 1;
+qx.ui.core.Widget.TYPE_PERCENT = 2;
+qx.ui.core.Widget.TYPE_AUTO = 3;
+qx.ui.core.Widget.TYPE_FLEX = 4;
+
+qx.Proto._evalUnitsPixelPercentAutoFlex = function(propValue)
+{
+ switch(propValue)
+ {
+ case "auto":
+ return qx.ui.core.Widget.TYPE_AUTO;
+
+ case Infinity:
+ case -Infinity:
+ return qx.ui.core.Widget.TYPE_NULL;
+ }
+
+ switch(typeof propValue)
+ {
+ case "number":
+ return isNaN(propValue) ? qx.ui.core.Widget.TYPE_NULL : qx.ui.core.Widget.TYPE_PIXEL;
+
+ case "string":
+ return propValue.indexOf("%") != -1 ? qx.ui.core.Widget.TYPE_PERCENT : propValue.indexOf("*") != -1 ? qx.ui.core.Widget.TYPE_FLEX : qx.ui.core.Widget.TYPE_NULL;
+ }
+
+ return qx.ui.core.Widget.TYPE_NULL;
+}
+
+qx.Proto._evalUnitsPixelPercentAuto = function(propValue)
+{
+ switch(propValue)
+ {
+ case "auto":
+ return qx.ui.core.Widget.TYPE_AUTO;
+
+ case Infinity:
+ case -Infinity:
+ return qx.ui.core.Widget.TYPE_NULL;
+ }
+
+ switch(typeof propValue)
+ {
+ case "number":
+ return isNaN(propValue) ? qx.ui.core.Widget.TYPE_NULL : qx.ui.core.Widget.TYPE_PIXEL;
+
+ case "string":
+ return propValue.indexOf("%") != -1 ? qx.ui.core.Widget.TYPE_PERCENT : qx.ui.core.Widget.TYPE_NULL;
+ }
+
+ return qx.ui.core.Widget.TYPE_NULL;
+}
+
+qx.Proto._evalUnitsPixelPercent = function(propValue)
+{
+ switch(propValue)
+ {
+ case Infinity:
+ case -Infinity:
+ return qx.ui.core.Widget.TYPE_NULL;
+ }
+
+ switch(typeof propValue)
+ {
+ case "number":
+ return isNaN(propValue) ? qx.ui.core.Widget.TYPE_NULL : qx.ui.core.Widget.TYPE_PIXEL;
+
+ case "string":
+ return propValue.indexOf("%") != -1 ? qx.ui.core.Widget.TYPE_PERCENT : qx.ui.core.Widget.TYPE_NULL;
+ }
+
+ return qx.ui.core.Widget.TYPE_NULL;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LAYOUT TYPE AND VALUE KEY PRE-CACHE
+---------------------------------------------------------------------------
+*/
+
+qx.ui.core.Widget.layoutPropertyTypes = {};
+
+qx.ui.core.Widget.initLayoutProperties = function()
+{
+ var a = [ "width", "height",
+ "minWidth", "maxWidth",
+ "minHeight", "maxHeight",
+ "left", "right", "top", "bottom" ];
+
+ for (var i=0, l=a.length, p, b, t; i<l; i++)
+ {
+ p = a[i];
+ b = "_computed" + qx.lang.String.toFirstUp(p);
+ t = b + "Type";
+
+ qx.ui.core.Widget.layoutPropertyTypes[p] =
+ {
+ dataType : t,
+ dataParsed : b + "Parsed",
+ dataValue : b + "Value",
+
+ typePixel : t + "Pixel",
+ typePercent : t + "Percent",
+ typeAuto : t + "Auto",
+ typeFlex : t + "Flex",
+ typeNull : t + "Null"
+ }
+ }
+}
+
+qx.ui.core.Widget.initLayoutProperties();
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LAYOUT TYPE AND VALUE STORAGE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._unitDetectionPixelPercentAutoFlex = function(propData, propValue)
+{
+ var r = qx.ui.core.Widget.layoutPropertyTypes[propData.name];
+
+ var s = r.dataType;
+ var p = r.dataParsed;
+ var v = r.dataValue;
+
+ var s1 = r.typePixel;
+ var s2 = r.typePercent;
+ var s3 = r.typeAuto;
+ var s4 = r.typeFlex;
+ var s5 = r.typeNull;
+
+ var wasPercent = this[s2];
+ var wasAuto = this[s3];
+ var wasFlex = this[s4];
+
+ switch(this[s] = this._evalUnitsPixelPercentAutoFlex(propValue))
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ this[s1] = true;
+ this[s2] = this[s3] = this[s4] = this[s5] = false;
+ this[p] = this[v] = Math.round(propValue);
+ break;
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ this[s2] = true;
+ this[s1] = this[s3] = this[s4] = this[s5] = false;
+ this[p] = parseFloat(propValue);
+ this[v] = null;
+ break;
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ this[s3] = true;
+ this[s1] = this[s2] = this[s4] = this[s5] = false;
+ this[p] = this[v] = null;
+ break;
+
+ case qx.ui.core.Widget.TYPE_FLEX:
+ this[s4] = true;
+ this[s1] = this[s2] = this[s3] = this[s5] = false;
+ this[p] = parseFloat(propValue);
+ this[v] = null;
+ break;
+
+ default:
+ this[s5] = true;
+ this[s1] = this[s2] = this[s3] = this[s4] = false;
+ this[p] = this[v] = null;
+ break;
+ }
+
+ if (wasPercent != this[s2])
+ {
+ switch(propData.name)
+ {
+ case "minWidth":
+ case "maxWidth":
+ case "width":
+ case "left":
+ case "right":
+ this._invalidateHasPercentX();
+ break;
+
+ case "maxHeight":
+ case "minHeight":
+ case "height":
+ case "top":
+ case "bottom":
+ this._invalidateHasPercentY();
+ break;
+ }
+ }
+
+ // No ELSE because you can also switch from percent to auto
+ if (wasAuto != this[s3])
+ {
+ switch(propData.name)
+ {
+ case "minWidth":
+ case "maxWidth":
+ case "width":
+ this._invalidateHasAutoX();
+ break;
+
+ case "minHeight":
+ case "maxHeight":
+ case "height":
+ this._invalidateHasAutoY();
+ break;
+ }
+ }
+
+ // No ELSE because you can also switch from percent to auto
+ if (wasFlex != this[s4])
+ {
+ switch(propData.name)
+ {
+ case "width":
+ this._invalidateHasFlexX();
+ break;
+
+ case "height":
+ this._invalidateHasFlexY();
+ break;
+ }
+ }
+}
+
+qx.Proto._unitDetectionPixelPercentAuto = function(propData, propValue)
+{
+ var r = qx.ui.core.Widget.layoutPropertyTypes[propData.name];
+
+ var s = r.dataType;
+ var p = r.dataParsed;
+ var v = r.dataValue;
+
+ var s1 = r.typePixel;
+ var s2 = r.typePercent;
+ var s3 = r.typeAuto;
+ var s4 = r.typeNull;
+
+ var wasPercent = this[s2];
+ var wasAuto = this[s3];
+
+ switch(this[s] = this._evalUnitsPixelPercentAuto(propValue))
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ this[s1] = true;
+ this[s2] = this[s3] = this[s4] = false;
+ this[p] = this[v] = Math.round(propValue);
+ break;
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ this[s2] = true;
+ this[s1] = this[s3] = this[s4] = false;
+ this[p] = parseFloat(propValue);
+ this[v] = null;
+ break;
+
+ case qx.ui.core.Widget.TYPE_AUTO:
+ this[s3] = true;
+ this[s1] = this[s2] = this[s4] = false;
+ this[p] = this[v] = null;
+ break;
+
+ default:
+ this[s4] = true;
+ this[s1] = this[s2] = this[s3] = false;
+ this[p] = this[v] = null;
+ break;
+ }
+
+ if (wasPercent != this[s2])
+ {
+ switch(propData.name)
+ {
+ case "minWidth":
+ case "maxWidth":
+ case "width":
+ case "left":
+ case "right":
+ this._invalidateHasPercentX();
+ break;
+
+ case "minHeight":
+ case "maxHeight":
+ case "height":
+ case "top":
+ case "bottom":
+ this._invalidateHasPercentY();
+ break;
+ }
+ }
+
+ // No ELSE because you can also switch from percent to auto
+ if (wasAuto != this[s3])
+ {
+ switch(propData.name)
+ {
+ case "minWidth":
+ case "maxWidth":
+ case "width":
+ this._invalidateHasAutoX();
+ break;
+
+ case "minHeight":
+ case "maxHeight":
+ case "height":
+ this._invalidateHasAutoY();
+ break;
+ }
+ }
+}
+
+qx.Proto._unitDetectionPixelPercent = function(propData, propValue)
+{
+ var r = qx.ui.core.Widget.layoutPropertyTypes[propData.name];
+
+ var s = r.dataType;
+ var p = r.dataParsed;
+ var v = r.dataValue;
+
+ var s1 = r.typePixel;
+ var s2 = r.typePercent;
+ var s3 = r.typeNull;
+
+ var wasPercent = this[s2];
+
+ switch(this[s] = this._evalUnitsPixelPercent(propValue))
+ {
+ case qx.ui.core.Widget.TYPE_PIXEL:
+ this[s1] = true;
+ this[s2] = this[s3] = false;
+ this[p] = this[v] = Math.round(propValue);
+ break;
+
+ case qx.ui.core.Widget.TYPE_PERCENT:
+ this[s2] = true;
+ this[s1] = this[s3] = false;
+ this[p] = parseFloat(propValue);
+ this[v] = null;
+ break;
+
+ default:
+ this[s3] = true;
+ this[s1] = this[s2] = false;
+ this[p] = this[v] = null;
+ break;
+ }
+
+ if (wasPercent != this[s2])
+ {
+ switch(propData.name)
+ {
+ case "minWidth":
+ case "maxWidth":
+ case "width":
+ case "left":
+ case "right":
+ this._invalidateHasPercentX();
+ break;
+
+ case "minHeight":
+ case "maxHeight":
+ case "height":
+ case "top":
+ case "bottom":
+ this._invalidateHasPercentY();
+ break;
+ }
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INLINE EVENTS
+---------------------------------------------------------------------------
+*/
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.ui.core.Widget.inlineEventMap =
+ {
+ input : "onpropertychange",
+ select : "onselect",
+ scroll : "onscroll",
+ focus : "onfocus",
+ blur : "onblur"
+ }
+
+ qx.Proto.enableInlineEvent = function(vEventName)
+ {
+ var vEventType = qx.ui.core.Widget.inlineEventMap[vEventName];
+
+ if (!this._inlineEvents)
+ {
+ this._inlineEvents = [vEventType];
+ }
+ else
+ {
+ this._inlineEvents.push(vEventType);
+ }
+
+ if (this._isCreated) {
+ this.getElement()[vEventType] = qx.ui.core.Widget.__oninlineevent;
+ }
+ }
+
+ qx.Proto.disableInlineEvent = function(vEventName)
+ {
+ var vEventType = qx.ui.core.Widget.inlineEventMap[vEventName];
+
+ if (this._inlineEvents) {
+ qx.lang.Array.remove(this._inlineEvents, vEventType);
+ }
+
+ if (this._isCreated) {
+ this.getElement()[vEventType] = null;
+ }
+ }
+
+ qx.Proto._addInlineEvents = function(vElement)
+ {
+ if (this._inlineEvents)
+ {
+ for (var i=0, a=this._inlineEvents, l=a.length; i<l; i++) {
+ vElement[a[i]] = qx.ui.core.Widget.__oninlineevent;
+ }
+ }
+ }
+
+ qx.Proto._removeInlineEvents = function(vElement)
+ {
+ if (this._inlineEvents)
+ {
+ for (var i=0, a=this._inlineEvents, l=a.length; i<l; i++) {
+ vElement[a[i]] = null;
+ }
+ }
+ }
+}
+else
+{
+ qx.Proto.enableInlineEvent = function(vEventName)
+ {
+ if (!this._inlineEvents)
+ {
+ this._inlineEvents = [vEventName];
+ }
+ else
+ {
+ this._inlineEvents.push(vEventName);
+ }
+
+ if (this._isCreated) {
+ this.getElement().addEventListener(vEventName, qx.ui.core.Widget.__oninlineevent, false);
+ }
+ }
+
+ qx.Proto.disableInlineEvent = function(vEventName)
+ {
+ if (this._inlineEvents) {
+ qx.lang.Array.remove(this._inlineEvents, vEventName);
+ }
+
+ if (this._isCreated) {
+ this.getElement().removeEventListener(vEventName, qx.ui.core.Widget.__oninlineevent, false);
+ }
+ }
+
+ qx.Proto._addInlineEvents = function(vElement)
+ {
+ if (this._inlineEvents)
+ {
+ for (var i=0, a=this._inlineEvents, l=a.length; i<l; i++) {
+ vElement.addEventListener(a[i], qx.ui.core.Widget.__oninlineevent, false);
+ }
+ }
+ }
+
+ qx.Proto._removeInlineEvents = function(vElement)
+ {
+ if (this._inlineEvents)
+ {
+ for (var i=0, a=this._inlineEvents, l=a.length; i<l; i++) {
+ vElement.removeEventListener(a[i], qx.ui.core.Widget.__oninlineevent, false);
+ }
+ }
+ }
+}
+
+qx.ui.core.Widget.__oninlineevent = function(e)
+{
+ if (!e) {
+ e = window.event;
+ }
+
+ if (this.qx_Widget) {
+ return this.qx_Widget._oninlineevent(e);
+ }
+}
+
+qx.Proto._oninlineevent = function(e)
+{
+ if (qx.ui.core.Widget._inFlushGlobalQueues) {
+ return;
+ }
+
+ // this.debug("Inlineevent: " + e.type);
+
+ switch(e.type)
+ {
+ case "propertychange":
+ this._oninlineproperty(e);
+ break;
+
+ case "input":
+ this._oninlineinput(e);
+ break;
+
+ default:
+ this.createDispatchEvent(e.type);
+ }
+}
+
+qx.Proto._oninlineinput = function(e)
+{
+ this.createDispatchDataEvent("input", this.getComputedValue());
+
+ // Block parents from this event
+ if (e.stopPropagation) {
+ e.stopPropagation();
+ }
+
+ e.returnValue = -1;
+}
+
+qx.Proto._oninlineproperty = function(e)
+{
+ switch(e.propertyName)
+ {
+ case "value":
+ if (!this._inValueProperty) {
+ this._oninlineinput(e);
+ }
+
+ break;
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CHILDREN MANAGMENT
+---------------------------------------------------------------------------
+*/
+
+/*!
+ The widget which is at the top level,
+ which contains all others (normally a
+ instance of qx.ui.core.ClientDocument).
+*/
+qx.Proto.getTopLevelWidget = function() {
+ return this._hasParent ? this.getParent().getTopLevelWidget() : null;
+}
+
+/*!
+ Move myself to immediately before another child of the same parent.
+*/
+qx.Proto.moveSelfBefore = function(vBefore) {
+ this.getParent().addBefore(this, vBefore);
+}
+
+/*!
+ Move myself to immediately after another child of the same parent.
+*/
+qx.Proto.moveSelfAfter = function(vAfter) {
+ this.getParent().addAfter(this, vAfter);
+}
+
+/*!
+ Move myself to the head of the list: make me the first child.
+*/
+qx.Proto.moveSelfToBegin = function() {
+ this.getParent().addAtBegin(this);
+}
+
+/*!
+ Move myself to the end of the list: make me the last child.
+*/
+qx.Proto.moveSelfToEnd = function() {
+ this.getParent().addAtEnd(this);
+}
+
+/*!
+ Returns the previous sibling.
+*/
+qx.Proto.getPreviousSibling = function()
+{
+ var p = this.getParent();
+
+ if(p == null) {
+ return null;
+ }
+
+ var cs = p.getChildren();
+ return cs[cs.indexOf(this) - 1];
+}
+
+/*!
+ Returns the next sibling.
+*/
+qx.Proto.getNextSibling = function()
+{
+ var p = this.getParent();
+
+ if(p == null) {
+ return null;
+ }
+
+ var cs = p.getChildren();
+ return cs[cs.indexOf(this) + 1];
+}
+
+/*!
+ Returns the previous visible sibling.
+*/
+qx.Proto.getPreviousVisibleSibling = function()
+{
+ if(!this._hasParent) {
+ return null;
+ }
+
+ var vChildren = this.getParent().getVisibleChildren();
+ return vChildren[vChildren.indexOf(this) - 1];
+}
+
+/*!
+ Returns the next visible sibling.
+*/
+qx.Proto.getNextVisibleSibling = function()
+{
+ if(!this._hasParent) {
+ return null;
+ }
+
+ var vChildren = this.getParent().getVisibleChildren();
+ return vChildren[vChildren.indexOf(this) + 1];
+}
+
+qx.Proto.getPreviousActiveSibling = function(vIgnoreClasses)
+{
+ var vPrev = qx.ui.core.Widget.getActiveSiblingHelper(this, this.getParent(), -1, vIgnoreClasses, null);
+ return vPrev ? vPrev : this.getParent().getLastActiveChild();
+}
+
+qx.Proto.getNextActiveSibling = function(vIgnoreClasses)
+{
+ var vNext = qx.ui.core.Widget.getActiveSiblingHelper(this, this.getParent(), 1, vIgnoreClasses, null);
+ return vNext ? vNext : this.getParent().getFirstActiveChild();
+}
+
+qx.Proto.isFirstChild = function() {
+ return this._hasParent && this.getParent().getFirstChild() == this;
+}
+
+qx.Proto.isLastChild = function() {
+ return this._hasParent && this.getParent().getLastChild() == this;
+}
+
+qx.Proto.isFirstVisibleChild = function() {
+ return this._hasParent && this.getParent().getFirstVisibleChild() == this;
+}
+
+qx.Proto.isLastVisibleChild = function() {
+ return this._hasParent && this.getParent().getLastVisibleChild() == this;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ENABLED MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyEnabled = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ this.removeState("disabled");
+ }
+ else
+ {
+ this.addState("disabled");
+
+ // Also reset some states to be sure a pressed/hovered button gets reset
+ this.removeState("over");
+
+ if (qx.OO.isAvailable("qx.ui.form.Button"))
+ {
+ this.removeState("abandoned");
+ this.removeState("pressed");
+ }
+ }
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ STATE HANDLING
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Returns whether a state is set.
+ *
+ * @param vState {string} the state to check.
+ * @return {boolean} whether the state is set.
+ */
+qx.Proto.hasState = function(vState) {
+ return this._states[vState] ? true : false;
+}
+
+/**
+ * Sets a state.
+ *
+ * @param state {string} the state to set.
+ */
+qx.Proto.addState = function(vState)
+{
+ if (! this._states[vState]) {
+ this._states[vState] = true;
+
+ if (this._hasParent) {
+ qx.ui.core.Widget.addToGlobalStateQueue(this);
+ }
+ }
+}
+
+/**
+ * Clears a state.
+ *
+ * @param vState {string} the state to clear.
+ */
+qx.Proto.removeState = function(vState)
+{
+ if (this._states[vState]) {
+ delete this._states[vState];
+
+ if (this._hasParent) {
+ qx.ui.core.Widget.addToGlobalStateQueue(this);
+ }
+ }
+}
+
+/**
+ * Sets or clears a state.
+ *
+ * @param state {string} the state to set or clear.
+ * @param enabled {boolean} whether the state should be set.
+ * If false it will be cleared.
+ */
+qx.Proto.setState = function(state, enabled) {
+ if (enabled) {
+ this.addState(state);
+ } else {
+ this.removeState(state);
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEARANCE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyInitialAppearance = function()
+{
+ var vAppearance = this.getAppearance();
+
+ if (vAppearance)
+ {
+ try
+ {
+ var r = qx.manager.object.AppearanceManager.getInstance().getAppearanceTheme().initialFrom(vAppearance);
+ if (r) {
+ this.set(r);
+ }
+ }
+ catch(ex)
+ {
+ this.error("Could not apply initial appearance", ex);
+ }
+ }
+}
+
+qx.Proto._applyStateAppearance = function()
+{
+ // HACK: Is there a cleaner way to implement this?
+ // Maybe not use the appearance for this, but a simple property and event handler combination?
+ this._applyStateStyleFocus(this._states);
+
+ var vAppearance = this.getAppearance();
+
+ if (vAppearance)
+ {
+ try
+ {
+ var r = qx.manager.object.AppearanceManager.getInstance().getAppearanceTheme().stateFrom(vAppearance, this._states);
+ if (r) {
+ this.set(r);
+ }
+ }
+ catch(ex)
+ {
+ this.error("Could not apply state appearance", ex);
+ }
+ }
+}
+
+qx.Proto._resetAppearanceThemeWrapper = function(vNewAppearanceTheme, vOldAppearanceTheme)
+{
+ var vAppearance = this.getAppearance();
+
+ if (vAppearance)
+ {
+ var vOldAppearanceThemeObject = qx.manager.object.AppearanceManager.getInstance().getThemeById(vOldAppearanceTheme);
+ var vNewAppearanceThemeObject = qx.manager.object.AppearanceManager.getInstance().getThemeById(vNewAppearanceTheme);
+
+ var vOldAppearanceProperties = qx.lang.Object.mergeWith(vOldAppearanceThemeObject.initialFrom(vAppearance), vOldAppearanceThemeObject.stateFrom(vAppearance, this._states));
+ var vNewAppearanceProperties = qx.lang.Object.mergeWith(vNewAppearanceThemeObject.initialFrom(vAppearance), vNewAppearanceThemeObject.stateFrom(vAppearance, this._states));
+
+ for (var vProp in vOldAppearanceProperties)
+ {
+ if (!(vProp in vNewAppearanceProperties)) {
+ this[qx.OO.resetter[vProp]]();
+ }
+ }
+
+ this.set(vNewAppearanceProperties);
+ }
+}
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ /*
+ Mshtml does not support outlines by css
+ */
+ qx.Proto._applyStateStyleFocus = function(vStates) {}
+}
+else if (qx.sys.Client.getInstance().isGecko())
+{
+ qx.Proto._applyStateStyleFocus = function(vStates)
+ {
+ if (vStates.focused)
+ {
+ if (!qx.event.handler.FocusHandler.mouseFocus && !this.getHideFocus())
+ {
+ this.setStyleProperty("MozOutline", "1px dotted invert");
+ }
+ }
+ else
+ {
+ this.removeStyleProperty("MozOutline");
+ }
+ }
+}
+else
+{
+ qx.Proto._applyStateStyleFocus = function(vStates)
+ {
+ if (vStates.focused)
+ {
+ if (!qx.event.handler.FocusHandler.mouseFocus && !this.getHideFocus())
+ {
+ this.setStyleProperty("outline", "1px dotted invert");
+ }
+ }
+ else
+ {
+ this.setStyleProperty("outline", "0px none");
+ }
+ }
+}
+
+qx.Proto.addToStateQueue = function() {
+ qx.ui.core.Widget.addToGlobalStateQueue(this);
+}
+
+qx.Proto.recursiveAddToStateQueue = function() {
+ this.addToStateQueue();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEARANCE MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyAppearance = function(propValue, propOldValue, propData)
+{
+ var vAppearanceThemeObject = qx.manager.object.AppearanceManager.getInstance().getAppearanceTheme();
+
+ var vNewAppearanceProperties = vAppearanceThemeObject.initialFrom(propValue);
+
+ if (this.isCreated()) {
+ qx.lang.Object.mergeWith(vNewAppearanceProperties, vAppearanceThemeObject.stateFrom(propValue, this._states));
+ }
+
+ if (propOldValue)
+ {
+ var vOldAppearanceProperties = vAppearanceThemeObject.initialFrom(propOldValue);
+
+ if (this.isCreated()) {
+ qx.lang.Object.mergeWith(vOldAppearanceProperties, vAppearanceThemeObject.stateFrom(propOldValue, this._states));
+ }
+
+ for (var vProp in vOldAppearanceProperties)
+ {
+ if (!(vProp in vNewAppearanceProperties)) {
+ this[qx.OO.resetter[vProp]]();
+ }
+ }
+ }
+
+ this.set(vNewAppearanceProperties);
+
+ return true;
+}
+
+qx.Proto._recursiveAppearanceThemeUpdate = function(vNewAppearanceTheme, vOldAppearanceTheme)
+{
+ try
+ {
+ this._resetAppearanceThemeWrapper(vNewAppearanceTheme, vOldAppearanceTheme);
+ }
+ catch(ex)
+ {
+ this.error("Failed to update appearance theme", ex);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ELEMENT DATA
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Placeholder method to add attributes and other content to element node
+*/
+qx.Proto._applyElementData = function(el) {}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HTML PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.setHtmlProperty = function(propName, propValue)
+{
+ if (!this._htmlProperties) {
+ this._htmlProperties = {};
+ }
+
+ this._htmlProperties[propName] = propValue;
+
+ if (this._isCreated && this.getElement()[propName] != propValue) {
+ this.getElement()[propName] = propValue;
+ }
+
+ return true;
+}
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto.removeHtmlProperty = function(propName)
+ {
+ if (!this._htmlProperties) {
+ return;
+ }
+
+ delete this._htmlProperties[propName];
+
+ if (this._isCreated) {
+ this.getElement().removeAttribute(propName);
+ }
+
+ return true;
+ }
+}
+else
+{
+ qx.Proto.removeHtmlProperty = function(propName)
+ {
+ if (!this._htmlProperties) {
+ return;
+ }
+
+ delete this._htmlProperties[propName];
+
+ if (this._isCreated)
+ {
+ this.getElement().removeAttribute(propName);
+ delete this.getElement()[propName];
+ }
+
+ return true;
+ }
+}
+
+qx.Proto.getHtmlProperty = function(propName)
+{
+ if (!this._htmlProperties) {
+ return "";
+ }
+
+ return this._htmlProperties[propName] || "";
+}
+
+qx.Proto._applyHtmlProperties = function(vElement)
+{
+ var vProperties = this._htmlProperties;
+
+ if (vProperties)
+ {
+ // this.debug("HTML-Properties: " + qx.lang.Object.getLength(vProperties));
+
+ var propName;
+
+ for (propName in vProperties) {
+ vElement[propName] = vProperties[propName];
+ }
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HTML ATTRIBUTES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.setHtmlAttribute = function(propName, propValue)
+{
+ if (!this._htmlAttributes) {
+ this._htmlAttributes = {};
+ }
+
+ this._htmlAttributes[propName] = propValue;
+
+ if (this._isCreated) {
+ this.getElement().setAttribute(propName, propValue);
+ }
+
+ return true;
+}
+
+qx.Proto.removeHtmlAttribute = function(propName)
+{
+ if (!this._htmlAttributes) {
+ return;
+ }
+
+ delete this._htmlAttributes[propName];
+
+ if (this._isCreated) {
+ this.getElement().removeAttribute(propName);
+ }
+
+ return true;
+}
+
+qx.Proto.getHtmlAttribute = function(propName)
+{
+ if (!this._htmlAttributes) {
+ return "";
+ }
+
+ return this._htmlAttributes[propName] || "";
+}
+
+qx.Proto._applyHtmlAttributes = function(vElement)
+{
+ var vAttributes = this._htmlAttributes;
+
+ if (vAttributes)
+ {
+ // this.debug("HTML-Attributes: " + qx.lang.Object.getLength(vAttributes));
+
+ var propName;
+
+ for (propName in vAttributes) {
+ vElement.setAttribute(propName, vAttributes[propName]);
+ }
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ STYLE PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getStyleProperty = function(propName) {
+ return this._styleProperties[propName] || "";
+}
+
+qx.Proto.setStyleProperty = function(propName, propValue)
+{
+ this._styleProperties[propName] = propValue;
+
+ if (this._isCreated)
+ {
+ /*
+ The zIndex and filter properties should always be
+ applied on the "real" element node.
+ */
+ switch(propName)
+ {
+ case "zIndex":
+ case "filter":
+ case "display":
+ case "visibility":
+ var vElement = this.getElement();
+ break;
+
+ default:
+ var vElement = this._getTargetNode();
+ }
+
+ if (vElement) {
+ vElement.style[propName] = propValue;
+ }
+ }
+
+ return true;
+}
+
+qx.Proto.removeStyleProperty = function(propName)
+{
+ delete this._styleProperties[propName];
+
+ if (this._isCreated)
+ {
+ /*
+ The zIndex and filter properties should always be
+ applied on the "real" element node.
+ */
+ switch(propName)
+ {
+ case "zIndex":
+ case "filter":
+ case "display":
+ case "visibility":
+ var vElement = this.getElement();
+ break;
+
+ default:
+ var vElement = this._getTargetNode();
+ }
+
+ if (vElement) {
+ vElement.style[propName] = "";
+ }
+ }
+
+ return true;
+}
+
+qx.Proto._applyStyleProperties = function(vElement)
+{
+ var vProperties = this._styleProperties;
+ var propName;
+
+ var vBaseElement = vElement;
+ var vTargetElement = this._getTargetNode();
+
+ for (propName in vProperties)
+ {
+ /*
+ The zIndex and filter properties should always be
+ applied on the "real" element node.
+ */
+ switch(propName)
+ {
+ case "zIndex":
+ case "filter":
+ vElement = vBaseElement;
+ break;
+
+ default:
+ vElement = vTargetElement;
+ }
+
+ vElement.style[propName] = vProperties[propName];
+ }
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ FOCUS HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.isFocusable = function() {
+ return this.isEnabled() && this.isSeeable() && this.getTabIndex() >= 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<a.length; i++)
+ {
+ if (a[i]!=pn) {
+ this.removeStyleProperty(a[i]);
+ }
+ }
+
+ return this._applyOverflow(pn, pv, propValue, propOldValue);
+ }
+}
+
+// Opera/Khtml Mode...
+// hopefully somewhat of this is supported in the near future.
+
+// overflow-x and overflow-y are also not supported by Opera 9.0 Beta1
+// and also not if we switch to IE emulation mode
+else
+{
+ qx.Proto._modifyOverflow = function(propValue, propOldValue, propData)
+ {
+ var pv = propValue;
+ var pn = propData.name;
+
+ switch(pv)
+ {
+ case "scrollX":
+ case "scrollY":
+ pv = "scroll";
+ break;
+ }
+
+ return this._applyOverflow(pn, pv, propValue, propOldValue);
+ }
+}
+
+qx.Proto._applyOverflow = function(pn, pv, propValue, propOldValue)
+{
+ // Apply Style
+ this.setStyleProperty(pn, pv);
+
+ // Invalidate Frame
+ this._invalidateFrameWidth();
+ this._invalidateFrameHeight();
+
+ return true;
+}
+
+qx.Proto.getOverflowX = function()
+{
+ var vOverflow = this.getOverflow();
+ return vOverflow == "scrollY" ? "hidden" : vOverflow;
+}
+
+qx.Proto.getOverflowY = function()
+{
+ var vOverflow = this.getOverflow();
+ return vOverflow == "scrollX" ? "hidden" : vOverflow;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HIDE FOCUS
+---------------------------------------------------------------------------
+*/
+
+if (qx.sys.Client.getInstance().isMshtml())
+{
+ qx.Proto._modifyHideFocus = function(propValue, propOldValue, propData)
+ {
+ this.setHtmlProperty(propData.name, propValue);
+ return true;
+ }
+}
+
+// Need no implementation for others then mshtml, because
+// all these browsers support css outlines and do not
+// have an attribute "hideFocus" as IE.
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ COLORS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyBackgroundColor = function(propValue, propOldValue, propData)
+{
+ if (propOldValue) {
+ propOldValue.remove(this);
+ }
+
+ if (propValue)
+ {
+ this._applyBackgroundColor(propValue.getStyle());
+ propValue.add(this);
+ }
+ else
+ {
+ this._resetBackgroundColor();
+ }
+
+ return true;
+}
+
+qx.Proto._modifyColor = function(propValue, propOldValue, propData)
+{
+ if (propOldValue) {
+ propOldValue.remove(this);
+ }
+
+ if (propValue)
+ {
+ this._applyColor(propValue.getStyle());
+ propValue.add(this);
+ }
+ else
+ {
+ this._resetColor();
+ }
+
+ return true;
+}
+
+qx.Proto._updateColors = function(vColor, vNewValue)
+{
+ if (this.getColor() == vColor) {
+ this._applyColor(vNewValue);
+ }
+
+ if (this.getBackgroundColor() == vColor) {
+ this._applyBackgroundColor(vNewValue);
+ }
+}
+
+qx.Proto._applyColor = function(vNewValue) {
+ this.setStyleProperty("color", vNewValue);
+}
+
+qx.Proto._applyBackgroundColor = function(vNewValue) {
+ this.setStyleProperty("backgroundColor", vNewValue);
+}
+
+qx.Proto._resetColor = function(vNewValue) {
+ this.removeStyleProperty("color");
+}
+
+qx.Proto._resetBackgroundColor = function() {
+ this.removeStyleProperty("backgroundColor");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ BORDER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._cachedBorderTop = 0;
+qx.Proto._cachedBorderRight = 0;
+qx.Proto._cachedBorderBottom = 0;
+qx.Proto._cachedBorderLeft = 0;
+
+qx.Proto._modifyBorder = function(propValue, propOldValue, propData)
+{
+ var vOldTop = this._cachedBorderTop;
+ var vOldRight = this._cachedBorderRight;
+ var vOldBottom = this._cachedBorderBottom;
+ var vOldLeft = this._cachedBorderLeft;
+
+ if (propOldValue) {
+ propOldValue.removeListenerWidget(this);
+ }
+
+ if (propValue)
+ {
+ propValue.addListenerWidget(this);
+
+ this._cachedBorderTop = propValue.getTopWidth();
+ this._cachedBorderRight = propValue.getRightWidth();
+ this._cachedBorderBottom = propValue.getBottomWidth();
+ this._cachedBorderLeft = propValue.getLeftWidth();
+ }
+ else
+ {
+ this._cachedBorderTop = this._cachedBorderRight = this._cachedBorderBottom = this._cachedBorderLeft = 0;
+ }
+
+
+
+ // ----------------
+ // X-AXIS
+ // ----------------
+ if ((vOldLeft + vOldRight) != (this._cachedBorderLeft + this._cachedBorderRight)) {
+ this._invalidateFrameWidth();
+ }
+
+ this.addToQueue("borderX");
+
+
+
+ // ----------------
+ // Y-AXIS
+ // ----------------
+ if ((vOldTop + vOldBottom) != (this._cachedBorderTop + this._cachedBorderBottom)) {
+ this._invalidateFrameHeight();
+ }
+
+ this.addToQueue("borderY");
+
+
+
+
+
+ return true;
+}
+
+qx.Proto.getCachedBorderTop = function() {
+ return this._cachedBorderTop;
+}
+
+qx.Proto.getCachedBorderRight = function() {
+ return this._cachedBorderRight;
+}
+
+qx.Proto.getCachedBorderBottom = function() {
+ return this._cachedBorderBottom;
+}
+
+qx.Proto.getCachedBorderLeft = function() {
+ return this._cachedBorderLeft;
+}
+
+qx.Proto._updateBorder = function(vEdge)
+{
+ // Small hack, remove later: TODO
+ // ?? Anybody have an idea about this TODO?
+ var vBorder = this.getBorder();
+ var vEdgeUp = qx.lang.String.toFirstUp(vEdge);
+
+ var vNewValue = vBorder["get" + vEdgeUp + "Width"]();
+ var vCacheName = "_cachedBorder" + vEdgeUp;
+ var vWidthChanged = this[vCacheName] != vNewValue;
+
+ this[vCacheName] = vNewValue;
+
+ switch(vEdge)
+ {
+ case "left":
+ case "right":
+ if (vWidthChanged) {
+ this.addToJobQueue("borderWidthX");
+ }
+
+ this.addToJobQueue("borderX");
+ break;
+
+ case "top":
+ case "bottom":
+ if (vWidthChanged) {
+ this.addToJobQueue("borderWidthY");
+ }
+
+ this.addToJobQueue("borderY");
+ break;
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PADDING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyPaddingX = function(propValue, propOldValue, propData)
+{
+ this._invalidateFrameWidth();
+ return true;
+}
+
+qx.Proto._modifyPaddingY = function(propValue, propOldValue, propData)
+{
+ this._invalidateFrameHeight();
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CLONE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._clonePropertyIgnoreList = "parent,element,visible";
+
+
+/*!
+Returns a cloned copy of the current instance of qx.ui.core.Widget.
+
+#param cloneRecursive[Boolean]: Should the widget cloned recursive (including all childs)?
+#param customPropertyList[Array]: Optional (reduced) list of properties to copy through
+*/
+
+// TODO: Needs modification to work with new codebase
+qx.Proto.clone = function(cloneRecursive, customPropertyList)
+{
+ var cloneInstance = new this.constructor;
+
+ var propertyName;
+ var propertyList = [];
+ var propertyIngoreList = this._clonePropertyIgnoreList.split(",");
+
+ // Build new filtered property list
+ var sourcePropertyList = qx.util.Validation.isValid(customPropertyList) ? customPropertyList : this._properties.split(",");
+ var sourcePropertyListLength = sourcePropertyList.length-1;
+ do {
+ propertyName = sourcePropertyList[sourcePropertyListLength];
+ if (!qx.lang.Array.contains(propertyIngoreList, propertyName)) {
+ propertyList.push(propertyName);
+ }
+ }
+ while(sourcePropertyListLength--);
+
+ // Apply properties to new clone instance
+ propertyListLength = propertyList.length-1;
+ do {
+ propertyName = qx.lang.String.toFirstUp(propertyList[propertyListLength]);
+ cloneInstance["set" + propertyName](this["get" + propertyName]());
+ }
+ while(propertyListLength--);
+
+ // post apply parent info
+ if (qx.lang.Array.contains(sourcePropertyList, "parent"))
+ {
+ var myParent = this.getParent();
+ if (myParent) {
+ cloneInstance.setParent(myParent);
+ }
+ }
+
+ // clone recursion
+ if (cloneRecursive) {
+ this._cloneRecursive(cloneInstance);
+ }
+
+ return cloneInstance;
+}
+
+qx.Proto._cloneRecursive = function(cloneInstance) {}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ COMMAND INTERFACE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.execute = function()
+{
+ var vCommand = this.getCommand();
+ if (vCommand) {
+ vCommand.execute(this);
+ }
+
+ this.createDispatchEvent("execute");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ NODE ALIASES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._visualPropertyCheck = function()
+{
+ if (!this.isCreated()) {
+ throw new Error("Element must be created previously!");
+ }
+}
+
+qx.Proto.setScrollLeft = function(nScrollLeft)
+{
+ this._visualPropertyCheck();
+ this._getTargetNode().scrollLeft = nScrollLeft;
+}
+
+qx.Proto.setScrollTop = function(nScrollTop)
+{
+ this._visualPropertyCheck();
+ this._getTargetNode().scrollTop = nScrollTop;
+}
+
+qx.Proto.getOffsetLeft = function()
+{
+ this._visualPropertyCheck();
+ return qx.dom.Offset.getLeft(this.getElement());
+}
+
+qx.Proto.getOffsetTop = function()
+{
+ this._visualPropertyCheck();
+ return qx.dom.Offset.getTop(this.getElement());
+}
+
+qx.Proto.getScrollLeft = function()
+{
+ this._visualPropertyCheck();
+ return this._getTargetNode().scrollLeft;
+}
+
+qx.Proto.getScrollTop = function()
+{
+ this._visualPropertyCheck();
+ return this._getTargetNode().scrollTop;
+}
+
+qx.Proto.getClientWidth = function()
+{
+ this._visualPropertyCheck();
+ return this._getTargetNode().clientWidth;
+}
+
+qx.Proto.getClientHeight = function()
+{
+ this._visualPropertyCheck();
+ return this._getTargetNode().clientHeight;
+}
+
+qx.Proto.getOffsetWidth = function()
+{
+ this._visualPropertyCheck();
+ return this.getElement().offsetWidth;
+}
+
+qx.Proto.getOffsetHeight = function()
+{
+ this._visualPropertyCheck();
+ return this.getElement().offsetHeight;
+}
+
+qx.Proto.getScrollWidth = function()
+{
+ this._visualPropertyCheck();
+ return this.getElement().scrollWidth;
+}
+
+qx.Proto.getScrollHeight = function()
+{
+ this._visualPropertyCheck();
+ return this.getElement().scrollHeight;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ SCROLL INTO VIEW
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.scrollIntoView = function(vAlignTopLeft)
+{
+ this.scrollIntoViewX(vAlignTopLeft);
+ this.scrollIntoViewY(vAlignTopLeft);
+}
+
+qx.Proto.scrollIntoViewX = function(vAlignLeft)
+{
+ if (!this._isCreated || !this._isDisplayable) {
+ return false;
+ }
+
+ return qx.dom.ScrollIntoView.scrollX(this.getElement(), vAlignLeft);
+}
+
+qx.Proto.scrollIntoViewY = function(vAlignTop)
+{
+ if (!this._isCreated || !this._isDisplayable) {
+ return false;
+ }
+
+ return qx.dom.ScrollIntoView.scrollY(this.getElement(), vAlignTop);
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DRAG AND DROP SUPPORT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.supportsDrop = function(vDragCache) {
+ return true;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ FADING PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ The amount of steps for the fade.
+ */
+qx.OO.addProperty({ name : 'fadeSteps', type : "number", allowNull : false, defaultValue : 10});
+/*!
+ The duration for the fade.
+ */
+qx.OO.addProperty({ name : 'fadeTime', type : "number", allowNull : false, defaultValue : 400});
+/*!
+ The time between the fade steps.
+ */
+qx.OO.addProperty({ name : 'fadeInterval', type : "number", allowNull : false, defaultValue : 40});
+/*!
+ The current state of a fade in progress.
+ */
+qx.OO.addProperty({ name : 'fadeCounter', type : "number", allowNull : false, defaultValue : 0});
+/*!
+ The amount of oppacity changed on each fade step.
+ */
+qx.OO.addProperty({ name : 'fadeUnit', type : "number", allowNull : false, defaultValue : 10});
+/*!
+ The maximum opacity for a fadeIn.
+ */
+qx.OO.addProperty({ name : 'fadeMax', type : "number", allowNull : false, defaultValue : 100});
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ FADING SUPPORT
+---------------------------------------------------------------------------
+*/
+qx.ui.core.Widget.FADE_IN = 'FADE_IN';
+qx.ui.core.Widget.FADE_OUT = 'FADE_OUT';
+qx.ui.core.Widget.FADE_FINISHED = 'FADE_FINISHED';
+
+
+qx.Proto.fadeIn = function(vSteps, vTime) {
+ if(vSteps) this.setFadeSteps(vSteps);
+ if(vTime) this.setFadeTime(vTime);
+ this._fadeMode = qx.ui.core.Widget.FADE_IN;
+ var timer = this.getFadeTimer();
+ timer.addEventListener("interval", this._onInterval, this);
+ timer.start();
+}
+
+qx.Proto.fadeOut = function(vSteps, vTime) {
+ if(vSteps) this.setFadeSteps(vSteps);
+ if(vTime) this.setFadeTime(vTime);
+ this._fadeMode = qx.ui.core.Widget.FADE_OUT;
+ var timer = this.getFadeTimer();
+ timer.addEventListener("interval", this._onInterval, this);
+ timer.start();
+};
+
+qx.Proto.getFadeTimer = function() {
+ if(this._fadeTimer){
+ this._fadeTimer.setInterval(this.getFadeInterval());
+ } else {
+ this._fadeTimer = new qx.client.Timer(this.getFadeInterval());
+ };
+ return this._fadeTimer;
+};
+
+qx.Proto.resetFader = function() {
+ this.setFadeCounter(0);
+ if(this.getFadeTimer()) {
+ this._fadeTimer.stop();
+ this._fadeTimer.dispose();
+ };
+ this._fadeTimer.dispose();
+ this._fadeTimer = null;
+};
+
+qx.Proto._onInterval = function(e) {
+ this.getFadeTimer().stop();
+ var counter = this.getFadeCounter();
+ switch (this._fadeMode){
+ case qx.ui.core.Widget.FADE_IN:
+ this.setFadeCounter(++counter);
+ if(counter <= this.getFadeSteps()){
+ 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_IN);
+ };
+ break;
+
+ case qx.ui.core.Widget.FADE_OUT:
+ this.setFadeCounter(--counter);
+ if(counter >= 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("<param name='");
+ vParamTags.push(vKey);
+ vParamTags.push("' value='");
+ vParamTags.push(vParams[vKey]);
+ 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("<embed type='application/x-shockwave-flash' width='100%' height='100%' src='");
+ html.push(this._source);
+ html.push("'");
+
+ var params = this.getParams();
+
+ for (var key in params)
+ {
+ html.push(" ");
+ html.push(key);
+ html.push("=");
+ html.push("'");
+ html.push(params[key]);
+ html.push("'");
+ }
+
+ var pairs = this.getVariablePairs();
+
+ if (pairs.length > 0)
+ {
+ html.push(" ");
+ html.push("flashvars");
+ html.push("=");
+ html.push("'");
+ html.push(pairs);
+ html.push("'");
+ }
+
+ html.push("></embed>");
+
+ 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("<object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000' width='100%' height='100%'>");
+ html.push("<param name='movie' value='");
+ html.push(this._source);
+ html.push("'/>");
+
+ var tags = this.generateParamTags();
+
+ if(tags.length > 0) {
+ html.push(tags);
+ }
+
+ var pairs = this.getVariablePairs();
+
+ if(pairs.length > 0)
+ {
+ html.push("<param name='flashvars' value='");
+ html.push(pairs);
+ html.push("'/>");
+ }
+
+ html.push("</object>");
+
+ 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<l; i++) {
+ if (a[i].id == vId) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+qx.Proto.getEntryById = function(vId) {
+ return this.getEntryByPosition(this.getPositionById(vId));
+}
+
+qx.Proto.getNodeById = function(vId) {
+ return this.getNodeByPosition(this.getPositionById(vId));
+}
+
+qx.Proto.getEntryByPosition = function(vPosition) {
+ return vPosition == -1 ? null : this._list[vPosition];
+}
+
+qx.Proto.getNodeByPosition = function(vPosition) {
+ return vPosition == -1 ? null : this._frame.childNodes[vPosition];
+}
+
+qx.Proto.getEntryByNode = function(vNode) {
+ return this.getEntryById(vNode.id);
+}
+
+qx.Proto.addFromPartialList = function(vPartialList)
+{
+ this.concat(vPartialList);
+
+ for (var i=0, a=vPartialList, l=a.length; i<l; i++) {
+ this._frame.appendChild(this.createCell(a[i], i));
+ }
+}
+
+qx.Proto.addFromUpdatedList = function(vNewList)
+{
+ for (var a=vNewList, l=a.length, i=this._list.length; i<l; i++) {
+ this._frame.appendChild(this.createCell(a[i], i));
+ }
+
+ this._list = vNewList;
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousedown = function(e)
+{
+ var vItem = this.getListItemTarget(e.getDomTarget());
+
+ if (vItem) {
+ this._manager.handleMouseDown(vItem, e);
+ }
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ var vItem = this.getListItemTarget(e.getDomTarget());
+
+ if (vItem) {
+ this._manager.handleMouseUp(vItem, e);
+ }
+}
+
+qx.Proto._onmousemove = function(e)
+{
+ if (qx.OO.isAvailable("qx.manager.object.ToolTipManager")) {
+ return;
+ }
+
+ var vItem = this.getListItemTarget(e.getDomTarget());
+
+ if (vItem == this._lastItem) {
+ return;
+ }
+
+ if (this._lastItem)
+ {
+ var vEventObject = new qx.event.type.MouseEvent("mouseout", e, false, this._lastItem);
+ qx.manager.object.ToolTipManager.getInstance().handleMouseOut(vEventObject);
+ vEventObject.dispose();
+ }
+
+ if (vItem)
+ {
+ if (this.hasEventListeners("beforeToolTipAppear")) {
+ this.dispatchEvent(new qx.event.type.DataEvent("beforeToolTipAppear", vItem), true);
+ }
+
+ if (!this.getToolTip()) {
+ return;
+ }
+
+ var vEventObject = new qx.event.type.MouseEvent("mouseout", e, false, vItem);
+ qx.manager.object.ToolTipManager.getInstance().handleMouseOver(vEventObject);
+ vEventObject.dispose();
+
+ this.setToolTip(null);
+ }
+
+ this._lastItem = vItem;
+}
+
+qx.Proto._onclick = function(e)
+{
+ var vItem = this.getListItemTarget(e.getDomTarget());
+
+ if (vItem) {
+ this._manager.handleClick(vItem, e);
+ }
+}
+
+qx.Proto._ondblclick = function(e)
+{
+ var vItem = this.getListItemTarget(e.getDomTarget());
+
+ if (vItem) {
+ this._manager.handleDblClick(vItem, e);
+ }
+}
+
+qx.Proto._onkeypress = function(e) {
+ this._manager.handleKeyPress(e);
+}
+
+qx.Proto.getListItemTarget = function(dt)
+{
+ while(dt.className.indexOf("galleryCell") == -1 && dt.tagName.toLowerCase() != "body") {
+ dt = dt.parentNode;
+ }
+
+ if (dt.tagName.toLowerCase() == "body") {
+ return null;
+ }
+
+ return dt;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ SCROLL INTO VIEW
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.scrollItemIntoView = function(vItem)
+{
+ this.scrollItemIntoViewX(vItem);
+ this.scrollItemIntoViewY(vItem);
+}
+
+qx.Proto.scrollItemIntoViewX = function(vItem) {
+ qx.dom.ScrollIntoView.scrollX(vItem);
+}
+
+qx.Proto.scrollItemIntoViewY = function(vItem) {
+ qx.dom.ScrollIntoView.scrollY(vItem);
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MANAGER REQUIREMENTS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getItems = function() {
+ return this._frame.childNodes;
+}
+
+qx.Proto.getFirstChild = function() {
+ return this._frame.childNodes[0];
+}
+
+qx.Proto.getLastChild = function() {
+ return this._frame.childNodes[this._frame.childNodes.length-1];
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INTERNALS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.createView = function()
+{
+ var s = (new Date).valueOf();
+
+ if (!this._protoCell) {
+ this.createProtoCell();
+ }
+
+ this._frame = document.createElement("div");
+ this._frame.className = "galleryFrame clearfix";
+
+ for (var i=0, a=this._list, l=a.length; i<l; i++) {
+ this._frame.appendChild(this.createCell(a[i], i));
+ }
+
+ return this._frame;
+}
+
+qx.Proto.createCell = function(d, i)
+{
+ var cframe = this._protoCell.cloneNode(true);
+
+ cframe.id = d.id;
+ cframe.pos = i;
+
+ if (this.getShowTitle())
+ {
+ cnode = cframe.childNodes[0];
+ cnode.firstChild.nodeValue = d.title;
+ }
+
+ var cnode = cframe.childNodes[this.getShowTitle() ? 1 : 0];
+ this.createImageCell(cnode, d);
+
+ if (this.getShowComment())
+ {
+ cnode = cframe.childNodes[this.getShowTitle() ? 2 : 1];
+ cnode.firstChild.nodeValue = d.comment;
+ }
+
+ return cframe;
+}
+
+qx.Proto._mshtml = qx.sys.Client.getInstance().isMshtml();
+
+qx.Proto.createImageCell = function(inode, d)
+{
+ if (this.hasEventListeners("loadComplete"))
+ {
+ inode.onload = qx.ui.embed.Gallery.imageOnLoad;
+ inode.onerror = qx.ui.embed.Gallery.imageOnError;
+ inode.gallery = this;
+ }
+
+ if (this._mshtml) {
+ inode.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + d.src + "',sizingMethod='scale')";
+ } else {
+ inode.src = d.src;
+ }
+
+ inode.width = d.thumbWidth + 2;
+ inode.height = d.thumbHeight + 2;
+ inode.style.marginLeft = inode.style.marginRight = Math.floor((this.getThumbMaxWidth()-d.thumbWidth)/2) + "px";
+ inode.style.marginTop = inode.style.marginBottom = Math.floor((this.getThumbMaxHeight()-d.thumbHeight)/2) + "px";
+}
+
+qx.Proto.imageOnComplete = function()
+{
+ this._processedImages++;
+
+ if(this._processedImages == this._listSize) {
+ this.dispatchEvent(new qx.event.type.Event("loadComplete"), true);
+ }
+}
+
+qx.ui.embed.Gallery.imageOnLoad = function()
+{
+ this.gallery.imageOnComplete();
+ this.gallery = null;
+ this.onload = null;
+ this.onerror = null;
+}
+
+qx.ui.embed.Gallery.imageOnError = function()
+{
+ this.gallery.imageOnComplete();
+ this.gallery = null;
+ this.onload = null;
+ this.onerror = null;
+}
+
+qx.Proto.createProtoCell = function()
+{
+ var frame = this._protoCell = document.createElement("div");
+ frame.className = "galleryCell";
+ frame.unselectable = "on";
+ frame.style.width = (this.getThumbMaxWidth() + 2) + "px";
+ frame.style.height = (this.getThumbMaxHeight() + this.getDecorHeight() + 2) + "px";
+
+ if (this.getShowTitle())
+ {
+ var title = document.createElement("div");
+ title.className = "galleryTitle";
+ title.unselectable = "on";
+ var ttext = document.createTextNode("-");
+ title.appendChild(ttext);
+
+ frame.appendChild(title);
+ }
+
+ var image = new Image();
+ image.src = this._blank;
+ frame.appendChild(image);
+
+ if (this.getShowComment())
+ {
+ var comment = document.createElement("div");
+ comment.className = "galleryComment";
+ comment.unselectable = "on";
+ var ctext = document.createTextNode("-");
+ comment.appendChild(ctext);
+
+ frame.appendChild(comment);
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ this._list = null;
+ this._protoCell = null;
+ this._frame = null;
+
+ if (this._manager)
+ {
+ this._manager.dispose();
+ this._manager = null;
+ }
+
+ this.removeEventListener("mousedown", this._onmousedown);
+ this.removeEventListener("mouseup", this._onmouseup);
+ this.removeEventListener("mousemove", this._onmousemove);
+
+ this.removeEventListener("click", this._onclick);
+ this.removeEventListener("dblclick", this._ondblclick);
+
+ this.removeEventListener("keypress", this._onkeypress);
+
+ return qx.ui.basic.Terminator.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/GalleryList.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/GalleryList.js
new file mode 100644
index 0000000000..c95b014f6d
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/GalleryList.js
@@ -0,0 +1,400 @@
+/* ************************************************************************
+
+ 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 loadComplete {qx.event.type.Event}
+ */
+qx.OO.defineClass("qx.ui.embed.GalleryList", qx.ui.basic.Terminator,
+function(galleryList)
+{
+ qx.ui.basic.Terminator.call(this);
+
+ this._blank = qx.manager.object.AliasManager.getInstance().resolvePath("static/image/blank.gif");
+ this._list = galleryList;
+ this._listSize = galleryList.length;
+ this._processedImages = 0;
+
+ this.setOverflow("auto");
+
+ this.setHtmlProperty("className", "qx_ui_embed_GalleryList");
+
+ this._manager = new qx.manager.selection.DomSelectionManager(this);
+
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+ this.addEventListener("click", this._onclick);
+ this.addEventListener("dblclick", this._ondblclick);
+ this.addEventListener("keypress", this._onkeypress);
+});
+
+qx.OO.addProperty({ name : "thumbMaxWidth", type : "number", defaultValue : 60 });
+qx.OO.addProperty({ name : "thumbMaxHeight", type : "number", defaultValue : 60 });
+qx.OO.addProperty({ name : "decorHeight", type : "number", defaultValue : 40 });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ELEMENT HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyElementData = function() {
+ this.getElement().appendChild(this.createView());
+}
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getManager = function() {
+ return this._manager;
+}
+
+
+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 = "";
+}
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousedown = function(e)
+{
+ var vItem = this.getListItemTarget(e.getDomTarget());
+
+ if (vItem) {
+ this._manager.handleMouseDown(vItem, e);
+ }
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ var vItem = this.getListItemTarget(e.getDomTarget());
+
+ if (vItem) {
+ this._manager.handleMouseUp(vItem, e);
+ }
+}
+
+qx.Proto._onclick = function(e)
+{
+ var vItem = this.getListItemTarget(e.getDomTarget());
+
+ if (vItem) {
+ this._manager.handleClick(vItem, e);
+ }
+}
+
+qx.Proto._ondblclick = function(e)
+{
+ var vItem = this.getListItemTarget(e.getDomTarget());
+
+ if (vItem) {
+ this._manager.handleDblClick(vItem, e);
+ }
+}
+
+qx.Proto._onkeypress = function(e) {
+ this._manager.handleKeyPress(e);
+}
+
+qx.Proto.getListItemTarget = function(dt)
+{
+ while(dt.className.indexOf("galleryCell") == -1 && dt.tagName.toLowerCase() != "body") {
+ dt = dt.parentNode;
+ }
+
+ if (dt.tagName.toLowerCase() == "body") {
+ return null;
+ }
+
+ return dt;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ SCROLL INTO VIEW
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.scrollItemIntoView = function(vItem)
+{
+ this.scrollItemIntoViewX(vItem);
+ this.scrollItemIntoViewY(vItem);
+}
+
+qx.Proto.scrollItemIntoViewX = function(vItem) {
+ qx.dom.ScrollIntoView.scrollX(vItem);
+}
+
+qx.Proto.scrollItemIntoViewY = function(vItem) {
+ qx.dom.ScrollIntoView.scrollY(vItem);
+}
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ SELECTION MANAGER API
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getItems = function() {
+ return this._frame.childNodes;
+}
+
+qx.Proto.getFirstChild = function() {
+ return this._frame.childNodes[0];
+}
+
+qx.Proto.getLastChild = function() {
+ return this._frame.childNodes[this._frame.childNodes.length-1];
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CREATE VIEW
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.createView = function()
+{
+ var s = (new Date).valueOf();
+
+ var protoCell = this.createProtoCell(this.getThumbMaxHeight());
+ var frame = this._frame = document.createElement("div");
+
+ this._frame.className = "galleryFrame clearfix";
+
+ var cframe, cnode;
+
+ for (var i=0, a=this._list, l=a.length, d; i<l; i++)
+ {
+ d = a[i];
+
+ cframe = protoCell.cloneNode(true);
+
+ cframe.id = d.id;
+ cframe.pos = i;
+
+ cnode = cframe.childNodes[0];
+ cnode.firstChild.nodeValue = d.number;
+
+ cnode = cframe.childNodes[1].firstChild;
+ this.createImageCell(cnode, d);
+
+ cnode = cframe.childNodes[2].firstChild;
+ cnode.firstChild.nodeValue = d.title;
+
+ cnode = cframe.childNodes[2].lastChild;
+ cnode.firstChild.nodeValue = d.comment;
+
+ frame.appendChild(cframe);
+ }
+
+ return frame;
+}
+
+qx.Proto._mshtml = qx.sys.Client.getInstance().isMshtml();
+
+qx.Proto.createImageCell = function(inode, d)
+{
+ if (this.hasEventListeners("loadComplete")) {
+ inode.onload = qx.ui.embed.GalleryList.imageOnLoad;
+ inode.onerror = qx.ui.embed.GalleryList.imageOnError;
+ inode.gallery = this;
+ }
+
+ inode.width = d.thumbWidth;
+ inode.height = d.thumbHeight;
+
+ if (this._mshtml) {
+ inode.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + d.src + "',sizingMethod='scale')";
+ } else {
+ inode.src = d.src;
+ }
+
+ inode.style.marginLeft = inode.style.marginRight = Math.floor((this.getThumbMaxWidth()-d.thumbWidth)/2) + "px";
+ inode.style.marginTop = inode.style.marginBottom = Math.floor((this.getThumbMaxHeight()-d.thumbHeight)/2) + "px";
+}
+
+qx.Proto.createProtoCell = function(tHeight)
+{
+ var frame = document.createElement("div");
+ frame.className = "galleryCell";
+ frame.unselectable = "on";
+ frame.style.height = (tHeight + 2) + "px";
+
+ var number = document.createElement("div");
+ number.className = "galleryNumber";
+ number.unselectable = "on";
+ var ntext = document.createTextNode("-");
+ number.appendChild(ntext);
+
+ var imageContainer = document.createElement("div");
+ imageContainer.className = "galleryImageContainer";
+ imageContainer.unselectable = "on";
+
+ var image = new Image();
+ image.src = this._blank;
+
+ imageContainer.appendChild(image);
+
+ var text = document.createElement("div");
+ text.className = "galleryText";
+ text.unselectable = "on";
+ text.style.width = (this.getWidth()-100-this.getThumbMaxWidth()) + "px";
+
+ var title = document.createElement("h3");
+ var ttext = document.createTextNode("-");
+ title.appendChild(ttext);
+ title.unselectable = "on";
+ text.appendChild(title);
+
+ var comment = document.createElement("p");
+ var ctext = document.createTextNode("-");
+ comment.appendChild(ctext);
+ comment.unselectable = "on";
+ text.appendChild(comment);
+
+
+ frame.appendChild(number);
+ frame.appendChild(imageContainer);
+ frame.appendChild(text);
+
+ return frame;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PRELOADING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.imageOnComplete = function()
+{
+ this._processedImages++;
+
+ if(this._processedImages == this._listSize) {
+ this.dispatchEvent(new qx.event.type.Event("loadComplete"), true);
+ }
+}
+
+qx.ui.embed.GalleryList.imageOnLoad = function()
+{
+ this.gallery.imageOnComplete();
+ this.gallery = null;
+ this.onload = null;
+ this.onerror = null;
+}
+
+qx.ui.embed.GalleryList.imageOnError = function()
+{
+ this.gallery.imageOnComplete();
+ this.gallery = null;
+ this.onload = null;
+ this.onerror = null;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ this._list = null;
+ this._frame = null;
+
+ if (this._manager)
+ {
+ this._manager.dispose();
+ this._manager = null;
+ }
+
+ this.removeEventListener("mousedown", this._onmousedown);
+ this.removeEventListener("mouseup", this._onmouseup);
+ this.removeEventListener("click", this._onclick);
+ this.removeEventListener("dblclick", this._ondblclick);
+ this.removeEventListener("keydown", this._onkeydown);
+
+ return qx.ui.basic.Terminator.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/HtmlEmbed.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/HtmlEmbed.js
new file mode 100644
index 0000000000..0649c69499
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/HtmlEmbed.js
@@ -0,0 +1,112 @@
+/* ************************************************************************
+
+ 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.HtmlEmbed", qx.ui.basic.Terminator,
+function(vHtml)
+{
+ qx.ui.basic.Terminator.call(this);
+
+ if (qx.util.Validation.isValidString(vHtml)) {
+ this.setHtml(vHtml);
+ }
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Any text string which can contain HTML, too
+*/
+qx.OO.addProperty({ name : "html", 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 });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyHtml = function()
+{
+ if (this._isCreated) {
+ this._syncHtml();
+ }
+
+ 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;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ELEMENT HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._applyElementData = function() {
+ this._syncHtml();
+}
+
+qx.Proto._syncHtml = function() {
+ this.getElement().innerHTML = this.getHtml();
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/IconHtmlEmbed.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/IconHtmlEmbed.js
new file mode 100644
index 0000000000..08e9aa9e8b
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/embed/IconHtmlEmbed.js
@@ -0,0 +1,134 @@
+/* ************************************************************************
+
+ 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.IconHtmlEmbed", qx.ui.embed.HtmlEmbed,
+function(vHtml, vIcon, vIconWidth, vIconHeight)
+{
+ qx.ui.embed.HtmlEmbed.call(this, vHtml);
+
+ if (typeof vIcon != "undefined")
+ {
+ this.setIcon(vIcon);
+
+ if (typeof vIconWidth != "undefined") {
+ this.setIconWidth(vIconWidth);
+ }
+
+ if (typeof vIconHeight != "undefined") {
+ this.setIconHeight(vIconWidth);
+ }
+ }
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Any URI String supported by qx.ui.basic.Image to display a icon
+*/
+qx.OO.addProperty({ name : "icon", type : "string", impl : "html" });
+
+/*!
+ The width of the icon.
+ If configured, this makes qx.ui.embed.IconHtmlEmbed a little bit faster as it does not need to wait until the image loading is finished.
+*/
+qx.OO.addProperty({ name : "iconWidth", type : "number", impl : "html" });
+
+/*!
+ The height of the icon
+ If configured, this makes qx.ui.embed.IconHtmlEmbed a little bit faster as it does not need to wait until the image loading is finished.
+*/
+qx.OO.addProperty({ name : "iconHeight", type : "number", impl : "html" });
+
+/*!
+ Space in pixels between the icon and the HTML.
+*/
+qx.OO.addProperty({ name : "spacing", type : "number", defaultValue : 4, impl : "html" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._mshtml = qx.sys.Client.getInstance().isMshtml();
+
+qx.Proto._syncHtml = function()
+{
+ var vHtml = [];
+
+ if (qx.util.Validation.isValidString(this.getIcon()))
+ {
+ vHtml.push("<img src=\"");
+ vHtml.push(qx.manager.object.AliasManager.getInstance().resolvePath(this._mshtml ? "static/image/blank.gif" : this.getIcon()));
+ vHtml.push("\" style=\"vertical-align:middle;");
+
+ if (qx.util.Validation.isValidNumber(this.getSpacing()))
+ {
+ vHtml.push("margin-right:");
+ vHtml.push(this.getSpacing());
+ vHtml.push("px;");
+ }
+
+ if (qx.util.Validation.isValidNumber(this.getIconWidth()))
+ {
+ vHtml.push("width:");
+ vHtml.push(this.getIconWidth());
+ vHtml.push("px;");
+ }
+
+ if (qx.util.Validation.isValidNumber(this.getIconHeight()))
+ {
+ vHtml.push("height:");
+ vHtml.push(this.getIconHeight());
+ vHtml.push("px;");
+ }
+
+ if (this._mshtml)
+ {
+ vHtml.push("filter:");
+ vHtml.push("progid:DXImageTransform.Microsoft.AlphaImageLoader(src='");
+ vHtml.push(qx.manager.object.AliasManager.getInstance().resolvePath(this.getIcon()));
+ vHtml.push("',sizingMethod='scale')");
+ vHtml.push(";");
+ }
+
+ vHtml.push("\"/>");
+ }
+
+ 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('<iframe name="' + vFrameName + '"></iframe>');
+ } 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 = "<a target='";
+qx.ui.embed.LinkEmbed.HREF_START = "' href='";
+qx.ui.embed.LinkEmbed.HREF_STOP = "'>";
+qx.ui.embed.LinkEmbed.LINK_STOP = "</a>";
+
+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:
+ * <ul>
+ * <li>Editable text field</li>
+ * <li>Complete key-navigation</li>
+ * <li>Images inside the list</li>
+ * <li>Images and text inside the list</li>
+ * </ul>
+ *
+ * @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 <ENTER>
+ case "Enter":
+ if (vVisible)
+ {
+ this.setSelected(this._manager.getSelectedItem());
+ this._closePopup();
+ this.setFocused(true);
+ }
+ else
+ {
+ this._openPopup();
+ }
+
+ return;
+
+ // Handle <ESC>
+ 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 <PAGEUP>
+ 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 <PAGEDOWN>
+ 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.
+ *
+ * <p>Features:</p>
+ * <ul>
+ * <li>Editable text field</li>
+ * <li>Complete key-navigation</li>
+ * <li>Mouse wheel navigation</li>
+ * <li>Multicolumn display in list</li>
+ * <li>If more than one column, headers are automatically shown</li>
+ * <li>Can show the ID and/or description of each list item</li>
+ * <li>Automatically calculating needed width</li>
+ * <li>Popup list always shows full contents, and can be wider than text field</li>
+ * <li>Search values through popup dialog</li>
+ * <li>Internationalization support of messages (through custom settings)</li>
+ * </ul>
+ * <p>Pending features:</p>
+ * <ul>
+ * <li>Images inside the list</li>
+ * <li>Autocomplete on key input</li>
+ * </ul>
+ *
+ * @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:<ul>.
+ * <li>Column 0 represents the ID, i.e. the value that is stored internally and used by the app.</li>
+ * <li>Column 1 represents the description, the text that the end user normally sees.</li>
+ * <li>Columns > 1 will also be shown in the popup list, it you have set the appropiate column headers with {@link #setColumnHeaders}.</li>
+ * </ul>*/
+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 <ENTER>
+ if (e.getKeyIdentifier() == "Enter" && !e.getAltKey())
+ {
+ var items = this.getSelectedItems();
+ var currentItem;
+
+ for (var i=0; i<items.length; i++) {
+ items[i].createDispatchEvent("action");
+ }
+ }
+};
+
+
+qx.Proto._onkeypress = function(e)
+{
+ // Give control to selectionManager
+ this._manager.handleKeyPress(e);
+};
+
+
+qx.Proto._lastKeyPress = 0;
+
+qx.Proto._onkeyinput = function(e)
+{
+ if (!this.getEnableInlineFind()) {
+ return;
+ }
+
+ // Reset string after a second of non pressed key
+ if (((new Date).valueOf() - this._lastKeyPress) > 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<vAllItems.length; i++) {
+ if (vAllItems[i][methodName](vUserValue)) {
+ return vAllItems[i];
+ }
+ }
+
+ // Mode #2: Find all items before the startIndex
+ for (var i=0; i<vStartIndex; i++) {
+ if (vAllItems[i][methodName](vUserValue)) {
+ return vAllItems[i];
+ }
+ }
+
+ return null;
+}
+
+qx.Proto.findString = function(vText, vStartIndex) {
+ return this._findItem(vText, vStartIndex || 0, "String");
+}
+
+qx.Proto.findStringExact = function(vText, vStartIndex) {
+ return this._findItem(vText, vStartIndex || 0, "StringExact");
+}
+
+qx.Proto.findValue = function(vText, vStartIndex) {
+ return this._findItem(vText, vStartIndex || 0, "Value");
+}
+
+qx.Proto.findValueExact = function(vText, vStartIndex) {
+ return this._findItem(vText, vStartIndex || 0, "ValueExact");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ SORT SUPPORT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._sortItemsCompare = function(a, b) {
+ return a.key < b.key ? -1 : a.key == b.key ? 0 : 1;
+}
+
+qx.Proto.sortItemsByString = function(vReverse)
+{
+ var sortitems = [];
+ var items = this.getChildren();
+
+ for(var i=0, l=items.length; i<l; i++) {
+ sortitems[i] = { key : items[i].getLabel(), item : items[i] }
+ }
+
+ sortitems.sort(this._sortItemsCompare);
+ if (vReverse) {
+ sortitems.reverse();
+ }
+
+ for(var i=0; i<l; i++) {
+ this.addAt(sortitems[i].item, i);
+ }
+}
+
+qx.Proto.sortItemsByValue = function(vReverse)
+{
+ var sortitems = [];
+ var items = this.getChildren();
+
+ for(var i=0, l=items.length; i<l; i++) {
+ sortitems[i] = { key : items[i].getValue(), item : items[i] }
+ }
+
+ sortitems.sort(this._sortItemsCompare);
+ if (vReverse) {
+ sortitems.reverse();
+ }
+
+ for(var i=0; i<l; i++) {
+ this.addAt(sortitems[i].item, i);
+ }
+}
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (this._manager)
+ {
+ this._manager.dispose();
+ this._manager = null;
+ }
+
+ 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);
+ this.removeEventListener("keydown", this._onkeydown);
+ this.removeEventListener("keypress", this._onkeypress);
+ this.removeEventListener("keyinput", this._onkeyinput);
+
+ return qx.ui.layout.VerticalBoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ListItem.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ListItem.js
new file mode 100644
index 0000000000..2499bc5823
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/ListItem.js
@@ -0,0 +1,115 @@
+/* ************************************************************************
+
+ 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)
+
+************************************************************************ */
+
+/**
+ * @event action {qx.event.type.Event} (Fired by {@link qx.ui.form.List})
+ */
+qx.OO.defineClass("qx.ui.form.ListItem", qx.ui.basic.Atom,
+function(vText, vIcon, vValue)
+{
+ qx.ui.basic.Atom.call(this, vText, vIcon);
+
+ if (qx.util.Validation.isValid(vValue)) {
+ this.setValue(vValue);
+ }
+
+
+ // ************************************************************************
+ // EVENT LISTENER
+ // ************************************************************************
+ this.addEventListener("dblclick", this._ondblclick);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "list-item" });
+qx.OO.addProperty({ name : "value" });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ STATE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.handleStateChange = function()
+{
+ if (this.hasState("lead"))
+ {
+ this.setStyleProperty("MozOutline", "1px dotted invert");
+ this.setStyleProperty("outline", "1px dotted invert");
+ }
+ else
+ {
+ this.removeStyleProperty("MozOutline");
+ this.setStyleProperty("outline", "0px none");
+ }
+}
+
+// Remove default outline focus border
+qx.Proto._applyStateStyleFocus = function(vStates) {};
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.matchesString = function(vText) {
+ return vText != "" && this.getLabel().toLowerCase().indexOf(vText.toLowerCase()) == 0;
+}
+
+qx.Proto.matchesStringExact = function(vText) {
+ return vText != "" && this.getLabel().toLowerCase() == String(vText).toLowerCase();
+}
+
+qx.Proto.matchesValue = function(vText) {
+ return vText != "" && this.getValue().toLowerCase().indexOf(vText.toLowerCase()) == 0;
+}
+
+qx.Proto.matchesValueExact = function(vText) {
+ return vText != "" && this.getValue().toLowerCase() == String(vText).toLowerCase();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._ondblclick = function(e)
+{
+ var vCommand = this.getCommand();
+ if (vCommand) {
+ vCommand.execute();
+ }
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/PasswordField.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/PasswordField.js
new file mode 100644
index 0000000000..17e0894a76
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/PasswordField.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_form)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.form.PasswordField", qx.ui.form.TextField,
+function(vText)
+{
+ qx.ui.form.TextField.call(this, vText);
+
+ this.setHtmlProperty("type", "password");
+});
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/RadioButton.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/RadioButton.js
new file mode 100644
index 0000000000..97486822c1
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/RadioButton.js
@@ -0,0 +1,185 @@
+/* ************************************************************************
+
+ 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.RadioButton", qx.ui.form.CheckBox,
+function(vText, vValue, vName, vChecked) {
+ qx.ui.form.CheckBox.call(this, vText, vValue, vName, vChecked);
+
+ this.addEventListener("keypress", this._onkeypress);
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ 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 });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ICON HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.INPUT_TYPE = "radio";
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyChecked = function(propValue, propOldValue, propData)
+{
+ if (this._iconObject) {
+ this._iconObject.setChecked(propValue);
+ }
+
+ var vManager = this.getManager();
+ if (vManager) {
+ vManager.handleItemChecked(this, propValue);
+ }
+
+ 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._iconObject) {
+ this._iconObject.setName(propValue);
+ }
+
+ if (this.getManager()) {
+ this.getManager().setName(propValue);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyValue = function(propValue, propOldValue, propData)
+{
+ if (this.isCreated() && this._iconObject) {
+ this._iconObject.setValue(propValue);
+ }
+
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT-HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeydown = function(e)
+{
+ if (e.getKeyIdentifier() == "Enter" && !e.getAltKey()) {
+ this.setChecked(true);
+ }
+};
+
+
+qx.Proto._onkeypress = function(e)
+{
+ switch(e.getKeyIdentifier())
+ {
+ case "Left":
+ case "Up":
+ qx.event.handler.FocusHandler.mouseFocus = false;
+ // we want to have a focus border when using arrows to select
+ qx.event.handler.FocusHandler.mouseFocus = false;
+
+ return this.getManager() ? this.getManager().selectPrevious(this) : true;
+
+ case "Right":
+ case "Down":
+ // we want to have a focus border when using arrows to select
+ qx.event.handler.FocusHandler.mouseFocus = false;
+
+ return this.getManager() ? this.getManager().selectNext(this) : true;
+ }
+};
+
+
+qx.Proto._onclick = function(e) {
+ this.setChecked(true);
+}
+
+qx.Proto._onkeyup = function(e)
+{
+ if(e.getKeyIdentifier() == "Space") {
+ this.setChecked(true);
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if(this.getDisposed()) {
+ return;
+ }
+
+ this.removeEventListener("keypress", this._onkeypress);
+ return qx.ui.form.CheckBox.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/RepeatButton.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/RepeatButton.js
new file mode 100755
index 0000000000..df04fdd3ba
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/RepeatButton.js
@@ -0,0 +1,127 @@
+/* ************************************************************************
+
+ 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)
+
+************************************************************************ */
+
+/**
+ * @event execute {qx.event.type.Event}
+ */
+qx.OO.defineClass("qx.ui.form.RepeatButton", qx.ui.form.Button,
+function(vText, vIcon, vIconWidth, vIconHeight, vFlash)
+{
+ qx.ui.form.Button.call(this, vText, vIcon, vIconWidth, vIconHeight, vFlash);
+
+ this._timer = new qx.client.Timer;
+ this._timer.setInterval(this.getInterval());
+ this._timer.addEventListener("interval", this._oninterval, this);
+});
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "interval", type : "number", defaultValue : 100 });
+qx.OO.addProperty({ name : "firstInterval", type : "number", defaultValue : 500 });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousedown = function(e)
+{
+ if (e.getTarget() != this || !e.isLeftButtonPressed()) {
+ return;
+ }
+
+ this._executed = false;
+
+ this._timer.setInterval(this.getFirstInterval());
+ this._timer.start();
+
+ this.removeState("abandoned");
+ this.addState("pressed");
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ this.setCapture(false);
+
+ if (!this.hasState("abandoned"))
+ {
+ this.addState("over");
+
+ if (this.hasState("pressed") && !this._executed) {
+ this.execute();
+ }
+ }
+
+ this._timer.stop();
+
+ this.removeState("abandoned");
+ this.removeState("pressed");
+}
+
+qx.Proto._oninterval = function(e)
+{
+ this._timer.stop();
+ this._timer.setInterval(this.getInterval());
+ this._timer.start();
+
+ this._executed = true;
+ this.createDispatchEvent("execute");
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._timer)
+ {
+ this._timer.stop();
+ this._timer.dispose();
+ this._timer = null;
+ }
+
+ return qx.ui.form.Button.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/Spinner.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/Spinner.js
new file mode 100644
index 0000000000..f2eeab0e5d
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form/Spinner.js
@@ -0,0 +1,683 @@
+/* ************************************************************************
+
+ 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)
+
+************************************************************************ */
+
+/**
+ * @event change {qx.event.type.Event}
+ */
+qx.OO.defineClass("qx.ui.form.Spinner", qx.ui.layout.HorizontalBoxLayout,
+function(vMin, vValue, vMax)
+{
+ qx.ui.layout.HorizontalBoxLayout.call(this);
+
+ // ************************************************************************
+ // BEHAVIOR
+ // ************************************************************************
+ this.setTabIndex(-1);
+
+ if (qx.sys.Client.getInstance().isMshtml()) {
+ this.setStyleProperty("fontSize", "0px");
+ }
+
+
+ // ************************************************************************
+ // MANAGER
+ // ************************************************************************
+ this._manager = new qx.type.Range();
+
+
+ // ************************************************************************
+ // TEXTFIELD
+ // ************************************************************************
+ this._textfield = new qx.ui.form.TextField;
+ this._textfield.setAppearance("spinner-field");
+ this._textfield.setValue(String(this._manager.getValue()));
+
+ this.add(this._textfield);
+
+
+ // ************************************************************************
+ // BUTTON LAYOUT
+ // ************************************************************************
+ this._buttonlayout = new qx.ui.layout.VerticalBoxLayout;
+ this._buttonlayout.setWidth("auto");
+ this.add(this._buttonlayout);
+
+
+ // ************************************************************************
+ // UP-BUTTON
+ // ************************************************************************
+ this._upbutton = new qx.ui.basic.Image("widget/arrows/up_small.gif");
+ this._upbutton.setAppearance("spinner-button-up");
+ this._buttonlayout.add(this._upbutton);
+
+
+ // ************************************************************************
+ // DOWN-BUTTON
+ // ************************************************************************
+ this._downbutton = new qx.ui.basic.Image("widget/arrows/down_small.gif");
+ this._downbutton.setAppearance("spinner-button-down");
+ this._buttonlayout.add(this._downbutton);
+
+
+ // ************************************************************************
+ // TIMER
+ // ************************************************************************
+ this._timer = new qx.client.Timer(this.getInterval());
+
+
+ // ************************************************************************
+ // EVENTS
+ // ************************************************************************
+ this.addEventListener("keypress", this._onkeypress, this);
+ this.addEventListener("keydown", this._onkeydown, this);
+ this.addEventListener("keyup", this._onkeyup, this);
+ this.addEventListener("mousewheel", this._onmousewheel, this);
+
+ this._textfield.addEventListener("input", this._oninput, this);
+ this._textfield.addEventListener("blur", this._onblur, this);
+ this._upbutton.addEventListener("mousedown", this._onmousedown, this);
+ this._downbutton.addEventListener("mousedown", this._onmousedown, this);
+ this._manager.addEventListener("change", this._onchange, this);
+ this._timer.addEventListener("interval", this._oninterval, this);
+
+
+ // ************************************************************************
+ // INITIALIZATION
+ // ************************************************************************
+
+ if(qx.util.Validation.isValidNumber(vMin)) {
+ this.setMin(vMin);
+ }
+
+ if(qx.util.Validation.isValidNumber(vMax)) {
+ this.setMax(vMax);
+ }
+
+ if(qx.util.Validation.isValidNumber(vValue)) {
+ this.setValue(vValue);
+ }
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "spinner" });
+
+/*!
+ The amount to increment on each event (keypress or mousedown).
+*/
+qx.OO.addProperty({ name : "incrementAmount", type : "number", defaultValue : 1 });
+
+/*!
+ The amount to increment on each event (keypress or mousedown).
+*/
+qx.OO.addProperty({ name : "wheelIncrementAmount", type : "number", defaultValue : 1 });
+
+/*!
+ The amount to increment on each pageup / pagedown keypress
+*/
+qx.OO.addProperty({ name : "pageIncrementAmount", type : "number", defaultValue : 10 });
+
+/*!
+ The current value of the interval (this should be used internally only).
+*/
+qx.OO.addProperty({ name : "interval", type : "number", defaultValue : 100 });
+
+/*!
+ The first interval on event based shrink/growth of the value.
+*/
+qx.OO.addProperty({ name : "firstInterval", type : "number", defaultValue : 500 });
+
+/*!
+ This configures the minimum value for the timer interval.
+*/
+qx.OO.addProperty({ name : "minTimer", type : "number", defaultValue : 20 });
+
+/*!
+ Decrease of the timer on each interval (for the next interval) until minTimer reached.
+*/
+qx.OO.addProperty({ name : "timerDecrease", type : "number", defaultValue : 2 });
+
+/*!
+ If minTimer was reached, how much the amount of each interval should growth (in relation to the previous interval).
+*/
+qx.OO.addProperty({ name : "amountGrowth", type : "number", defaultValue : 1.01 });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PREFERRED DIMENSIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computePreferredInnerWidth = function() {
+ return 50;
+}
+
+qx.Proto._computePreferredInnerHeight = function() {
+ return 14;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ KEY EVENT-HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeypress = function(e)
+{
+ var vIdentifier = e.getKeyIdentifier();
+
+ if (vIdentifier == "Enter" && !e.getAltKey())
+ {
+ this._checkValue(true, false, false);
+ this._textfield.selectAll();
+ }
+ else
+ {
+ switch (vIdentifier)
+ {
+ case "Up":
+ case "Down":
+
+ case "Left":
+ case "Right":
+
+ case "Shift":
+ case "Control":
+ case "Alt":
+
+ case "Escape":
+ case "Delete":
+ case "Backspace":
+
+ case "Insert":
+
+ case "Home":
+ case "End":
+
+ case "PageUp":
+ case "PageDown":
+
+ case "NumLock":
+ case "Tab":
+ break;
+
+ default:
+ if (vIdentifier >= "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<vStart)
+ {
+ // find next line break
+ i = vText.indexOf("\r\n", i);
+
+ if (i == -1) {
+ break;
+ }
+
+ vStart--;
+ i++;
+ }
+
+ var vRange = this._getRange();
+
+ vRange.collapse();
+ vRange.move("character", vStart);
+ vRange.select();
+ }
+
+ qx.Proto.getSelectionStart = function()
+ {
+ this._visualPropertyCheck();
+
+ var vSelectionRange = this._getSelectionRange();
+
+ if (!this.getElement().contains(vSelectionRange.parentElement())) {
+ return -1;
+ }
+
+ var vRange = this._getRange();
+
+ vRange.setEndPoint("EndToStart", vSelectionRange);
+ return vRange.text.length;
+ }
+
+ qx.Proto.setSelectionLength = function(vLength)
+ {
+ this._visualPropertyCheck();
+
+ var vSelectionRange = this._getSelectionRange();
+
+ if (!this.getElement().contains(vSelectionRange.parentElement())) {
+ return;
+ }
+
+ vSelectionRange.collapse();
+ vSelectionRange.moveEnd("character", vLength);
+ vSelectionRange.select();
+ }
+
+ qx.Proto.getSelectionLength = function()
+ {
+ this._visualPropertyCheck();
+
+ var vSelectionRange = this._getSelectionRange();
+
+ if (!this.getElement().contains(vSelectionRange.parentElement())) {
+ return 0;
+ }
+
+ return vSelectionRange.text.length;
+ }
+
+ qx.Proto.setSelectionText = function(vText)
+ {
+ this._visualPropertyCheck();
+
+ var vStart = this.getSelectionStart();
+ var vSelectionRange = this._getSelectionRange();
+
+ if (!this.getElement().contains(vSelectionRange.parentElement())) {
+ return;
+ }
+
+ vSelectionRange.text = vText;
+
+ // apply text to internal storage
+ this.setValue(this.getElement().value);
+
+ // recover selection (to behave the same gecko does)
+ this.setSelectionStart(vStart);
+ this.setSelectionLength(vText.length);
+
+ return true;
+ }
+
+ qx.Proto.getSelectionText = function()
+ {
+ this._visualPropertyCheck();
+
+ var vSelectionRange = this._getSelectionRange();
+
+ if (!this.getElement().contains(vSelectionRange.parentElement())) {
+ return "";
+ }
+
+ return vSelectionRange.text;
+ }
+
+ qx.Proto.selectAll = function()
+ {
+ this._visualPropertyCheck();
+
+ if (this.getValue() != null)
+ {
+ this.setSelectionStart(0);
+ this.setSelectionLength(this.getValue().length);
+ }
+
+ // to be sure we get the element selected
+ this.getElement().select();
+ }
+
+ qx.Proto.selectFromTo = function(vStart, vEnd)
+ {
+ this._visualPropertyCheck();
+
+ this.setSelectionStart(vStart);
+ this.setSelectionLength(vEnd-vStart);
+ }
+}
+else
+{
+ qx.Proto.setSelectionStart = function(vStart)
+ {
+ this._visualPropertyCheck();
+ this.getElement().selectionStart = vStart;
+ }
+
+ qx.Proto.getSelectionStart = function()
+ {
+ this._visualPropertyCheck();
+ return this.getElement().selectionStart;
+ }
+
+ qx.Proto.setSelectionLength = function(vLength)
+ {
+ this._visualPropertyCheck();
+
+ var el = this.getElement();
+ if (qx.util.Validation.isValidString(el.value)) {
+ el.selectionEnd = el.selectionStart + vLength;
+ }
+ }
+
+ qx.Proto.getSelectionLength = function()
+ {
+ this._visualPropertyCheck();
+
+ var el = this.getElement();
+ return el.selectionEnd - el.selectionStart;
+ }
+
+ qx.Proto.setSelectionText = function(vText)
+ {
+ this._visualPropertyCheck();
+
+ var el = this.getElement();
+
+ var vOldText = el.value;
+ var vStart = el.selectionStart;
+
+ var vOldTextBefore = vOldText.substr(0, vStart);
+ var vOldTextAfter = vOldText.substr(el.selectionEnd);
+
+ var vValue = el.value = vOldTextBefore + vText + vOldTextAfter;
+
+ // recover selection
+ el.selectionStart = vStart;
+ el.selectionEnd = vStart + vText.length;
+
+ // apply new value to internal cache
+ this.setValue(vValue);
+
+ return true;
+ }
+
+ qx.Proto.getSelectionText = function()
+ {
+ this._visualPropertyCheck();
+
+ return this.getElement().value.substr(this.getSelectionStart(), this.getSelectionLength());
+ }
+
+ qx.Proto.selectAll = function()
+ {
+ this._visualPropertyCheck();
+
+ this.getElement().select();
+ }
+
+ qx.Proto.selectFromTo = function(vStart, vEnd)
+ {
+ this._visualPropertyCheck();
+
+ var el = this.getElement();
+ el.selectionStart = vStart;
+ el.selectionEnd = vEnd;
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this.removeEventListener("blur", this._onblur);
+ this.removeEventListener("focus", this._onfocus);
+
+ qx.ui.basic.Terminator.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/CheckGroupBox.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/CheckGroupBox.js
new file mode 100644
index 0000000000..9dcca10179
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/CheckGroupBox.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_form)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.groupbox.CheckGroupBox", qx.ui.groupbox.GroupBox,
+function(vLegend) {
+ qx.ui.groupbox.GroupBox.call(this, vLegend);
+});
+
+qx.Proto._createLegendObject = function()
+{
+ this._legendObject = new qx.ui.form.CheckBox;
+ this._legendObject.setAppearance("check-box-field-set-legend");
+ this._legendObject.setChecked(true);
+
+ this.add(this._legendObject);
+}
+
+qx.Proto.setIcon = qx.Proto.getIcon = null;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/GroupBox.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/GroupBox.js
new file mode 100644
index 0000000000..2457c3bdd0
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/GroupBox.js
@@ -0,0 +1,156 @@
+/* ************************************************************************
+
+ 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.groupbox.GroupBox", qx.ui.layout.CanvasLayout,
+function(vLegend, vIcon)
+{
+ qx.ui.layout.CanvasLayout.call(this);
+
+
+ // ************************************************************************
+ // SUB WIDGETS
+ // ************************************************************************
+ this._createFrameObject();
+ this._createLegendObject();
+
+
+ // ************************************************************************
+ // INIT
+ // ************************************************************************
+ this.setLegend(vLegend);
+
+ if (qx.util.Validation.isValidString(vIcon)) {
+ this.setIcon(vIcon);
+ }
+
+
+ // ************************************************************************
+ // REMAPPING
+ // ************************************************************************
+ this.remapChildrenHandlingTo(this._frameObject);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "field-set" });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ SUB WIDGET CREATION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._createLegendObject = function()
+{
+ this._legendObject = new qx.ui.basic.Atom;
+ this._legendObject.setAppearance("field-set-legend");
+
+ this.add(this._legendObject);
+}
+
+qx.Proto._createFrameObject = function()
+{
+ this._frameObject = new qx.ui.layout.CanvasLayout;
+ this._frameObject.setAppearance("field-set-frame");
+
+ this.add(this._frameObject);
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ GETTER FOR SUB WIDGETS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getFrameObject = function() {
+ return this._frameObject;
+}
+
+qx.Proto.getLegendObject = function() {
+ return this._legendObject;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ SETTER/GETTER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.setLegend = function(vLegend) {
+ this._legendObject.setLabel(vLegend);
+}
+
+qx.Proto.getLegend = function() {
+ return this._legendObject.getLabel();
+}
+
+qx.Proto.setIcon = function(vIcon) {
+ this._legendObject.setIcon(vIcon);
+}
+
+qx.Proto.getIcon = function() {
+ this._legendObject.getIcon();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return true;
+ }
+
+ if (this._legendObject)
+ {
+ this._legendObject.dispose();
+ this._legendObject = null;
+ }
+
+ if (this._frameObject)
+ {
+ this._frameObject.dispose();
+ this._frameObject = 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/groupbox/RadioGroupBox.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/RadioGroupBox.js
new file mode 100644
index 0000000000..bcb230e6b7
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/groupbox/RadioGroupBox.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_form)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.groupbox.RadioGroupBox", qx.ui.groupbox.GroupBox,
+function(vLegend) {
+ qx.ui.groupbox.GroupBox.call(this, vLegend);
+});
+
+qx.Proto._createLegendObject = function()
+{
+ this._legendObject = new qx.ui.form.RadioButton;
+ this._legendObject.setAppearance("radio-button-field-set-legend");
+ this._legendObject.setChecked(true);
+
+ this.add(this._legendObject);
+}
+
+qx.Proto.setIcon = qx.Proto.getIcon = null;
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/BoxLayout.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/BoxLayout.js
new file mode 100644
index 0000000000..c31e9c796c
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/BoxLayout.js
@@ -0,0 +1,273 @@
+/* ************************************************************************
+
+ 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.BoxLayout", qx.ui.core.Parent,
+function(vOrientation)
+{
+ qx.ui.core.Parent.call(this);
+
+ // apply orientation
+ if (qx.util.Validation.isValidString(vOrientation)) {
+ this.setOrientation(vOrientation);
+ }
+});
+
+qx.ui.layout.BoxLayout.STR_REVERSED = "-reversed";
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ The orientation of the layout control. Allowed values are "horizontal" (default) and "vertical".
+*/
+qx.OO.addProperty({ name : "orientation", type : "string", possibleValues : [ "horizontal", "vertical" ], addToQueueRuntime : true });
+
+/*!
+ The spacing between childrens. Could be any positive integer value.
+*/
+qx.OO.addProperty({ name : "spacing", type : "number", defaultValue : 0, addToQueueRuntime : true, impl : "layout" });
+
+/*!
+ The horizontal align of the children. Allowed values are: "left", "center" and "right"
+*/
+qx.OO.addProperty({ name : "horizontalChildrenAlign", type : "string", defaultValue : "left", possibleValues : [ "left", "center", "right" ], impl : "layoutOrder", addToQueueRuntime : true });
+
+/*!
+ The vertical align of the children. Allowed values are: "top", "middle" and "bottom"
+*/
+qx.OO.addProperty({ name : "verticalChildrenAlign", type : "string", defaultValue : "top", possibleValues : [ "top", "middle", "bottom" ], impl : "layoutOrder", addToQueueRuntime : true });
+
+/*!
+ Should the children be layouted in reverse order?
+*/
+qx.OO.addProperty({ name : "reverseChildrenOrder", type : "boolean", defaultValue : false, impl : "layoutOrder", addToQueueRuntime : true });
+
+/*!
+ Should the widgets be stretched to the available width (orientation==vertical) or height (orientation==horizontal)?
+ This only applies if the child has not configured a own value for this axis.
+*/
+qx.OO.addProperty({ name : "stretchChildrenOrthogonalAxis", type : "boolean", defaultValue : true, addToQueueRuntime : true });
+
+/*!
+ If there are min/max values in combination with flex try to optimize placement.
+ This is more complex and produces more time for the layouter but sometimes this feature is needed.
+*/
+qx.OO.addProperty({ name : "useAdvancedFlexAllocation", type : "boolean", defaultValue : false, addToQueueRuntime : true });
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INIT LAYOUT IMPL
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This creates an new instance of the layout impl this widget uses
+*/
+qx.Proto._createLayoutImpl = function() {
+ return this.getOrientation() == "vertical" ? new qx.renderer.layout.VerticalBoxLayoutImpl(this) : new qx.renderer.layout.HorizontalBoxLayoutImpl(this);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ HELPERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._layoutHorizontal = false;
+qx.Proto._layoutVertical = false;
+qx.Proto._layoutMode = "left";
+
+qx.Proto.isHorizontal = function() {
+ return this._layoutHorizontal;
+}
+
+qx.Proto.isVertical = function() {
+ return this._layoutVertical;
+}
+
+qx.Proto.getLayoutMode = function()
+{
+ if (this._layoutMode == null) {
+ this._updateLayoutMode();
+ }
+
+ return this._layoutMode;
+}
+
+qx.Proto._updateLayoutMode = function()
+{
+ this._layoutMode = this._layoutVertical ? this.getVerticalChildrenAlign() : this.getHorizontalChildrenAlign();
+
+ if (this.getReverseChildrenOrder()) {
+ this._layoutMode += qx.ui.layout.BoxLayout.STR_REVERSED;
+ }
+}
+
+qx.Proto._invalidateLayoutMode = function() {
+ this._layoutMode = null;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyOrientation = function(propValue, propOldValue, propData)
+{
+ // update fast access variables
+ this._layoutHorizontal = propValue == "horizontal";
+ this._layoutVertical = propValue == "vertical";
+
+ // Layout Implementation
+ if (this._layoutImpl)
+ {
+ this._layoutImpl.dispose();
+ this._layoutImpl = null;
+ }
+
+ if (qx.util.Validation.isValidString(propValue)) {
+ this._layoutImpl = this._createLayoutImpl();
+ }
+
+ // call other core modifier
+ return this._modifyLayoutOrder(propValue, propOldValue, propData);
+}
+
+qx.Proto._modifyLayoutOrder = function(propValue, propOldValue, propData)
+{
+ // update layout mode
+ this._invalidateLayoutMode();
+
+ // call other core modifier
+ return this._modifyLayout(propValue, propOldValue, propData);
+}
+
+qx.Proto._modifyLayout = function(propValue, propOldValue, propData)
+{
+ // invalidate inner preferred dimensions
+ this._invalidatePreferredInnerDimensions();
+
+ // accumulated width needs to be invalidated
+ this._invalidateAccumulatedChildrenOuterWidth();
+ this._invalidateAccumulatedChildrenOuterHeight();
+
+ // make property handling happy :)
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ACCUMULATED CHILDREN WIDTH/HEIGHT
+--------------------------------------------------------------------------------
+
+ Needed for center/middle and right/bottom alignment
+
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addCachedProperty({ name : "accumulatedChildrenOuterWidth", defaultValue : null });
+qx.OO.addCachedProperty({ name : "accumulatedChildrenOuterHeight", defaultValue : null });
+
+qx.Proto._computeAccumulatedChildrenOuterWidth = function()
+{
+ var ch=this.getVisibleChildren(), chc, i=-1, sp=this.getSpacing(), s=-sp;
+
+ while(chc=ch[++i]) {
+ s += chc.getOuterWidth() + sp;
+ }
+
+ return s;
+}
+
+qx.Proto._computeAccumulatedChildrenOuterHeight = function()
+{
+ var ch=this.getVisibleChildren(), chc, i=-1, sp=this.getSpacing(), s=-sp;
+
+ while(chc=ch[++i]) {
+ s += chc.getOuterHeight() + sp;
+ }
+
+ return s;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ STRETCHING SUPPORT
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._recomputeChildrenStretchingX = function()
+{
+ var ch=this.getVisibleChildren(), chc, i=-1;
+
+ while(chc=ch[++i])
+ {
+ if (chc._recomputeStretchingX() && chc._recomputeBoxWidth()) {
+ chc._recomputeOuterWidth();
+ }
+ }
+}
+
+qx.Proto._recomputeChildrenStretchingY = function()
+{
+ var ch=this.getVisibleChildren(), chc, i=-1;
+
+ while(chc=ch[++i])
+ {
+ if (chc._recomputeStretchingY() && chc._recomputeBoxHeight()) {
+ chc._recomputeOuterHeight();
+ }
+ }
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/CanvasLayout.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/CanvasLayout.js
new file mode 100644
index 0000000000..977d6a8525
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/CanvasLayout.js
@@ -0,0 +1,45 @@
+/* ************************************************************************
+
+ 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.ui.layout.CanvasLayout", qx.ui.core.Parent,
+function() {
+ qx.ui.core.Parent.call(this);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INIT LAYOUT IMPL
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This creates an new instance of the layout impl this widget uses
+*/
+qx.Proto._createLayoutImpl = function() {
+ return new qx.renderer.layout.CanvasLayoutImpl(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/DockLayout.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/DockLayout.js
new file mode 100644
index 0000000000..7002036e5f
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/DockLayout.js
@@ -0,0 +1,116 @@
+/* ************************************************************************
+
+ 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.ui.layout.DockLayout", qx.ui.core.Parent,
+function() {
+ qx.ui.core.Parent.call(this);
+});
+
+/*!
+ The layout mode (in which order the children should be layouted)
+*/
+qx.OO.addProperty({ name : "mode", type : "string", defaultValue : "vertical", possibleValues : [ "vertical", "horizontal", "ordered" ], addToQueueRuntime : true });
+
+/*
+ Overwrite from qx.ui.core.Widget, we do not support 'auto' and 'flex'
+*/
+qx.OO.changeProperty({ name : "width", addToQueue : true, unitDetection : "pixelPercent" });
+qx.OO.changeProperty({ name : "minWidth", defaultValue : -Infinity, addToQueue : true, unitDetection : "pixelPercent" });
+qx.OO.changeProperty({ name : "minWidth", defaultValue : -Infinity, addToQueue : true, unitDetection : "pixelPercent" });
+qx.OO.changeProperty({ name : "height", addToQueue : true, unitDetection : "pixelPercent" });
+qx.OO.changeProperty({ name : "minHeight", defaultValue : -Infinity, addToQueue : true, unitDetection : "pixelPercent" });
+qx.OO.changeProperty({ name : "minHeight", defaultValue : -Infinity, addToQueue : true, unitDetection : "pixelPercent" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INIT LAYOUT IMPL
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This creates an new instance of the layout impl this widget uses
+*/
+qx.Proto._createLayoutImpl = function() {
+ return new qx.renderer.layout.DockLayoutImpl(this);
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ENHANCED CHILDREN FEATURES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Add multiple childrens and make them left aligned
+*/
+qx.Proto.addLeft = function() {
+ this._addAlignedHorizontal("left", arguments);
+}
+
+/*!
+ Add multiple childrens and make them right aligned
+*/
+qx.Proto.addRight = function() {
+ this._addAlignedHorizontal("right", arguments);
+}
+
+/*!
+ Add multiple childrens and make them top aligned
+*/
+qx.Proto.addTop = function() {
+ this._addAlignedVertical("top", arguments);
+}
+
+/*!
+ Add multiple childrens and make them bottom aligned
+*/
+qx.Proto.addBottom = function() {
+ this._addAlignedVertical("bottom", arguments);
+}
+
+qx.Proto._addAlignedVertical = function(vAlign, vArgs)
+{
+ for (var i=0, l=vArgs.length; i<l; i++) {
+ vArgs[i].setVerticalAlign(vAlign);
+ }
+
+ this.add.apply(this, vArgs);
+}
+
+qx.Proto._addAlignedHorizontal = function(vAlign, vArgs)
+{
+ for (var i=0, l=vArgs.length; i<l; i++) {
+ vArgs[i].setHorizontalAlign(vAlign);
+ }
+
+ this.add.apply(this, vArgs);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/FlowLayout.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/FlowLayout.js
new file mode 100644
index 0000000000..d2c1d934b8
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/FlowLayout.js
@@ -0,0 +1,106 @@
+/* ************************************************************************
+
+ 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.ui.layout.FlowLayout", qx.ui.core.Parent,
+function() {
+ qx.ui.core.Parent.call(this);
+});
+
+/*!
+ The spacing between childrens. Could be any positive integer value.
+*/
+qx.OO.addProperty({ name : "horizontalSpacing", type : "number", defaultValue : 0, addToQueueRuntime : true, impl : "layout" });
+
+/*!
+ The spacing between childrens. Could be any positive integer value.
+*/
+qx.OO.addProperty({ name : "verticalSpacing", type : "number", defaultValue : 0, addToQueueRuntime : true, impl : "layout" });
+
+/*!
+ The horizontal align of the children. Allowed values are: "left" and "right"
+*/
+qx.OO.addProperty({ name : "horizontalChildrenAlign", type : "string", defaultValue : "left", possibleValues : [ "left", "right" ], addToQueueRuntime : true });
+
+/*!
+ The vertical align of the children. Allowed values are: "top" and "bottom"
+*/
+qx.OO.addProperty({ name : "verticalChildrenAlign", type : "string", defaultValue : "top", possibleValues : [ "top", "bottom" ], addToQueueRuntime : true });
+
+/*!
+ Should the children be layouted in reverse order?
+*/
+qx.OO.addProperty({ name : "reverseChildrenOrder", type : "boolean", defaultValue : false, addToQueueRuntime : true, impl : "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.FlowLayoutImpl(this);
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DIMENSION CACHE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._changeInnerWidth = function(vNew, vOld)
+{
+ qx.ui.core.Parent.prototype._changeInnerWidth.call(this, vNew, vOld);
+
+ // allow 'auto' values for height to update when the inner width changes
+ this._invalidatePreferredInnerHeight();
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyLayout = function(propValue, propOldValue, propData)
+{
+ // invalidate inner preferred dimensions
+ this._invalidatePreferredInnerDimensions();
+
+ return true;
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/GridLayout.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/GridLayout.js
new file mode 100644
index 0000000000..d823c5b9d9
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/layout/GridLayout.js
@@ -0,0 +1,864 @@
+/* ************************************************************************
+
+ 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.ui.layout.GridLayout", qx.ui.core.Parent,
+function()
+{
+ qx.ui.core.Parent.call(this);
+
+ this._columnData = [];
+ this._rowData = [];
+
+ this._spans = [];
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ The spacing between childrens. Could be any positive integer value.
+*/
+qx.OO.addProperty({ name : "horizontalSpacing", type : "number", defaultValue : 0, addToQueueRuntime : true, impl : "layout" });
+
+/*!
+ The spacing between childrens. Could be any positive integer value.
+*/
+qx.OO.addProperty({ name : "verticalSpacing", type : "number", defaultValue : 0, addToQueueRuntime : true, impl : "layout" });
+
+/*!
+ The horizontal align of the children. Allowed values are: "left", "center" and "right"
+*/
+qx.OO.addProperty({ name : "horizontalChildrenAlign", type : "string", defaultValue : "left", possibleValues : [ "left", "center", "right" ], addToQueueRuntime : true });
+
+/*!
+ The vertical align of the children. Allowed values are: "top", "middle" and "bottom"
+*/
+qx.OO.addProperty({ name : "verticalChildrenAlign", type : "string", defaultValue : "top", possibleValues : [ "top", "middle", "bottom" ], addToQueueRuntime : true });
+
+/*!
+ Cell padding top of all cells, if not locally defined
+*/
+qx.OO.addProperty({ name : "cellPaddingTop", type : "number" });
+
+/*!
+ Cell padding right of all cells, if not locally defined
+*/
+qx.OO.addProperty({ name : "cellPaddingRight", type : "number" });
+
+/*!
+ Cell padding bottom of all cells, if not locally defined
+*/
+qx.OO.addProperty({ name : "cellPaddingBottom", type : "number" });
+
+/*!
+ Cell padding left of all cells, if not locally defined
+*/
+qx.OO.addProperty({ name : "cellPaddingLeft", type : "number" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ INIT LAYOUT IMPL
+---------------------------------------------------------------------------
+*/
+
+/*!
+ This creates an new instance of the layout impl this widget uses
+*/
+qx.Proto._createLayoutImpl = function() {
+ return new qx.renderer.layout.GridLayoutImpl(this);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ CORE FUNCTIONS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.add = function(vChild, vCol, vRow)
+{
+ vChild._col = vCol;
+ vChild._row = vRow;
+
+ if (this.isFillCell(vCol, vRow)) {
+ throw new Error("Could not insert child " + vChild + " into a fill cell: " + vCol + "x" + vRow);
+ }
+
+ qx.ui.core.Parent.prototype.add.call(this, vChild);
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyLayout = function(propValue, propOldValue, propData)
+{
+ // invalidate inner preferred dimensions
+ this._invalidatePreferredInnerDimensions();
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ GRID SETUP
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._syncDataFields = function(vData, vOldLength, vNewLength)
+{
+ if (vNewLength > vOldLength)
+ {
+ for (var i=vOldLength; i<vNewLength; i++) {
+ vData[i] = {};
+ }
+ }
+ else if (vOldLength > 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<l; i++) {
+ if (this._getColumnProperty(i, "widthType") == qx.ui.core.Widget.TYPE_PERCENT) {
+ this._setupColumnProperty(i, "widthComputed", null);
+ }
+ }
+
+ qx.ui.core.Parent.prototype._changeInnerWidth.call(this, vNew, vOld);
+}
+
+qx.Proto._changeInnerHeight = function(vNew, vOld)
+{
+ for (var i=0, l=this.getRowCount(); i<l; i++) {
+ if (this._getRowProperty(i, "heightType") == qx.ui.core.Widget.TYPE_PERCENT) {
+ this._setupRowProperty(i, "heightComputed", null);
+ }
+ }
+
+ qx.ui.core.Parent.prototype._changeInnerHeight.call(this, vNew, vOld);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DIMENSION CACHE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getInnerWidthForChild = function(vChild) {
+ return this._getColumnProperty(vChild._col, "widthComputed");
+}
+
+qx.Proto.getInnerHeightForChild = function(vChild) {
+ return this._getRowProperty(vChild._row, "heightComputed");
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ SPAN CELLS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.mergeCells = function(vStartCol, vStartRow, vColLength, vRowLength)
+{
+ var vSpans = this._spans;
+ var vLength = vSpans.length;
+
+ // Find end cols/rows
+ var vEndCol = vStartCol + vColLength - 1;
+ var vEndRow = vStartRow + vRowLength - 1;
+
+ if (this._collidesWithSpans(vStartCol, vStartRow, vEndCol, vEndRow))
+ {
+ this.debug("Span collision detected!");
+
+ // Send out warning
+ return false;
+ }
+
+ // Finally store new span entry
+ vSpans.push({ startCol : vStartCol, startRow : vStartRow, endCol : vEndCol, endRow : vEndRow, colLength : vColLength, rowLength : vRowLength });
+
+ // Send out ok
+ return true;
+}
+
+qx.Proto.hasSpans = function() {
+ return this._spans.length > 0;
+}
+
+qx.Proto.getSpanEntry = function(vCol, vRow)
+{
+ for (var i=0, s=this._spans, l=s.length, c; i<l; i++)
+ {
+ c = s[i];
+
+ if (vCol >= 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<l; i++)
+ {
+ c = s[i];
+
+ if (c.startCol == vCol && c.startRow == vRow) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+qx.Proto.isSpanCell = function(vCol, vRow)
+{
+ for (var i=0, s=this._spans, l=s.length, c; i<l; i++)
+ {
+ c = s[i];
+
+ if (vCol >= 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<l; i++)
+ {
+ c = s[i];
+
+ if (vCol >= 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<l; i++)
+ {
+ c = s[i];
+
+ if (vEndCol >= 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; i++, j=0)
+ {
+ for (var vCol in vColumns)
+ {
+ vCell = new vColumns[vCol].contentClass;
+
+ this.add(vCell, j++, i);
+
+ if (vColumns[vCol].align) {
+ vCell.setStyleProperty("textAlign",
+ vColumns[vCol].align);
+ }
+ }
+ }
+ }
+
+ // Sync cells: Remove existing ones and dispose them
+ else if (this._lastRowCount > 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<vRowCount; i++) {
+ this.setRowHeight(i, this._rowHeight);
+ }
+
+ if (!vUpdate)
+ {
+ // Apply width and alignment to all columns
+ var vCount = 0;
+ for (var vCol in vColumns)
+ {
+ this.setColumnHorizontalAlignment(vCount, vColumns[vCol].align);
+ this.setColumnWidth(vCount, vColumns[vCol].width);
+
+ vCount++;
+ }
+ }
+
+ // Store last row count
+ this._lastRowCount = vRowCount;
+}
+
+qx.Proto._currentScrollTop = -1;
+
+qx.Proto._updateRendering = function(vForce)
+{
+ if (this._updatingRendering) {
+ return;
+ }
+
+ var vScrollTop = (this._initialLayoutDone
+ ? this.getView().getScroll().getScrollTop()
+ : 0);
+
+ this._updatingRendering = true;
+ this._currentScrollTop = vScrollTop;
+
+ for (var i=0; i<this._rowCount; i++) {
+ this._updateRow(i);
+ }
+
+ delete this._updatingRendering;
+}
+
+qx.Proto._updateRow = function(vRelativeRow)
+{
+ var vData = this._data;
+ var vRowOffset = Math.floor(this._currentScrollTop / this._rowHeight);
+
+ var vColumnCount = this.getColumnCount();
+ var vColumns = this._columns;
+
+ var vChildren = this.getVisibleChildren();
+ var vChild, vEntry, vCol;
+
+ var j=0;
+
+ for (vCol in vColumns)
+ {
+ vEntry = vData[vRowOffset+vRelativeRow];
+ vChild = vChildren[vColumnCount*vRelativeRow+(j++)];
+
+ if (vChild)
+ {
+ if (vEntry && vEntry._selected) {
+ vChild.addState("selected");
+ } else {
+ vChild.removeState("selected");
+ }
+ vChild.set(vEntry
+ ? vEntry[vCol]
+ : vColumns[vCol].empty || vColumns[vCol].contentClass.empty);
+ }
+ }
+}
+
+qx.Proto._onscroll = function(e) {
+ this._updateRendering();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DIMENSION CACHE
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._changeInnerHeight = function(vNew, vOld)
+{
+ this._updateLayout(true);
+ this._updateRendering(true);
+
+ return qx.ui.layout.GridLayout.prototype._changeInnerHeight.call(this,
+ vNew,
+ vOld);
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MANAGER BINDING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getManager = function() {
+ return this._manager;
+}
+
+qx.Proto.getListViewTarget = function(e)
+{
+ var vEventTop = e.getPageY();
+ var vPaneTop = qx.dom.Location.getPageInnerTop(this.getElement());
+ var vItemNo = Math.floor(this._currentScrollTop / this._rowHeight) +
+ Math.floor((vEventTop - vPaneTop) / this._rowHeight);
+
+ return this._data[vItemNo];
+}
+
+qx.Proto.getSelectedItem = function() {
+ return this.getSelectedItems()[0];
+}
+
+qx.Proto.getSelectedItems = function() {
+ return this._manager.getSelectedItems();
+}
+
+qx.Proto.getData = function() {
+ return this._data;
+}
+
+// use static row height
+qx.Proto.getItemHeight = function(vItem) {
+ return this._rowHeight;
+}
+
+// use the full inner width of the pane
+qx.Proto.getItemWidth = function(vItem) {
+ return qx.dom.Dimension.getInnerWidth(this.getElement());
+}
+
+qx.Proto.getItemLeft = function(vItem) {
+ return 0;
+}
+
+qx.Proto.getItemTop = function(vItem) {
+ return this._data.indexOf(vItem) * this._rowHeight;
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MOUSE EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmousewheel = function(e)
+{
+ var vScroll = this.getView().getScroll();
+ vScroll.setScrollTop(vScroll.getScrollTop() - (e.getWheelDelta() * 20));
+}
+
+qx.Proto._onmouseover = function(e)
+{
+ var vTarget = this.getListViewTarget(e);
+ if (vTarget) {
+ this._manager.handleMouseOver(vTarget, e);
+ }
+}
+
+qx.Proto._onmousedown = function(e)
+{
+ var vTarget = this.getListViewTarget(e);
+ if (vTarget) {
+ this._manager.handleMouseDown(vTarget, e);
+ }
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ var vTarget = this.getListViewTarget(e);
+ if (vTarget) {
+ this._manager.handleMouseUp(vTarget, e);
+ }
+}
+
+qx.Proto._onclick = function(e)
+{
+ var vTarget = this.getListViewTarget(e);
+ if (vTarget) {
+ this._manager.handleClick(vTarget, e);
+ }
+}
+
+qx.Proto._ondblclick = function(e)
+{
+ var vTarget = this.getListViewTarget(e);
+ if (vTarget) {
+ this._manager.handleDblClick(vTarget, e);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ KEY EVENT HANDLER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onkeypress = function(e)
+{
+ this._manager.handleKeyPress(e);
+ e.preventDefault();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MANAGER SELECTION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._updateSelectionState = function(vItem, vIsSelected)
+{
+ vItem._selected = vIsSelected;
+ this._updateItem(vItem);
+}
+
+qx.Proto._updateAnchorState = function(vItem, vIsAnchor)
+{
+ vItem._anchor = vIsAnchor;
+ this._updateItem(vItem);
+}
+
+qx.Proto._updateLeadState = function(vItem, vIsLead)
+{
+ vItem._lead = vIsLead;
+ this._updateItem(vItem);
+}
+
+qx.Proto.scrollItemIntoView = function(vItem, vAlignLeftTop)
+{
+ this.scrollItemIntoViewX(vItem, vAlignLeftTop);
+ this.scrollItemIntoViewY(vItem, vAlignLeftTop);
+}
+
+qx.Proto.scrollItemIntoViewX = function(vItem, vAlignLeft) {
+ // this.error("Not implemented in qx.ui.listview.ListViewPane!");
+}
+
+qx.Proto.scrollItemIntoViewY = function(vItem, vAlignTop)
+{
+ var vItems = this._data;
+ var vOffset = vItems.indexOf(vItem) * this._rowHeight;
+ var vHeight = this._rowHeight;
+
+ // normalize client height (we want that the item is fully visible)
+ var vParentHeight = (Math.floor(this.getClientHeight() / this._rowHeight) *
+ this._rowHeight);
+ var vParentScrollTop = this._currentScrollTop;
+
+ var vNewScrollTop = null;
+
+ if (vAlignTop)
+ {
+ vNewScrollTop = vOffset;
+ }
+ else if (vAlignTop == false)
+ {
+ vNewScrollTop = vOffset + vHeight - vParentHeight;
+ }
+ else if (vHeight > 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<l; i++)
+ {
+ if (a[i].getMenu && a[i].getMenu() && a[i].getMenu().isSubButton(vButton)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEAR/DISAPPEAR
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._beforeAppear = function()
+{
+ // Intentionally bypass superclass and call super.super._beforeAppear
+ qx.ui.layout.CanvasLayout.prototype._beforeAppear.call(this);
+
+ // register to menu manager as active widget
+ qx.manager.object.MenuManager.getInstance().add(this);
+
+ // zIndex handling
+ this.bringToFront();
+
+ //setup as global active widget
+ this._makeActive();
+}
+
+qx.Proto._beforeDisappear = function()
+{
+ // Intentionally bypass superclass and call super.super._beforeDisappear
+ qx.ui.layout.CanvasLayout.prototype._beforeDisappear.call(this);
+
+ // deregister as opened from qx.manager.object.MenuManager
+ qx.manager.object.MenuManager.getInstance().remove(this);
+
+ // reset global active widget
+ this._makeInactive();
+
+ // reset properties on close
+ this.setHoverItem(null);
+ this.setOpenItem(null);
+
+ // be sure that the opener button gets the correct state
+ var vOpener = this.getOpener();
+ if (vOpener) {
+ vOpener.removeState("pressed");
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyHoverItem = function(propValue, propOldValue, propData)
+{
+ if (propOldValue) {
+ propOldValue.removeState("over");
+ }
+
+ if (propValue) {
+ propValue.addState("over");
+ }
+
+ return true;
+}
+
+qx.Proto._modifyOpenItem = function(propValue, propOldValue, propData)
+{
+ var vMakeActive = false;
+
+ if (propOldValue)
+ {
+ var vOldSub = propOldValue.getMenu();
+
+ if (vOldSub)
+ {
+ vOldSub.setParentMenu(null);
+ vOldSub.setOpener(null);
+ vOldSub.hide();
+ }
+ }
+
+ if (propValue)
+ {
+ var vSub = propValue.getMenu();
+
+ if (vSub)
+ {
+ vSub.setOpener(propValue);
+ vSub.setParentMenu(this);
+
+ var pl = propValue.getElement();
+ var el = this.getElement();
+
+ vSub.setTop(qx.dom.Location.getPageBoxTop(pl) + this.getSubMenuVerticalOffset());
+ vSub.setLeft(qx.dom.Location.getPageBoxLeft(el) + qx.dom.Dimension.getBoxWidth(el) + this.getSubMenuHorizontalOffset());
+
+ vSub.show();
+
+ qx.ui.core.Widget.flushGlobalQueues();
+ }
+ }
+
+ return true;
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LOCATIONS AND DIMENSIONS OF CHILDRENS CHILDREN:
+ CREATE VARIABLES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addCachedProperty({ name : "maxIconWidth" });
+qx.OO.addCachedProperty({ name : "maxLabelWidth" });
+qx.OO.addCachedProperty({ name : "maxLabelWidthIncShortcut" });
+qx.OO.addCachedProperty({ name : "maxShortcutWidth" });
+qx.OO.addCachedProperty({ name : "maxArrowWidth" });
+qx.OO.addCachedProperty({ name : "maxContentWidth" });
+
+qx.OO.addCachedProperty({ name : "iconPosition", defaultValue : 0 });
+qx.OO.addCachedProperty({ name : "labelPosition" });
+qx.OO.addCachedProperty({ name : "shortcutPosition" });
+qx.OO.addCachedProperty({ name : "arrowPosition" });
+
+qx.OO.addCachedProperty({ name : "menuButtonNeededWidth" });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ LOCATIONS AND DIMENSIONS OF CHILDRENS CHILDREN:
+ MAX WIDTH COMPUTERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._computeMaxIconWidth = function()
+{
+ var ch=this.getLayout().getChildren(), chl=ch.length, chc, m=0;
+
+ for (var i=0; i<chl; i++)
+ {
+ chc = ch[i];
+
+ if (chc.hasIcon()) {
+ // Make static as long as not supported well
+ // m = Math.max(m, chc.getIconObject().getPreferredBoxWidth());
+ m = Math.max(m, 16);
+ }
+ }
+
+ return m;
+}
+
+qx.Proto._computeMaxLabelWidth = function()
+{
+ var ch=this.getLayout().getChildren(), chl=ch.length, chc, m=0;
+
+ for (var i=0; i<chl; i++)
+ {
+ chc = ch[i];
+
+ if (chc.hasLabel()) {
+ m = Math.max(m, chc.getLabelObject().getPreferredBoxWidth());
+ }
+ }
+
+ return m;
+}
+
+qx.Proto._computeMaxLabelWidthIncShortcut = function()
+{
+ var ch=this.getLayout().getChildren(), chl=ch.length, chc, m=0;
+
+ for (var i=0; i<chl; i++)
+ {
+ chc = ch[i];
+
+ if (chc.hasLabel() && chc.hasShortcut()) {
+ m = Math.max(m, chc.getLabelObject().getPreferredBoxWidth());
+ }
+ }
+
+ return m;
+}
+
+qx.Proto._computeMaxShortcutWidth = function()
+{
+ var ch=this.getLayout().getChildren(), chl=ch.length, chc, m=0;
+
+ for (var i=0; i<chl; i++)
+ {
+ chc = ch[i];
+
+ if (chc.hasShortcut()) {
+ m = Math.max(m, chc.getShortcutObject().getPreferredBoxWidth());
+ }
+ }
+
+ return m;
+}
+
+qx.Proto._computeMaxArrowWidth = function()
+{
+ var ch=this.getLayout().getChildren(), chl=ch.length, chc, m=0;
+
+ for (var i=0; i<chl; i++)
+ {
+ chc = ch[i];
+
+ if (chc.hasMenu()) {
+ // Make static as long as not supported well
+ // m = Math.max(m, chc.getArrowObject().getPreferredBoxWidth());
+ m = Math.max(m, 4);
+ }
+ }
+
+ return m;
+}
+
+qx.Proto._computeMaxContentWidth = function()
+{
+ var vSum;
+
+ var lw = this.getMaxLabelWidth();
+ var sw = this.getMaxShortcutWidth();
+
+ if (this.getIndentShortcuts())
+ {
+ var vTemp = sw+this.getMaxLabelWidthIncShortcut();
+
+ if (sw > 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<vLength; i++) {
+ vAll[i].setZIndex(vIndex++);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ TIMESTAMP HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getShowTimeStamp = function() {
+ return this._showTimeStamp;
+}
+
+qx.Proto.getHideTimeStamp = function() {
+ return this._hideTimeStamp;
+}
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+/**
+ * Positions the popup relative to some reference element.
+ * @param el {var} Reference DOM element/widget.
+ * @param offsetX {int} Offset in pixels in X direction (optional).
+ * @param offsetY {int} Offset in pixels in Y direction (optional).
+ */
+qx.Proto.positionRelativeTo = function(el, offsetX, offsetY)
+{
+ if (el instanceof qx.ui.core.Widget) {
+ el = el.getElement();
+ }
+ if (el) {
+ var gecko = qx.sys.Client.getInstance().isGecko();
+ var loc = qx.dom.Location;
+ this.setLocation(loc.getClientAreaLeft(el) - (gecko ? qx.dom.Style.getBorderLeft(el):0) + (offsetX || 0),
+ loc.getClientAreaTop(el) - (gecko ? qx.dom.Style.getBorderTop(el):0) + (offsetY || 0));
+ } else {
+ this.warn('Missing reference element');
+ }
+}
+
+qx.Proto.centerToBrowser = function()
+{
+ var d = qx.ui.core.ClientDocument.getInstance();
+
+ var left = (d.getClientWidth() - this.getBoxWidth()) / 2;
+ var top = (d.getClientHeight() - this.getBoxHeight()) / 2;
+
+ this.setLeft(left < 0 ? 0 : left);
+ this.setTop(top < 0 ? 0 : top);
+}
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this._showTimeStamp = null;
+ this._hideTimeStamp = 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/popup/PopupAtom.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/PopupAtom.js
new file mode 100644
index 0000000000..eee111b84e
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/PopupAtom.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_popup)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.popup.PopupAtom", qx.ui.popup.Popup,
+function(vLabel, vIcon)
+{
+ qx.ui.popup.Popup.call(this);
+
+ this._atom = new qx.ui.basic.Atom(vLabel, vIcon);
+ this._atom.setParent(this);
+});
+
+qx.Proto.getAtom = function() {
+ return this._atom;
+}
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (this._atom)
+ {
+ this._atom.dispose();
+ this._atom = null;
+ }
+
+ return qx.ui.popup.Popup.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/ToolTip.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/ToolTip.js
new file mode 100644
index 0000000000..6fd70f61ba
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/popup/ToolTip.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_popup)
+#load(qx.manager.object.ToolTipManager)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.popup.ToolTip", qx.ui.popup.PopupAtom,
+function(vLabel, vIcon)
+{
+ // ************************************************************************
+ // INIT
+ // ************************************************************************
+
+ qx.ui.popup.PopupAtom.call(this, vLabel, vIcon);
+
+ // Apply shadow
+ this.setStyleProperty("filter", "progid:DXImageTransform.Microsoft.Shadow(color='Gray', Direction=135, Strength=4)");
+
+
+ // ************************************************************************
+ // TIMER
+ // ************************************************************************
+
+ this._showTimer = new qx.client.Timer(this.getShowInterval());
+ this._showTimer.addEventListener("interval", this._onshowtimer, this);
+
+ this._hideTimer = new qx.client.Timer(this.getHideInterval());
+ this._hideTimer.addEventListener("interval", this._onhidetimer, this);
+
+
+ // ************************************************************************
+ // EVENTS
+ // ************************************************************************
+ this.addEventListener("mouseover", this._onmouseover);
+ this.addEventListener("mouseout", this._onmouseover);
+});
+
+qx.Proto._minZIndex = 1e7;
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "tool-tip" });
+
+qx.OO.addProperty({ name : "hideOnHover", type : "boolean", defaultValue : true });
+
+qx.OO.addProperty({ name : "mousePointerOffsetX", type : "number", defaultValue : 1 });
+qx.OO.addProperty({ name : "mousePointerOffsetY", type : "number", defaultValue : 20 });
+
+qx.OO.addProperty({ name : "showInterval", type : "number", defaultValue : 1000 });
+qx.OO.addProperty({ name : "hideInterval", type : "number", defaultValue : 4000 });
+
+qx.OO.addProperty({ name : "boundToWidget", type : "object", instance : "qx.ui.core.Widget" });
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyHideInterval = function(propValue, propOldValue, propData)
+{
+ this._hideTimer.setInterval(propValue);
+ return true;
+}
+
+qx.Proto._modifyShowInterval = function(propValue, propOldValue, propData)
+{
+ this._showTimer.setInterval(propValue);
+ return true;
+}
+
+qx.Proto._modifyBoundToWidget = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ this.setParent(propValue.getTopLevelWidget());
+ }
+ else if (propOldValue)
+ {
+ this.setParent(null);
+ }
+
+ return true;
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEAR/DISAPPEAR
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._beforeAppear = function()
+{
+ qx.ui.popup.PopupAtom.prototype._beforeAppear.call(this);
+
+ this._stopShowTimer();
+ this._startHideTimer();
+}
+
+qx.Proto._beforeDisappear = function() {
+ qx.ui.popup.PopupAtom.prototype._beforeDisappear.call(this);
+
+ this._stopHideTimer();
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ TIMER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._startShowTimer = function()
+{
+ if(!this._showTimer.getEnabled()) {
+ this._showTimer.start();
+ }
+}
+
+qx.Proto._startHideTimer = function()
+{
+ if(!this._hideTimer.getEnabled()) {
+ this._hideTimer.start();
+ }
+}
+
+qx.Proto._stopShowTimer = function()
+{
+ if(this._showTimer.getEnabled()) {
+ this._showTimer.stop();
+ }
+}
+
+qx.Proto._stopHideTimer = function()
+{
+ if(this._hideTimer.getEnabled()) {
+ this._hideTimer.stop();
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmouseover = function(e)
+{
+ if(this.getHideOnHover()) {
+ this.hide();
+ }
+}
+
+qx.Proto._onshowtimer = function(e)
+{
+ this.setLeft(qx.event.type.MouseEvent.getPageX() + this.getMousePointerOffsetX());
+ this.setTop(qx.event.type.MouseEvent.getPageY() + this.getMousePointerOffsetY());
+
+ this.show();
+
+ // we need a manual flushing because it could be that
+ // there is currently no event which do this for us
+ // and so show the tooltip.
+ qx.ui.core.Widget.flushGlobalQueues();
+
+ return true;
+}
+
+qx.Proto._onhidetimer = function(e) {
+ return this.hide();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if(this.getDisposed()) {
+ return;
+ }
+
+ this.removeEventListener("mouseover", this._onmouseover);
+ this.removeEventListener("mouseout", this._onmouseover);
+
+ if (this._showTimer)
+ {
+ this._showTimer.removeEventListener("interval", this._onshowtimer, this);
+ this._showTimer.dispose();
+ this._showTimer = null;
+ }
+
+ if (this._hideTimer)
+ {
+ this._hideTimer.removeEventListener("interval", this._onhidetimer, this);
+ this._hideTimer.dispose();
+ this._hideTimer = null;
+ }
+
+ return qx.ui.popup.PopupAtom.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/resizer/Resizer.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/resizer/Resizer.js
new file mode 100755
index 0000000000..7ebd182268
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/resizer/Resizer.js
@@ -0,0 +1,417 @@
+/* ************************************************************************
+
+ 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)
+ * David Perez (david-perez)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_resizer)
+
+************************************************************************ */
+
+/**
+ * This class acts as a wrapper for other child, and allows it to be resized (not moved), normally in
+ * the right and/or bottom directions. Child can be e.g. a qx.ui.form.TextArea,
+ * qx.ui.table.Table or qx.ui.form.List. It is an alternative to splitters.
+ */
+qx.OO.defineClass('qx.ui.resizer.Resizer', qx.ui.layout.CanvasLayout,
+function(child)
+{
+ qx.ui.layout.CanvasLayout.call(this);
+
+ this._frame = new qx.ui.basic.Terminator;
+ this._frame.setAppearance("resizer-frame");
+
+ this._registerResizeEvents();
+
+ this.setAppearance('resizer');
+ this.setResizeableWest(false);
+ this.setResizeableNorth(false);
+
+ this.setMinWidth("auto");
+ this.setMinHeight("auto");
+ this.auto();
+
+ if (child)
+ {
+ // Remove child border, as the resizer has already its own border.
+ child.setBorder(new qx.renderer.border.Border(0));
+ this.add(this._child = child);
+ }
+});
+
+
+
+
+
+/*!
+ If the window is resizeable in the left direction.
+*/
+qx.OO.addProperty({ name : "resizeableWest", type : "boolean", defaultValue : true });
+/*!
+ If the window is resizeable in the top direction.
+*/
+qx.OO.addProperty({ name : "resizeableNorth", type : "boolean", defaultValue : true });
+/*!
+ If the window is resizeable in the right direction.
+*/
+qx.OO.addProperty({ name : "resizeableEast", type : "boolean", defaultValue : true });
+/*!
+ If the window is resizeable in the bottom direction.
+*/
+qx.OO.addProperty({ name : "resizeableSouth", type : "boolean", defaultValue : true });
+
+/*!
+ If the window is resizeable
+*/
+qx.OO.addPropertyGroup({ name : "resizeable", members : [ "west", "north", "east", "south" ], mode : "shorthand" });
+
+/*!
+ The resize method to use
+*/
+qx.OO.addProperty({ name : "resizeMethod", type : "string", defaultValue : "frame", possibleValues : [ "opaque", "lazyopaque", "frame", "translucent" ] });
+
+/*!
+ The resize method to use
+*/
+qx.OO.addProperty({ name : "resizeMethod", type : "string", defaultValue : "frame", possibleValues : [ "opaque", "lazyopaque", "frame", "translucent" ] });
+
+
+
+
+
+
+/**
+ * Adjust so that it returns a boolean instead of an array.
+ * @return {boolean}
+ */
+qx.Proto.isResizeable = qx.Proto.getResizeable = function() {
+ return this.getResizeableWest() || this.getResizeableEast() || this.getResizeableNorth() || this.getResizeableSouth();
+}
+
+qx.Proto._registerResizeEvents = function() {
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+ this.addEventListener("mousemove", this._onmousemove);
+}
+
+qx.Proto._onmousedown = function(e)
+{
+ if (this._resizeNorth || this._resizeSouth || this._resizeWest || this._resizeEast)
+ {
+ // enable capturing
+ this.setCapture(true);
+
+ // activate global cursor
+ this.getTopLevelWidget().setGlobalCursor(this.getCursor());
+
+ // caching element
+ var el = this.getElement();
+
+ // measuring and caching of values for resize session
+ var pa = this.getTopLevelWidget();
+ 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);
+
+ // handle frame and translucently
+ switch(this.getResizeMethod())
+ {
+ case "translucent":
+ this.setOpacity(0.5);
+ break;
+
+ case "frame":
+ var f = this._frame;
+
+ if (f.getParent() != pa)
+ {
+ f.setParent(pa);
+ 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;
+ }
+
+ // create resize session
+ var s = this._resizeSession = {};
+ var minRef = this._child;
+
+ if (this._resizeWest)
+ {
+ s.boxWidth = qx.dom.Dimension.getBoxWidth(el);
+ s.boxRight = qx.dom.Location.getPageBoxRight(el);
+ }
+
+ if (this._resizeWest || this._resizeEast)
+ {
+ s.boxLeft = qx.dom.Location.getPageBoxLeft(el);
+
+ s.parentAreaOffsetLeft = l;
+ s.parentAreaOffsetRight = r;
+
+ s.minWidth = minRef.getMinWidthValue();
+ s.maxWidth = minRef.getMaxWidthValue();
+ }
+
+ if (this._resizeNorth)
+ {
+ s.boxHeight = qx.dom.Dimension.getBoxHeight(el);
+ s.boxBottom = qx.dom.Location.getPageBoxBottom(el);
+ }
+
+ if (this._resizeNorth || this._resizeSouth)
+ {
+ s.boxTop = qx.dom.Location.getPageBoxTop(el);
+
+ s.parentAreaOffsetTop = t;
+ s.parentAreaOffsetBottom = b;
+
+ s.minHeight = minRef.getMinHeightValue();
+ s.maxHeight = minRef.getMaxHeightValue();
+ }
+ }
+ else
+ {
+ // cleanup resize session
+ delete this._resizeSession;
+ }
+
+ // stop event
+ e.stopPropagation();
+}
+
+qx.Proto._onmouseup = function(e)
+{
+ var s = this._resizeSession;
+
+ if (s)
+ {
+ // disable capturing
+ this.setCapture(false);
+
+ // deactivate global cursor
+ this.getTopLevelWidget().setGlobalCursor(null);
+
+ // sync sizes to frame
+ switch(this.getResizeMethod())
+ {
+ case "frame":
+ var o = this._frame;
+ if (!(o && o.getParent())) {
+ break;
+ }
+ // no break here
+
+ case "lazyopaque":
+ if (qx.util.Validation.isValidNumber(s.lastLeft)) {
+ this.setLeft(s.lastLeft);
+ }
+
+ if (qx.util.Validation.isValidNumber(s.lastTop)) {
+ this.setTop(s.lastTop);
+ }
+
+ if (qx.util.Validation.isValidNumber(s.lastWidth)) {
+ var child = this.getChildren()[0];
+ if (child) {
+ child.setWidth(s.lastWidth);
+ }
+ }
+
+ if (qx.util.Validation.isValidNumber(s.lastHeight)) {
+ var child = this.getChildren()[0];
+ if (child) {
+ child.setHeight(s.lastHeight);
+ }
+ }
+
+ if (this.getResizeMethod() == "frame") {
+ this._frame.setParent(null);
+ }
+ break;
+
+ case "translucent":
+ this.setOpacity(null);
+ break;
+ }
+
+ // cleanup session
+ delete this._resizeNorth;
+ delete this._resizeEast;
+ delete this._resizeSouth;
+ delete this._resizeWest;
+
+ delete this._resizeSession;
+ }
+
+ // stop event
+ e.stopPropagation();
+}
+
+qx.Proto._near = function(p, e) {
+ return e > (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.<br /><br />
+ *
+ * new qx.ui.splitpane.HorizontalSplitPane()<br />
+ * 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.<br /><br />
+ *
+ * new qx.ui.splitpane.VerticalSplitPane()<br />
+ * 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 = '<div style="';
+qx.Class.MAIN_DIV_START_END = '">';
+qx.Class.MAIN_DIV_END = '</div>';
+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 = '<div style="position:absolute;left:';
+qx.Class.ARRAY_JOIN_MAIN_DIV_WIDTH = 'px;top:0px;width:';
+qx.Class.ARRAY_JOIN_MAIN_DIV_HEIGHT = 'px;height:';
+qx.Class.ARRAY_JOIN_MAIN_DIV_START_END = '">';
+qx.Class.ARRAY_JOIN_MAIN_DIV_END = '</div>';
+
+qx.Class.TABLE_TD = '<td style="height:';
+qx.Class.TABLE_TD_END = '</td>'; \ No newline at end of file
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/AbstractTableModel.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/AbstractTableModel.js
new file mode 100644
index 0000000000..99470e9361
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/table/AbstractTableModel.js
@@ -0,0 +1,150 @@
+/* ************************************************************************
+
+ 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 table model that performs the column handling, so subclasses only
+ * need to care for row handling.
+ */
+qx.OO.defineClass("qx.ui.table.AbstractTableModel", qx.ui.table.TableModel,
+function() {
+ qx.ui.table.TableModel.call(this);
+
+ this._columnIdArr = [];
+ this._columnNameArr = [];
+ this._columnIndexMap = {};
+});
+
+
+// overridden
+qx.Proto.getColumnCount = function() {
+ return this._columnIdArr.length;
+}
+
+
+// overridden
+qx.Proto.getColumnIndexById = function(columnId) {
+ return this._columnIndexMap[columnId];
+}
+
+
+// overridden
+qx.Proto.getColumnId = function(columnIndex) {
+ return this._columnIdArr[columnIndex];
+}
+
+
+// overridden
+qx.Proto.getColumnName = function(columnIndex) {
+ return this._columnNameArr[columnIndex];
+}
+
+
+/**
+ * Sets the column IDs. These IDs may be used internally to identify a column.
+ * <p>
+ * Note: This will clear previously set column names.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * Note: The column IDs have to be defined before.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * Note: The column IDs have to be defined before.
+ * </p>
+ *
+ * @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.
+ * <p>
+ * The cellInfo map contains the following properties:
+ * <ul>
+ * <li>value (var): the cell's value.</li>
+ * <li>row (int): the model index of the row the cell belongs to.</li>
+ * <li>col (int): the model index of the column the cell belongs to.</li>
+ * <li>xPos (int): the x position of the cell in the table pane.</li>
+ * </ul>
+ *
+ * @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.
+ * <p>
+ * The cellInfo map contains the following properties:
+ * <ul>
+ * <li>value (var): the cell's value.</li>
+ * <li>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()}</li>
+ * <li>row (int): the model index of the row the cell belongs to.</li>
+ * <li>col (int): the model index of the column the cell belongs to.</li>
+ * <li>table (qx.ui.table.Table): the table the cell belongs to.</li>
+ * <li>xPos (int): the x position of the cell in the table pane.</li>
+ * <li>selected (boolean): whether the cell is selected.</li>
+ * <li>focusedCol (boolean): whether the cell is in the same column as the
+ * focused cell.</li>
+ * <li>focusedRow (boolean): whether the cell is in the same row as the
+ * focused cell.</li>
+ * <li>editable (boolean): whether the cell is editable.</li>
+ * <li>style (string): The CSS styles that should be applied to the outer HTML
+ * element.</li>
+ * </ul>
+ *
+ * @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.
+ * <p>
+ * The rowInfo map contains the following properties:
+ * <ul>
+ * <li>rowData (var): contains the row data for the row.
+ * The kind of this object depends on the table model, see
+ * {@link TableModel#getRowData()}</li>
+ * <li>row (int): the model index of the row.</li>
+ * <li>selected (boolean): whether a cell in this row is selected.</li>
+ * <li>focusedRow (boolean): whether the focused cell is in this row.</li>
+ * <li>table (qx.ui.table.Table): the table the row belongs to.</li>
+ * </ul>
+ *
+ * @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 "&lt;";
+ case ">": return "&gt;";
+ case "&": return "&amp;";
+ }
+}
+
+
+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.
+ * <p>
+ * The cellInfo map contains the following properties:
+ * <ul>
+ * <li>col (int): the model index of the column.</li>
+ * <li>xPos (int): the x position of the column in the table pane.</li>
+ * <li>name (string): the name of the column.</li>
+ * <li>editable (boolean): whether the column is editable.</li>
+ * <li>sorted (boolean): whether the column is sorted.</li>
+ * <li>sortedAscending (boolean): whether sorting is ascending.</li>
+ * </ul>
+ *
+ * @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:
+ * <ul>
+ * <li>"url": (type string) must be the URL of the image to show.</li>
+ * <li>"imageWidth": (type int) the width of the image in pixels.</li>
+ * <li>"imageHeight": (type int) the height of the image in pixels.</li>
+ * <li>"tooltip": (type string) must be the image tooltip text.</li>
+ * </ul>
+ */
+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 = '<img src="';
+qx.Class.IMG_END = '"/>';
+qx.Class.IMG_TITLE_START = '" title="';
+qx.Class.TABLE_DIV = '<div style="overflow:hidden;height:';
+qx.Class.TABLE_DIV_CLOSE = 'px">';
+qx.Class.TABLE_DIV_END = '</div>';
+
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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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);
+ }
+ }
+};
+
+
+/**
+ * <p>See overridden method for details.</p>
+ *
+ * @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.
+ * <p>
+ * 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;
+}
+
+
+/**
+ * <p>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.</p>
+ *
+ * <p>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.</p>
+ *
+ * @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();
+}
+
+
+/**
+ * <p>Returns whether batch mode is active. See setter for a description of batch mode.</p>
+ *
+ * @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
+ * <code>minIndex</code> and a <code>maxIndex</code> 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.
+ * <p>
+ * Usage Example:
+ * <pre>
+ * var selectedRowData = [];
+ * mySelectionModel.iterateSelection(function(index) {
+ * selectedRowData.push(myTableModel.getRowData(index));
+ * });
+ * </pre>
+ *
+ * @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;
+});
+
+
+/**
+ * <p>See overridden method for details.</p>
+ *
+ * @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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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:
+ * <ul>
+ * <li>col: The model index of the column the width of which has changed.</li>
+ * <li>newWidth: The new width of the column in pixels.</li>
+ * <li>oldWidth: The old width of the column in pixels.</li>
+ * </ul>
+ * @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:
+ * <ul>
+ * <li>col: The model index of the column the visibility of which has changed.</li>
+ * <li>visible: Whether the column is now visible.</li>
+ * </ul>
+ * @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:
+ * <ul>
+ * <li>col: The model index of the column that was moved.</li>
+ * <li>fromOverXPos: The old overall x position of the column.</li>
+ * <li>toOverXPos: The new overall x position of the column.</li>
+ * </ul>
+ *
+ * @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.
+ * <p>
+ * 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:
+ * <ul>
+ * <li>firstRow: The index of the first row that has changed.</li>
+ * <li>lastRow: The index of the last row that has changed.</li>
+ * <li>firstColumn: The model index of the first column that has changed.</li>
+ * <li>lastColumn: The model index of the last column that has changed.</li>
+ * </ul>
+ * @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");
+}
+
+
+/**
+ * <p>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.</p>
+ *
+ * <p><b>Important:</b>Models which do not have their row data accessible in one object
+ * may return null.</p>
+ *
+ * @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.
+ * <p>
+ * 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.
+ * <p>
+ * 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('<table cellspacing\="0" cellpadding\="0" style\="table-layout:fixed;font-family:\'Segoe UI\', Corbel, Calibri, Tahoma, \'Lucida Sans Unicode\', sans-serif;font-size:11px;width:');
+ htmlArr.push(rowWidth);
+ htmlArr.push('px"><colgroup>');
+
+ for (var x = 0; x < colCount; x++) {
+ var col = paneModel.getColumnAtX(x);
+
+ htmlArr.push();
+ htmlArr.push(columnModel.getColumnWidth(col));
+ htmlArr.push('"/>');
+ }
+
+ htmlArr.push('</colgroup><tbody>');
+ }
+
+ 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('<tr style\="height:');
+ htmlArr.push(rowHeight);
+ } else {
+ htmlArr.push('<div style\="position:absolute;font-family:\'Segoe UI\', Corbel, Calibri, Tahoma, \'Lucida Sans Unicode\', sans-serif;font-size:11px;left:0px;top:');
+ htmlArr.push(y * rowHeight);
+ htmlArr.push('px;width:');
+ htmlArr.push(rowWidth);
+ htmlArr.push('px;height:');
+ htmlArr.push(rowHeight);
+ htmlArr.push('px;background-color:');
+ }
+
+ rowRenderer._createRowStyle_array_join(cellInfo, htmlArr);
+
+ 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('</tr>');
+ } else {
+ htmlArr.push('</div>');
+ }
+ }
+
+ if (TablePane.USE_TABLE) {
+ htmlArr.push('</tbody></table>');
+ }
+
+ 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 <code>xPos</code>.
+ *
+ * @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 <code>col</code>.
+ *
+ * @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).
+ * <p>
+ * 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
+ * <code>pageX</code>/<code>pageY</code>. 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.
+ * <p>
+ * 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<vLength; i++) {
+ if (!(vChildren[i] instanceof qx.ui.toolbar.PartHandle)) {
+ cloneInstance.add(vChildren[i].clone(true));
+ }
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ if (this._handle)
+ {
+ this._handle.dispose();
+ this._handle = 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/toolbar/PartHandle.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/PartHandle.js
new file mode 100644
index 0000000000..4e50692832
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/PartHandle.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)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_toolbar)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.toolbar.PartHandle", qx.ui.layout.CanvasLayout,
+function()
+{
+ qx.ui.layout.CanvasLayout.call(this);
+
+ var l = new qx.ui.basic.Terminator;
+ l.setAppearance("toolbar-part-handle-line");
+ this.add(l);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "toolbar-part-handle" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/RadioButton.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/RadioButton.js
new file mode 100644
index 0000000000..fd222a214c
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/RadioButton.js
@@ -0,0 +1,116 @@
+/* ************************************************************************
+
+ 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.RadioButton", qx.ui.toolbar.CheckBox,
+function(vText, vIcon, vChecked) {
+ qx.ui.toolbar.CheckBox.call(this, vText, vIcon, vChecked);
+});
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ 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" });
+
+/*!
+ Prohibit the deselction of the checked radio button when clicked on it.
+*/
+qx.OO.addProperty({ name : "disableUncheck", type : "boolean", defaultValue : false });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyChecked = function(propValue, propOldValue, propData)
+{
+ qx.ui.toolbar.CheckBox.prototype._modifyChecked.call(this, propValue, propOldValue, propData);
+
+ var vManager = this.getManager();
+ if (vManager) {
+ vManager.handleItemChecked(this, propValue);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyManager = function(propValue, propOldValue, propData)
+{
+ if (propOldValue) {
+ propOldValue.remove(this);
+ }
+
+ if (propValue) {
+ propValue.add(this);
+ }
+
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onmouseup = function(e)
+{
+ this.setCapture(false);
+
+ if (!this.hasState("abandoned"))
+ {
+ this.addState("over");
+ this.setChecked(this.getDisableUncheck() || !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/Separator.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Separator.js
new file mode 100644
index 0000000000..61c07ee760
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/Separator.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)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_toolbar)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.toolbar.Separator", qx.ui.layout.CanvasLayout,
+function()
+{
+ qx.ui.layout.CanvasLayout.call(this);
+
+ var l = new qx.ui.basic.Terminator;
+ l.setAppearance("toolbar-separator-line");
+ this.add(l);
+});
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "toolbar-separator" });
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/ToolBar.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/ToolBar.js
new file mode 100644
index 0000000000..c3ada9e29c
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/toolbar/ToolBar.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)
+
+************************************************************************ */
+
+/* ************************************************************************
+
+#module(ui_toolbar)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.toolbar.ToolBar", qx.ui.layout.HorizontalBoxLayout,
+function()
+{
+ qx.ui.layout.HorizontalBoxLayout.call(this);
+
+ this.addEventListener("keypress", this._onkeypress);
+});
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.addProperty({ name : "openMenu", type : "object", instance : "qx.ui.menu.Menu" });
+
+/*!
+ Appearance of the widget
+*/
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "toolbar" });
+
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getAllButtons = function()
+{
+ var vChildren = this.getChildren();
+ var vLength = vChildren.length;
+ var vDeepChildren = [];
+ var vCurrent;
+
+ for (var i=0; i<vLength; i++)
+ {
+ vCurrent = vChildren[i];
+
+ if (vCurrent instanceof qx.ui.toolbar.MenuButton)
+ {
+ vDeepChildren.push(vCurrent);
+ }
+ else if (vCurrent instanceof qx.ui.toolbar.Part)
+ {
+ vDeepChildren = vDeepChildren.concat(vCurrent.getChildren());
+ }
+ }
+
+ return vDeepChildren;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Wraps key events to target functions
+*/
+qx.Proto._onkeypress = function(e)
+{
+ switch(e.getKeyIdentifier())
+ {
+ case "Left":
+ return this._onkeypress_left();
+
+ case "Right":
+ return this._onkeypress_right();
+ }
+}
+
+qx.Proto._onkeypress_left = 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 vPrevButton = null;
+
+ for (var i=vIndex-1; 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; i<vChildrenLength; i++)
+ {
+ vCurrent = vChildren[i];
+
+ if (vCurrent instanceof qx.ui.toolbar.MenuButton && vCurrent.getEnabled())
+ {
+ vNextButton = vCurrent;
+ break;
+ }
+ }
+
+ // If none found, try again from the begin (looping)
+ if (!vNextButton)
+ {
+ for (var i=0; i<vIndex; i++)
+ {
+ vCurrent = vChildren[i];
+
+ if (vCurrent instanceof qx.ui.toolbar.MenuButton && vCurrent.getEnabled())
+ {
+ vNextButton = vCurrent;
+ break;
+ }
+ }
+ }
+
+ if (vNextButton)
+ {
+ // hide other menus
+ qx.manager.object.MenuManager.getInstance().update();
+
+ // show next menu
+ vNextButton._showMenu(true);
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this.removeEventListener("keypress", this._onkeypress);
+
+ return qx.ui.layout.HorizontalBoxLayout.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/AbstractTreeElement.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/AbstractTreeElement.js
new file mode 100644
index 0000000000..b5468a3540
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/tree/AbstractTreeElement.js
@@ -0,0 +1,502 @@
+/* ************************************************************************
+
+ 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.AbstractTreeElement", qx.ui.layout.BoxLayout,
+function(vLabel, vIcon, vIconSelected)
+{
+ if (this.classname == qx.ui.tree.AbstractTreeElement.ABSTRACT_CLASS) {
+ throw new Error("Please omit the usage of qx.ui.tree.AbstractTreeElement directly. Choose between qx.ui.tree.TreeFolder and qx.ui.tree.TreeFile instead!");
+ }
+
+ // Precreate subwidgets
+ this._indentObject = new qx.ui.embed.HtmlEmbed;
+ this._iconObject = new qx.ui.basic.Image;
+ this._labelObject = new qx.ui.basic.Label;
+
+ // Make anonymous
+ this._indentObject.setAnonymous(true);
+ this._iconObject.setAnonymous(true);
+ this._labelObject.setAnonymous(true);
+
+ // Behaviour and Hard Styling
+ this._labelObject.setSelectable(false);
+ this._labelObject.setStyleProperty("lineHeight", "100%");
+
+ qx.ui.layout.BoxLayout.call(this, "horizontal");
+
+ if (qx.util.Validation.isValid(vLabel)) {
+ this.setLabel(vLabel);
+ }
+
+ // Prohibit selection
+ this.setSelectable(false);
+
+ // Base URL used for indent images
+ this.BASE_URI = qx.manager.object.AliasManager.getInstance().resolvePath("widget/tree/");
+
+ // Adding subwidgets
+ this.add(this._indentObject, this._iconObject, this._labelObject);
+
+ // Set Icons
+ if ((vIcon != null) && (qx.util.Validation.isValidString(vIcon))) {
+ this.setIcon(vIcon);
+ this.setIconSelected(vIcon);
+ }
+ if ((vIconSelected != null) && (qx.util.Validation.isValidString(vIconSelected))) {
+ this.setIconSelected(vIconSelected);
+ }
+
+ // Setup initial icon
+ this._iconObject.setSource(this._evalCurrentIcon());
+
+ // Set Appearance
+ this._iconObject.setAppearance("tree-element-icon");
+ this._labelObject.setAppearance("tree-element-label");
+
+ // Register event listeners
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+});
+
+qx.ui.tree.AbstractTreeElement.ABSTRACT_CLASS = "qx.ui.tree.AbstractTreeElement";
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "tree-element" });
+
+/*!
+ The icons
+*/
+qx.OO.addProperty({ name : "icon", type : "string" });
+qx.OO.addProperty({ name : "iconSelected", type : "string" });
+
+/*!
+ The label/caption/text of the qx.ui.basic.Atom instance
+*/
+qx.OO.addProperty({ name : "label", type : "string" });
+
+/*!
+ Selected property
+*/
+qx.OO.addProperty({ name : "selected", type : "boolean", defaultValue : false });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyLabel = function(propValue, propOldValue, propData)
+{
+ if (this._labelObject) {
+ this._labelObject.setHtml(propValue);
+ }
+
+ return true;
+}
+
+qx.Proto._modifySelected = function(propValue, propOldValue, propData)
+{
+ propValue ? this.addState("selected") : this.removeState("selected");
+ propValue ? this._labelObject.addState("selected") : this._labelObject.removeState("selected");
+
+ var vTree = this.getTree();
+ if (!vTree._fastUpdate || (propOldValue && vTree._oldItem == this))
+ {
+ this._iconObject.setSource(this._evalCurrentIcon());
+
+ if (propValue) {
+ this._iconObject.addState("selected");
+ } else {
+ this._iconObject.removeState("selected");
+ }
+ }
+
+ var vManager = this.getTree().getManager();
+
+ if (propOldValue && vManager.getSelectedItem() == this)
+ {
+ vManager.deselectAll();
+ }
+ else if (propValue && vManager.getSelectedItem() != this)
+ {
+ vManager.setSelectedItem(this);
+ }
+
+ return true;
+}
+
+qx.Proto._evalCurrentIcon = function()
+{
+ if (this.getSelected() && this.getIconSelected()) {
+ return this.getIconSelected();
+ } else {
+ return this.getIcon() || "icon/16/file-new.png";
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getParentFolder = function()
+{
+ try {
+ return this.getParent().getParent();
+ } catch(ex) {}
+
+ return null;
+}
+
+qx.Proto.getLevel = function()
+{
+ var vParentFolder = this.getParentFolder();
+ return vParentFolder ? vParentFolder.getLevel() + 1 : null;
+}
+
+qx.Proto.getTree = function()
+{
+ var vParentFolder = this.getParentFolder();
+ return vParentFolder ? vParentFolder.getTree() : null;
+}
+
+qx.Proto.getIndentObject = function() {
+ return this._indentObject;
+}
+
+qx.Proto.getIconObject = function() {
+ return this._iconObject;
+}
+
+qx.Proto.getLabelObject = function() {
+ return this._labelObject;
+}
+
+/**
+ * <p>deselects, disconnects, removes and disposes the
+ * current tree element and its content.
+ * </p>
+ *
+ * <p>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).
+ * </p>
+ *
+ * <p>The method destroyContent is defined in the TreeFolder class.
+ * </p>
+ */
+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<vLevel; i++)
+ {
+ vImage = vCurrentObject.getIndentSymbol(vTree.getUseTreeLines(), i==0);
+
+ if (vImage)
+ {
+ vHtml.push("<img style=\"position:absolute;top:0px;left:");
+ vHtml.push((vLevel-i-1) * 19);
+ vHtml.push("px\" src=\"");
+ vHtml.push(this.BASE_URI);
+ vHtml.push(vImage);
+ vHtml.push(".");
+ vHtml.push("gif");
+ vHtml.push("\" />");
+ }
+
+ 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; i<chl; i++) {
+ a = a.concat(ch[i].getItems(recursive, invisible));
+ }
+ }
+ }
+
+ return a;
+}
+
+/**
+ * <p>deselects, disconnects, removes and disposes the
+ * content of the folder and its subfolders.
+ * </p>
+ *
+ * <p>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.
+ * </p>
+ */
+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<l; i++) {
+ ch[i]._updateIndent();
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this.removeEventListener("dblclick", this._ondblclick);
+
+ if (this._horizontalLayout)
+ {
+ this._horizontalLayout.dispose();
+ this._horizontalLayout = null;
+ }
+
+ if (this._containerObject)
+ {
+ this._containerObject.dispose();
+ this._containerObject = null;
+ }
+
+ return qx.ui.tree.AbstractTreeElement.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/AbstractTreeElement.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/AbstractTreeElement.js
new file mode 100644
index 0000000000..16245b9f0b
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/AbstractTreeElement.js
@@ -0,0 +1,529 @@
+/* ************************************************************************
+
+ 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.OO.defineClass("qx.ui.treefullcontrol.AbstractTreeElement", qx.ui.layout.BoxLayout,
+function(treeRowStructure)
+{
+ if (this.classname == qx.ui.treefullcontrol.AbstractTreeElement.ABSTRACT_CLASS) {
+ throw new Error("Please omit the usage of qx.ui.treefullcontrol.AbstractTreeElement directly. Choose between qx.ui.treefullcontrol.TreeFolder, qx.ui.treefullcontrol.TreeFolderSimple, qx.ui.treefullcontrol.TreeFile and qx.ui.treefullcontrol.TreeFileSimple instead!");
+ }
+
+ if (treeRowStructure !== qx.ui.treefullcontrol.TreeRowStructure.getInstance())
+ {
+ throw new Error("A qx.ui.treefullcontrol.TreeRowStructure parameter is required.");
+ }
+
+ // Precreate subwidgets
+ this._indentObject = treeRowStructure._indentObject;
+ this._iconObject = treeRowStructure._iconObject;
+ this._labelObject = treeRowStructure._labelObject;
+
+ // Make anonymous
+ this._indentObject.setAnonymous(true);
+ this._iconObject.setAnonymous(true);
+ this._labelObject.setAnonymous(true);
+
+ // Behaviour and Hard Styling
+ this._labelObject.setSelectable(false);
+ this._labelObject.setStyleProperty("lineHeight",
+ "100%");
+
+ qx.ui.layout.BoxLayout.call(this, "horizontal");
+
+ if (qx.util.Validation.isValid(treeRowStructure._label)) {
+ this.setLabel(treeRowStructure._label);
+ }
+
+ // Prohibit selection
+ this.setSelectable(false);
+
+ // Base URL used for indent images
+ this.BASE_URI = qx.manager.object.AliasManager.getInstance().resolvePath("widget/tree/");
+
+ /*
+ * Add all of the objects which are to be in the horizontal layout.
+ */
+ for (var i = 0; i < treeRowStructure._fields.length; i++)
+ {
+ this.add(treeRowStructure._fields[i]);
+ }
+
+ // Set Icons
+ if ((treeRowStructure._icons.unselected != null) &&
+ (qx.util.Validation.isValidString(treeRowStructure._icons.unselected))) {
+ this.setIcon(treeRowStructure._icons.unselected);
+ this.setIconSelected(treeRowStructure._icons.unselected);
+ }
+ if ((treeRowStructure._icons.selected != null) &&
+ (qx.util.Validation.isValidString(treeRowStructure._icons.selected))) {
+ this.setIconSelected(treeRowStructure._icons.selected);
+ }
+
+ // Setup initial icon
+ this._iconObject.setSource(this._evalCurrentIcon());
+
+ // Set Appearance
+ this._iconObject.setAppearance("tree-element-icon");
+ this._labelObject.setAppearance("tree-element-label");
+
+ // Register event listeners
+ this.addEventListener("mousedown", this._onmousedown);
+ this.addEventListener("mouseup", this._onmouseup);
+});
+
+qx.ui.treefullcontrol.AbstractTreeElement.ABSTRACT_CLASS = "qx.ui.treefullcontrol.AbstractTreeElement";
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+qx.OO.changeProperty({ name : "appearance",
+ type : "string",
+ defaultValue : "tree-element"
+ });
+
+/*!
+ The icons
+*/
+qx.OO.addProperty({ name : "icon",
+ type : "string"
+ });
+
+qx.OO.addProperty({ name : "iconSelected",
+ type : "string"
+ });
+
+/*!
+ The label/caption/text of the qx.ui.basic.Atom instance
+*/
+qx.OO.addProperty({ name : "label",
+ type : "string"
+ });
+
+/*!
+ Selected property
+*/
+qx.OO.addProperty({ name : "selected",
+ type : "boolean",
+ defaultValue : false
+ });
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyLabel = function(propValue, propOldValue, propData)
+{
+ if (this._labelObject) {
+ this._labelObject.setHtml(propValue);
+ }
+
+ return true;
+}
+
+qx.Proto._modifySelected = function(propValue, propOldValue, propData)
+{
+ if (propValue) {
+ this.addState("selected");
+ this._labelObject.addState("selected");
+ } else {
+ this.removeState("selected");
+ this._labelObject.removeState("selected");
+ }
+
+ var vTree = this.getTree();
+ if (!vTree._fastUpdate ||
+ (propOldValue && vTree._oldItem == this)) {
+ this._iconObject.setSource(this._evalCurrentIcon());
+
+ if (propValue) {
+ this._iconObject.addState("selected");
+ } else {
+ this._iconObject.removeState("selected");
+ }
+ }
+
+ var vManager = this.getTree().getManager();
+
+ if (propOldValue && vManager.getSelectedItem() == this)
+ {
+ vManager.deselectAll();
+ }
+ else if (propValue && vManager.getSelectedItem() != this)
+ {
+ vManager.setSelectedItem(this);
+ }
+
+ return true;
+}
+
+qx.Proto._evalCurrentIcon = function()
+{
+ if (this.getSelected() && this.getIconSelected()) {
+ return this.getIconSelected();
+ } else {
+ return this.getIcon() || "icon/16/file-new.png";
+ }
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getParentFolder = function()
+{
+ try {
+ return this.getParent().getParent();
+ } catch(ex) {}
+
+ return null;
+}
+
+qx.Proto.getLevel = function()
+{
+ var vParentFolder = this.getParentFolder();
+ return vParentFolder ? vParentFolder.getLevel() + 1 : null;
+}
+
+qx.Proto.getTree = function()
+{
+ var vParentFolder = this.getParentFolder();
+ return vParentFolder ? vParentFolder.getTree() : null;
+}
+
+qx.Proto.getIndentObject = function() {
+ return this._indentObject;
+}
+
+qx.Proto.getIconObject = function() {
+ return this._iconObject;
+}
+
+qx.Proto.getLabelObject = function() {
+ return this._labelObject;
+}
+
+/**
+ * Obtain the entire hierarchy of labels from the root down to the current
+ * node.
+ *
+ * @param
+ * vArr -
+ * When called by the user, arr should typically be an empty array. Each
+ * level from the current node upwards will push its label onto the array.
+ */
+qx.Proto.getHierarchy = function(vArr) {
+ // Add our label to the array
+ if (this._labelObject) {
+ vArr.unshift(this._labelObject.getHtml());
+ }
+
+ // Get the parent folder
+ var parent = this.getParentFolder();
+
+ // If it exists...
+ if (parent) {
+ // ... then add it and its ancestors' labels to the array.
+ parent.getHierarchy(vArr);
+ }
+
+ // Give 'em what they came for
+ return vArr;
+}
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ 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.treefullcontrol.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 information 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;
+ var vMinLevel = 0;
+ var vMaxLevel = vLevel;
+
+ // If we're displaying the open/close button for the root node (normal)...
+ if (vTree.getRootOpenClose()) {
+ // ... then we need one more level
+ vMaxLevel = vLevel + 1;
+ }
+
+ // If we're not displaying the root node (creating virtual roots)...
+ if (vTree.hideNode()) {
+ // ... then start one level higher
+ vMinLevel = 1;
+ }
+
+ for (var i=vMinLevel; i<vMaxLevel; i++)
+ {
+ vImage = vCurrentObject.getIndentSymbol(vTree.getUseTreeLines(),
+ i,
+ vMinLevel,
+ vMaxLevel);
+
+ if (vImage)
+ {
+ vHtml.push("<img style=\"position:absolute;top:0px;left:");
+
+ // location of image; Root's image could be left of margin (invisible)
+ vHtml.push((vMaxLevel-i-1) * 19);
+
+ vHtml.push("px\" src=\"");
+ vHtml.push(this.BASE_URI);
+ vHtml.push(vImage);
+ vHtml.push(".");
+ vHtml.push("gif");
+ vHtml.push("\" />");
+ }
+
+ 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 <i>true</i>, indicates that tree lines at that indentation
+ level are to be omitted. Any value of that element other than <i>true</i>,
+ 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 <i>true</i> and desiring to reset the default
+ behavior, you should 'delete' the element rather than setting it to some
+ value other than <i>true</i>.)
+
+ If useTreeLines is <i>false</i>, 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<chl; i++) {
+ a = a.concat(ch[i].getItems());
+ }
+ }
+
+ return a;
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ 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)
+{
+ // we need the whole indent process if certain tree lines are to be excluded
+ if (this.getTree().getExcludeSpecificTreeLines().length > 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<l; i++) {
+ ch[i]._updateIndent();
+ }
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ DISPOSER
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.dispose = function()
+{
+ if (this.getDisposed()) {
+ return;
+ }
+
+ this.removeEventListener("dblclick", this._ondblclick);
+
+ if (this._horizontalLayout)
+ {
+ this._horizontalLayout.dispose();
+ this._horizontalLayout = null;
+ }
+
+ if (this._containerObject)
+ {
+ this._containerObject.dispose();
+ this._containerObject = null;
+ }
+
+ return qx.ui.treefullcontrol.AbstractTreeElement.prototype.dispose.call(this);
+}
diff --git a/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeRowStructure.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeRowStructure.js
new file mode 100644
index 0000000000..4fc32ef31e
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/treefullcontrol/TreeRowStructure.js
@@ -0,0 +1,260 @@
+/* ************************************************************************
+
+ 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(ui_treefullcontrol)
+
+************************************************************************ */
+
+/**
+ * The structure of a tree row.
+ *
+ * This is a singleton class. The constructor is not accessed by users;
+ * instead, to obtain the one and only TreeRowStructure object, call either
+ *
+ * qx.ui.treefullcontrol.TreeRowStructure.newRow()
+ *
+ * or
+ *
+ * qx.ui.treefullcontrol.TreeRowStructure.standard().
+ *
+ * The structure of a tree row is provided by a
+ * qx.ui.treefullcontrol.TreeRowStructure. The order of elements added to
+ * this object is the order in which they will be presented in a tree row.
+ *
+ * The three standard parts of a tree: the indentation (and its associated
+ * tree-lines, if enabled), the icon (selected or unselected), and the label
+ * are added to the structure in the desired order by calling, respectively,
+ * the methods addIndent(), addIcon() and addLabel().
+ *
+ * By default, indentation will appear at the beginning of the tree row. This
+ * can be changed by calling the addIndent() method after having calling other
+ * add*() methods on this object. If indentation is to be at the beginning of
+ * the tree row, simply do not call addIndent().
+ *
+ * Any other object which is valid within a qx.ui.layout.HorizontalBoxLayout
+ * may be added to the structure using addObject(). If the object has no
+ * special treatment, it may be made anonymous with obj.SetAnonymous(true).
+ * Otherwise, all handling for the object should be done by the application.
+ *
+ * A "standard" (traditional) tree row would be generated like this:
+ *
+ * treeRowStructure = qx.ui.treefullcontrol.TreeRowStructure.standard("Trash");
+ *
+ * which equates to issuing these commands:
+ *
+ * treeRowStructure = qx.ui.treefullcontrol.TreeRowStructure.newRow();
+ *
+ * //treeRowStructure.addIndent() // defaults to here; no need to call
+ * treeRowStructure.addIcon();
+ * treeRowStructure.addLabel("Trash");
+ *
+ * The former method is typically preferred.
+ *
+ * An example of a more sophisticated structure:
+ *
+ * treeRowStructure = qx.ui.treefullcontrol.TreeRowStructure.newRow();
+ *
+ * // A left-justified icon
+ * obj = new qx.ui.basic.Image("icon/16/alarm.png");
+ * treeRowStructure.addObject(obj, true);
+ *
+ * // Here's our indentation and tree-lines
+ * treeRowStructure.addIndent();
+ *
+ * // The standard tree icon follows
+ * treeRowStructure.addIcon("icon/16/desktop.png","icon/16/dictionary.png");
+ *
+ * // Right after the tree icon is a checkbox
+ * obj = new qx.ui.form.CheckBox(null, 23, null, false);
+ * obj.setPadding(0, 0);
+ * treeRowStructure.addObject(obj, true);
+ *
+ * // The label
+ * treeRowStructure.addLabel("Trash");
+ *
+ * // All else should be right justified
+ * obj = new qx.ui.basic.HorizontalSpacer;
+ * treeRowStructure.addObject(obj, true);
+ *
+ * // Add a file size, date and mode
+ * obj = new qx.ui.basic.Label("23kb");
+ * obj.setWidth(50);
+ * treeRowStructure.addObject(obj, true);
+ * obj = new qx.ui.basic.Label("11 Sept 1959");
+ * obj.setWidth(150);
+ * treeRowStructure.addObject(obj, true);
+ * obj = new qx.ui.basic.Label("-rw-r--r--");
+ * obj.setWidth(80);
+ * treeRowStructure.addObject(obj, true);
+ */
+
+qx.OO.defineClass("qx.ui.treefullcontrol.TreeRowStructure", qx.core.Object,
+function()
+{
+ qx.core.Object.call(this);
+});
+
+
+/**
+ * Prepare to define a new row.
+ *
+ * This reinitializes the singleton TreeRowStructure so that it is ready to
+ * define a new tree row.
+ *
+ * @return The singleton itself, purely for convenience.
+ */
+qx.Proto.newRow = function()
+{
+ /* Create the indent, icon, and label objects */
+ this._indentObject = new qx.ui.embed.HtmlEmbed;
+ this._iconObject = new qx.ui.basic.Image;
+ this._labelObject = new qx.ui.basic.Label;
+
+ /* Create an object to hold the ordering of row objects */
+ this._fields = new Array;
+
+ /* Create an object to hold the icon names */
+ this._icons = new Object;
+
+ /* Initially assume that indentation goes at the beginning of the row */
+ this._fields.push(this._indentObject);
+
+ /* Set initial flags */
+ this._indentAdded = false;
+ this._iconAdded = false;
+ this._labelAdded = false;
+
+ /* Return the singleton (from which we were called) */
+ return this;
+}
+
+/**
+ * Define a new row with the 'standard' structure.
+ *
+ * This reinitializes the singleton TreeRowStructure to the state of a
+ * standard'or traditional tree row:
+ * - indentation
+ * - icon
+ * - label
+ *
+ * The icon parameters may be omitted in which case the defaults will be
+ * used. If the label parameter is omitted, no label will appear.
+ *
+ * @param vLabel {string} The label text
+ * @param vIcon {string} Relative path to the 'non-selected' icon
+ * @param vIconSelected {string} Relative path to the 'selected' icon
+ *
+ * @return The singleton itself, purely for convenience.
+ */
+qx.Proto.standard = function(vLabel, vIcon, vIconSelected)
+{
+ this.newRow();
+ this.addIcon(vIcon, vIconSelected);
+ this.addLabel(vLabel);
+
+ return this;
+}
+
+qx.Proto.addIndent = function()
+{
+ /* If the assumed indent object is in use... */
+ if (! this._indentAdded)
+ {
+ /* ... then remove it. */
+ this._fields.shift();
+ this._indentAdded = true;
+ }
+ else
+ {
+ throw new Error("Indent object added more than once.");
+ }
+
+ /* Add the indentation to the structure */
+ this._fields.push(this._indentObject);
+}
+
+qx.Proto.addIcon = function(vIcon, vIconSelected)
+{
+ /* Ensure only one standard icon is added */
+ if (! this._iconAdded)
+ {
+ this._iconAdded = true;
+ }
+ else
+ {
+ throw new Error("Icon object added more than once.");
+ }
+
+ /* Track the two icon names */
+ this._icons.unselected = vIcon;
+ this._icons.selected = vIconSelected;
+
+ /* Add the icon to the structure */
+ this._fields.push(this._iconObject);
+}
+
+qx.Proto.addLabel = function(vLabel)
+{
+ /* Ensure only one standard label is added */
+ if (! this._labelAdded)
+ {
+ this._labelAdded = true;
+ }
+ else
+ {
+ throw new Error("Label added more than once.");
+ }
+
+ /* Track the label text */
+ this._label = vLabel;
+
+ /* Add the label to the structure */
+ this._fields.push(this._labelObject);
+}
+
+/*
+ * Add an object to the tree row structure. For convenience, vAnonymous can
+ * be provided, and if a boolean value is provided, vObj.setAnonymous() is
+ * called with the provided value. If the object has already been
+ * setAnonymous or if there is no need to do so, then provide no value for
+ * vAnonymous or pass 'null'.
+ */
+qx.Proto.addObject = function(vObj, vAnonymous)
+{
+ /* Is requested, set this object's anonymous state */
+ if (typeof vAnonymous == "boolean")
+ {
+ vObj.setAnonymous(vAnonymous);
+ }
+
+ /* Add this user-specified object to the structure */
+ this._fields.push(vObj);
+}
+
+
+/*
+---------------------------------------------------------------------------
+ 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/window/Window.js b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/window/Window.js
new file mode 100644
index 0000000000..3f55963727
--- /dev/null
+++ b/webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/window/Window.js
@@ -0,0 +1,1441 @@
+/* ************************************************************************
+
+ 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)
+
+************************************************************************ */
+
+qx.OO.defineClass("qx.ui.window.Window", qx.ui.popup.Popup,
+function(vCaption, vIcon, vWindowManager)
+{
+ qx.ui.popup.Popup.call(this);
+
+ // ************************************************************************
+ // FUNCTIONAL STYLE
+ // ************************************************************************
+
+ this.setMinWidth("auto");
+ this.setMinHeight("auto");
+ this.setAutoHide(false);
+
+
+
+ // ************************************************************************
+ // MANAGER
+ // ************************************************************************
+
+ // Init Focus Manager
+ this.activateFocusRoot();
+
+ // Init Window Manager
+ this.setWindowManager(vWindowManager || qx.ui.window.Window.getDefaultWindowManager());
+
+
+
+ // ************************************************************************
+ // RESIZE AND MOVE FRAME
+ // ************************************************************************
+
+ var f = this._frame = new qx.ui.basic.Terminator;
+ f.setAppearance("window-resize-frame");
+
+
+ // ************************************************************************
+ // LAYOUT
+ // ************************************************************************
+
+ var l = this._layout = new qx.ui.layout.VerticalBoxLayout;
+ l.setEdge(0);
+ this.add(l);
+
+
+ // ************************************************************************
+ // CAPTIONBAR
+ // ************************************************************************
+
+ var cb = this._captionBar = new qx.ui.layout.HorizontalBoxLayout;
+ cb.setAppearance("window-captionbar");
+ l.add(cb);
+
+
+ // ************************************************************************
+ // CAPTIONICON
+ // ************************************************************************
+
+ if (qx.util.Validation.isValidString(vIcon))
+ {
+ var ci = this._captionIcon = new qx.ui.basic.Image(vIcon);
+ ci.setAppearance("window-captionbar-icon");
+ cb.add(ci);
+ }
+
+
+ // ************************************************************************
+ // CAPTIONTITLE
+ // ************************************************************************
+
+ var ct = this._captionTitle = new qx.ui.basic.Label(vCaption);
+ ct.setAppearance("window-captionbar-title");
+ ct.setSelectable(false);
+ cb.add(ct);
+
+
+ // ************************************************************************
+ // CAPTIONFLEX
+ // ************************************************************************
+
+ var cf = this._captionFlex = new qx.ui.basic.HorizontalSpacer;
+ cb.add(cf);
+
+
+ // ************************************************************************
+ // CAPTIONBUTTONS: MINIMIZE
+ // ************************************************************************
+
+ var bm = this._minimizeButton = new qx.ui.form.Button(null, "widget/window/minimize.gif");
+
+ bm.setAppearance("window-captionbar-minimize-button");
+ bm.setTabIndex(-1);
+
+ bm.addEventListener("execute", this._onminimizebuttonclick, this);
+ bm.addEventListener("mousedown", this._onbuttonmousedown, this);
+
+ cb.add(bm);
+
+
+ // ************************************************************************
+ // CAPTIONBUTTONS: RESTORE
+ // ************************************************************************
+
+ var br = this._restoreButton = new qx.ui.form.Button(null, "widget/window/restore.gif");
+
+ br.setAppearance("window-captionbar-restore-button");
+ br.setTabIndex(-1);
+
+ br.addEventListener("execute", this._onrestorebuttonclick, this);
+ br.addEventListener("mousedown", this._onbuttonmousedown, this);
+
+ // don't add initially
+ // cb.add(br);
+
+
+ // ************************************************************************
+ // CAPTIONBUTTONS: MAXIMIZE
+ // ************************************************************************
+
+ var bx = this._maximizeButton = new qx.ui.form.Button(null, "widget/window/maximize.gif");
+
+ bx.setAppearance("window-captionbar-maximize-button");
+ bx.setTabIndex(-1);
+
+ bx.addEventListener("execute", this._onmaximizebuttonclick, this);
+ bx.addEventListener("mousedown", this._onbuttonmousedown, this);
+
+ cb.add(bx);
+
+
+ // ************************************************************************
+ // CAPTIONBUTTONS: CLOSE
+ // ************************************************************************
+
+ var bc = this._closeButton = new qx.ui.form.Button(null, "widget/window/close.gif");
+
+ bc.setAppearance("window-captionbar-close-button");
+ bc.setTabIndex(-1);
+
+ bc.addEventListener("execute", this._onclosebuttonclick, this);
+ bc.addEventListener("mousedown", this._onbuttonmousedown, this);
+
+ cb.add(bc);
+
+
+ // ************************************************************************
+ // PANE
+ // ************************************************************************
+
+ var p = this._pane = new qx.ui.layout.CanvasLayout;
+ p.setHeight("1*");
+ p.setOverflow("hidden");
+ l.add(p);
+
+
+ // ************************************************************************
+ // STATUSBAR
+ // ************************************************************************
+
+ var sb = this._statusBar = new qx.ui.layout.HorizontalBoxLayout;
+ sb.setAppearance("window-statusbar");
+
+
+ // ************************************************************************
+ // STATUSTEXT
+ // ************************************************************************
+
+ var st = this._statusText = new qx.ui.basic.Label("Ready");
+ st.setAppearance("window-statusbar-text");
+ st.setSelectable(false);
+ sb.add(st);
+
+
+ // ************************************************************************
+ // INIT
+ // ************************************************************************
+
+ this.setCaption(vCaption);
+ this.setIcon(vIcon);
+
+
+ // ************************************************************************
+ // EVENTS: WINDOW
+ // ************************************************************************
+
+ this.addEventListener("mousedown", this._onwindowmousedown, this);
+ this.addEventListener("mouseup", this._onwindowmouseup, this);
+ this.addEventListener("mousemove", this._onwindowmousemove, this);
+ this.addEventListener("click", this._onwindowclick, this);
+
+
+ // ************************************************************************
+ // EVENTS: CAPTIONBAR
+ // ************************************************************************
+
+ cb.addEventListener("mousedown", this._oncaptionmousedown, this);
+ cb.addEventListener("mouseup", this._oncaptionmouseup, this);
+ cb.addEventListener("mousemove", this._oncaptionmousemove, this);
+ cb.addEventListener("dblclick", this._oncaptiondblblick, this);
+
+
+ // ************************************************************************
+ // REMAPPING
+ // ************************************************************************
+ this.remapChildrenHandlingTo(this._pane);
+});
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ PROPERTIES
+---------------------------------------------------------------------------
+*/
+
+/*!
+ Appearance of the widget
+*/
+qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "window" });
+
+/*!
+ The windowManager to use for.
+*/
+qx.OO.addProperty({ name : "windowManager", type : "object" });
+
+/*!
+ If the window is active, only one window in a single qx.manager.object.WindowManager could
+ have set this to true at the same time.
+*/
+qx.OO.addProperty({ name : "active", type : "boolean", defaultValue : false });
+
+/*!
+ Should be window be modal (this disable minimize and maximize buttons)
+*/
+qx.OO.addProperty({ name : "modal", type : "boolean", defaultValue : false });
+
+/*!
+ Should be window be modal (this disable minimize and maximize buttons)
+*/
+qx.OO.addProperty({ name : "mode", type : "string", defaultValue : null, possibleValues : [ "minimized", "maximized" ], allowNull : true });
+
+/*!
+ The opener (button) of the window
+*/
+qx.OO.addProperty({ name : "opener", type : "object" });
+
+/*!
+ The text of the caption
+*/
+qx.OO.addProperty({ name : "caption", type : "string" });
+
+/*!
+ The icon of the caption
+*/
+qx.OO.addProperty({ name : "icon", type : "string" });
+
+/*!
+ The text of the statusbar
+*/
+qx.OO.addProperty({ name : "status", type : "string", defaultValue : "Ready" });
+
+/*!
+ Should the close button be shown
+*/
+qx.OO.addProperty({ name : "showClose", type : "boolean", defaultValue : true });
+
+/*!
+ Should the maximize button be shown
+*/
+qx.OO.addProperty({ name : "showMaximize", type : "boolean", defaultValue : true });
+
+/*!
+ Should the minimize button be shown
+*/
+qx.OO.addProperty({ name : "showMinimize", type : "boolean", defaultValue : true });
+
+/*!
+ Should the statusbar be shown
+*/
+qx.OO.addProperty({ name : "showStatusbar", type : "boolean", defaultValue : false });
+
+/*!
+ Should the user have the ability to close the window
+*/
+qx.OO.addProperty({ name : "allowClose", type : "boolean", defaultValue : true });
+
+/*!
+ Should the user have the ability to maximize the window
+*/
+qx.OO.addProperty({ name : "allowMaximize", type : "boolean", defaultValue : true });
+
+/*!
+ Should the user have the ability to minimize the window
+*/
+qx.OO.addProperty({ name : "allowMinimize", type : "boolean", defaultValue : true });
+
+/*!
+ If the text (in the captionbar) should be visible
+*/
+qx.OO.addProperty({ name : "showCaption", type : "boolean", defaultValue : true });
+
+/*!
+ If the icon (in the captionbar) should be visible
+*/
+qx.OO.addProperty({ name : "showIcon", type : "boolean", defaultValue : true });
+
+/*!
+ If the window is resizeable
+*/
+qx.OO.addProperty({ name : "resizeable", type : "boolean", defaultValue : true });
+
+/*!
+ If the window is moveable
+*/
+qx.OO.addProperty({ name : "moveable", type : "boolean", defaultValue : true });
+
+/*!
+ The resize method to use
+*/
+qx.OO.addProperty({ name : "resizeMethod", type : "string", defaultValue : "frame", possibleValues : [ "opaque", "lazyopaque", "frame", "translucent" ] });
+
+/*!
+ The move method to use
+*/
+qx.OO.addProperty({ name : "moveMethod", type : "string", defaultValue : "opaque", possibleValues : [ "opaque", "frame", "translucent" ] });
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MANAGER HANDLING
+---------------------------------------------------------------------------
+*/
+
+qx.ui.window.Window.getDefaultWindowManager = function()
+{
+ if (!qx.ui.window.Window._defaultWindowManager) {
+ qx.ui.window.Window._defaultWindowManager = new qx.manager.object.WindowManager;
+ }
+
+ return qx.ui.window.Window._defaultWindowManager;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ UTILITIES
+---------------------------------------------------------------------------
+*/
+
+qx.Proto.getPane = function() {
+ return this._pane;
+}
+
+qx.Proto.getCaptionBar = function() {
+ return this._captionBar;
+}
+
+qx.Proto.getStatusBar = function() {
+ return this._statusBar;
+}
+
+qx.Proto.close = function() {
+ this.hide();
+}
+
+qx.Proto.open = function(vOpener)
+{
+ if (qx.util.Validation.isValid(vOpener)) {
+ this.setOpener(vOpener);
+ }
+
+ if (this.getCentered()) {
+ this.centerToBrowser();
+ }
+
+ this.show();
+}
+
+qx.Proto.focus = function() {
+ this.setActive(true);
+}
+
+qx.Proto.blur = function() {
+ this.setActive(false);
+}
+
+qx.Proto.maximize = function() {
+ this.setMode("maximized");
+}
+
+qx.Proto.minimize = function() {
+ this.setMode("minimized");
+}
+
+qx.Proto.restore = function() {
+ this.setMode(null);
+}
+
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ APPEAR/DISAPPEAR
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._beforeAppear = function()
+{
+ // Intentionally bypass superclass and call super.super._beforeAppear
+ qx.ui.layout.CanvasLayout.prototype._beforeAppear.call(this);
+
+ // Hide popups
+ qx.manager.object.PopupManager.getInstance().update();
+
+ // Configure the focus root to be the current opened window
+ qx.event.handler.EventHandler.getInstance().setFocusRoot(this);
+
+ this.getWindowManager().add(this);
+ this._makeActive();
+}
+
+qx.Proto._beforeDisappear = function()
+{
+ // Intentionally bypass superclass and call super.super._beforeDisappear
+ qx.ui.layout.CanvasLayout.prototype._beforeDisappear.call(this);
+
+ // Reset focus root
+ var vFocusRoot = qx.event.handler.EventHandler.getInstance().getFocusRoot();
+ if (vFocusRoot == this || this.contains(vFocusRoot)) {
+ qx.event.handler.EventHandler.getInstance().setFocusRoot(null);
+ }
+
+ // Be sure to disable any capturing inside invisible parts
+ // Is this to much overhead?
+ // Are there any other working solutions?
+ var vWidget = qx.event.handler.EventHandler.getInstance().getCaptureWidget();
+ if (vWidget && this.contains(vWidget)) {
+ vWidget.setCapture(false);
+ }
+
+ this.getWindowManager().remove(this);
+ this._makeInactive();
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ ZIndex Positioning
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._minZIndex = 1e5;
+
+qx.Proto._sendTo = function()
+{
+ var vAll = qx.lang.Object.getValues(this.getWindowManager().getAll()).sort(qx.util.Compare.byZIndex);
+ var vLength = vAll.length;
+ var vIndex = this._minZIndex;
+
+ for (var i=0; i<vLength; i++) {
+ vAll[i].setZIndex(vIndex++);
+ }
+}
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ MODIFIERS
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._modifyActive = function(propValue, propOldValue, propData)
+{
+ if (propOldValue)
+ {
+ if (this.getFocused()) {
+ this.setFocused(false);
+ }
+
+ if (this.getWindowManager().getActiveWindow() == this) {
+ this.getWindowManager().setActiveWindow(null);
+ }
+
+ this.removeState("active");
+ this._captionBar.removeState("active");
+ }
+ else
+ {
+ // Switch focus
+ // Also do this if gets inactive as this moved the focus outline
+ // away from any focused child.
+ if (!this.getFocusedChild()) {
+ this.setFocused(true);
+ }
+
+ this.getWindowManager().setActiveWindow(this);
+ this.bringToFront();
+
+ this.addState("active");
+ this._captionBar.addState("active");
+ }
+
+ return true;
+}
+
+qx.Proto._modifyModal = function(propValue, propOldValue, propData)
+{
+ // Inform blocker
+ if (this._initialLayoutDone && this.getVisibility() && this.getDisplay())
+ {
+ var vTop = this.getTopLevelWidget();
+ propValue ? vTop.block(this) : vTop.release(this);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyAllowClose = function(propValue, propOldValue, propData) {
+ return this._closeButtonManager();
+}
+
+qx.Proto._modifyAllowMaximize = function(propValue, propOldValue, propData) {
+ return this._maximizeButtonManager();
+}
+
+qx.Proto._modifyAllowMinimize = function(propValue, propOldValue, propData) {
+ return this._minimizeButtonManager();
+}
+
+qx.Proto._modifyMode = function(propValue, propOldValue, propData)
+{
+ switch(propValue)
+ {
+ case "minimized":
+ this._minimize();
+ break;
+
+ case "maximized":
+ this._maximize();
+ break;
+
+ default:
+ switch(propOldValue)
+ {
+ case "maximized":
+ this._restoreFromMaximized();
+ break;
+
+ case "minimized":
+ this._restoreFromMinimized();
+ break;
+ }
+ }
+
+ return true;
+}
+
+qx.Proto._modifyShowCaption = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ this._captionBar.addAt(this._captionTitle, this.getShowIcon() ? 1 : 0);
+ }
+ else
+ {
+ this._captionBar.remove(this._captionTitle);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyShowIcon = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ this._captionBar.addAtBegin(this._captionIcon);
+ }
+ else
+ {
+ this._captionBar.remove(this._captionIcon);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyShowStatusbar = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ this._layout.addAtEnd(this._statusBar);
+ }
+ else
+ {
+ this._layout.remove(this._statusBar);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyShowClose = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ this._captionBar.addAtEnd(this._closeButton);
+ }
+ else
+ {
+ this._captionBar.remove(this._closeButton);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyShowMaximize = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ var t = this.getMode() == "maximized" ? this._restoreButton : this._maximizeButton;
+
+ if (this.getShowMinimize())
+ {
+ this._captionBar.addAfter(t, this._minimizeButton);
+ }
+ else
+ {
+ this._captionBar.addAfter(t, this._captionFlex);
+ }
+ }
+ else
+ {
+ this._captionBar.remove(this._maximizeButton);
+ this._captionBar.remove(this._restoreButton);
+ }
+
+ return true;
+}
+
+qx.Proto._modifyShowMinimize = function(propValue, propOldValue, propData)
+{
+ if (propValue)
+ {
+ this._captionBar.addAfter(this._minimizeButton, this._captionFlex);
+ }
+ else
+ {
+ this._captionBar.remove(this._minimizeButton);
+ }
+
+ return true;
+}
+
+qx.Proto._minimizeButtonManager = function()
+{
+ this._minimizeButton.setEnabled(this.getAllowMinimize());
+
+ return true;
+}
+
+qx.Proto._closeButtonManager = function()
+{
+ this._closeButton.setEnabled(this.getAllowClose());
+
+ return true;
+}
+
+qx.Proto._maximizeButtonManager = function()
+{
+ var b = this.getAllowMaximize() && this.getResizeable() && this._computedMaxWidthTypeNull && this._computedMaxHeightTypeNull;
+
+ this._maximizeButton.setEnabled(b);
+ this._restoreButton.setEnabled(b);
+
+ return true;
+}
+
+qx.Proto._modifyStatus = function(propValue, propOldValue, propData)
+{
+ this._statusText.setHtml(propValue);
+
+ return true;
+}
+
+qx.Proto._modifyMaxWidth = function(propValue, propOldValue, propData) {
+ return this._maximizeButtonManager();
+}
+
+qx.Proto._modifyMaxHeight = function(propValue, propOldValue, propData) {
+ return this._maximizeButtonManager();
+}
+
+qx.Proto._modifyResizeable = function(propValue, propOldValue, propData) {
+ return this._maximizeButtonManager();
+}
+
+qx.Proto._modifyCaption = function(propValue, propOldValue, propData)
+{
+ this._captionTitle.setHtml(propValue);
+ return true;
+}
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ STATE LAYOUT IMPLEMENTATION
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._minimize = function()
+{
+ this.blur();
+ this.hide();
+}
+
+qx.Proto._restoreFromMaximized = function()
+{
+ // restore previous dimension and location
+ this.setLeft(this._previousLeft ? this._previousLeft : null);
+ this.setWidth(this._previousWidth ? this._previousWidth : null);
+ this.setRight(this._previousRight ? this._previousRight : null);
+
+ this.setTop(this._previousTop ? this._previousTop : null);
+ this.setHeight(this._previousHeight ? this._previousHeight : null);
+ this.setBottom(this._previousBottom ? this._previousBottom : null);
+
+ // update state
+ this.removeState("maximized");
+
+ // toggle button
+ if (this.getShowMaximize())
+ {
+ var cb = this._captionBar;
+ var v = cb.indexOf(this._restoreButton);
+
+ cb.remove(this._restoreButton);
+ cb.addAt(this._maximizeButton, v);
+ }
+
+ // finally focus the window
+ this.focus();
+}
+
+qx.Proto._restoreFromMinimized = function()
+{
+ if (this.hasState("maximized"))
+ {
+ this.setMode("maximized");
+ }
+
+ this.show();
+ this.focus();
+}
+
+qx.Proto._maximize = function()
+{
+ if (this.hasState("maximized"))
+ {
+ return;
+ }
+
+ // store current dimension and location
+ this._previousLeft = this.getLeft();
+ this._previousWidth = this.getWidth();
+ this._previousRight = this.getRight();
+ this._previousTop = this.getTop();
+ this._previousHeight = this.getHeight();
+ this._previousBottom = this.getBottom();
+
+ // setup new dimension and location
+ this.setWidth(null);
+ this.setLeft(0);
+ this.setRight(0);
+ this.setHeight(null);
+ this.setTop(0);
+ this.setBottom(0);
+
+ // update state
+ this.addState("maximized");
+
+ // toggle button
+ if (this.getShowMaximize())
+ {
+ var cb = this._captionBar;
+ var v = cb.indexOf(this._maximizeButton);
+
+ cb.remove(this._maximizeButton);
+ cb.addAt(this._restoreButton, v);
+ }
+
+ // finally focus the window
+ this.focus();
+}
+
+
+
+
+
+
+
+/*
+---------------------------------------------------------------------------
+ EVENTS: WINDOW
+---------------------------------------------------------------------------
+*/
+
+qx.Proto._onwindowmousedown = function(e)
+{
+ this.focus();
+
+ if (this._resizeNorth || this._resizeSouth || this._resizeWest || this._resizeEast)
+ {
+ // enable capturing
+ this.setCapture(true);
+
+ // activate global cursor
+ this.getTopLevelWidget().setGlobalCursor(this.getCursor());
+
+ // caching element
+ var el = this.getElement();
+
+ // measuring and caching of values for resize 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);
+
+ // handle frame and translucently
+ switch(this.getResizeMethod())
+ {
+ 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;
+ }
+
+ // create resize session
+ var s = this._resizeSession = {};
+
+ if (this._resizeWest)
+ {
+ s.boxWidth = qx.dom.Dimension.getBoxWidth(el);
+ s.boxRight = qx.dom.Location.getPageBoxRight(el);
+ }
+
+ if (this._resizeWest || this._resizeEast)
+ {
+ s.boxLeft = qx.dom.Location.getPageBoxLeft(el);
+
+ s.parentAreaOffsetLeft = l;
+ s.parentAreaOffsetRight = r;
+
+ s.minWidth = this.getMinWidthValue();
+ s.maxWidth = this.getMaxWidthValue();
+ }
+
+ if (this._resizeNorth)
+ {
+ s.boxHeight = qx.dom.Dimension.getBoxHeight(el);
+ s.boxBottom = qx.dom.Location.getPageBoxBottom(el);
+ }
+
+ if (this._resizeNorth || this._resizeSouth)
+ {
+ s.boxTop = qx.dom.Location.getPageBoxTop(el);
+
+ s.parentAreaOffsetTop = t;
+ s.parentAreaOffsetBottom = b;
+
+ s.minHeight = this.getMinHeightValue();
+ s.maxHeight = this.getMaxHeightValue();
+ }
+ }
+ else
+ {
+ // cleanup resize session
+ delete this._resizeSession;
+ }
+
+ // stop event
+ e.stopPropagation();
+}
+
+qx.Proto._onwindowmouseup = function(e)
+{
+ var s = this._resizeSession;
+
+ if (s)
+ {
+ // disable capturing
+ this.setCapture(false);
+
+ // deactivate global cursor
+ this.getTopLevelWidget().setGlobalCursor(null);
+
+ // sync sizes to frame
+ switch(this.getResizeMethod())
+ {
+ case "frame":
+ var o = this._frame;
+ if (!(o && o.getParent())) {
+ break;
+ }
+ // no break here
+
+ case "lazyopaque":
+ if (qx.util.Validation.isValidNumber(s.lastLeft)) {
+ this.setLeft(s.lastLeft);
+ }
+
+ if (qx.util.Validation.isValidNumber(s.lastTop)) {
+ this.setTop(s.lastTop);
+ }
+
+ if (qx.util.Validation.isValidNumber(s.lastWidth)) {
+ this.setWidth(s.lastWidth);
+ }
+
+ if (qx.util.Validation.isValidNumber(s.lastHeight)) {
+ this.setHeight(s.lastHeight);
+ }
+
+ if (this.getResizeMethod() == "frame") {
+ this._frame.setParent(null);
+ }
+ break;
+
+ case "translucent":
+ this.setOpacity(null);
+ break;
+ }
+
+ // cleanup session
+ delete this._resizeNorth;
+ delete this._resizeEast;
+ delete this._resizeSouth;
+ delete this._resizeWest;
+
+ delete this._resizeSession;
+ }
+
+ // stop event
+ e.stopPropagation();
+}
+
+qx.Proto._near = function(p, e) {
+ return e > (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);
+}