diff options
Diffstat (limited to 'webapps/qooxdoo-0.6.3-sdk/frontend/framework/source/class/qx/ui/form')
13 files changed, 4488 insertions, 0 deletions
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); +} |