1 /* ************************************************************************
3 qooxdoo - the new era of web development
8 2004-2007 1&1 Internet AG, Germany, http://www.1and1.org
11 LGPL: http://www.gnu.org/licenses/lgpl.html
12 EPL: http://www.eclipse.org/org/documents/epl-v10.php
13 See the LICENSE file in the project's top-level directory for details.
16 * Sebastian Werner (wpbasti)
17 * Andreas Ecker (ecker)
19 ************************************************************************ */
21 /* ************************************************************************
24 #embed(qx.widgettheme/arrows/up_small.gif)
25 #embed(qx.widgettheme/arrows/down_small.gif)
27 ************************************************************************ */
30 * @event change {qx.event.type.Event}
32 qx.OO.defineClass("qx.ui.form.Spinner", qx.ui.layout.HorizontalBoxLayout,
33 function(vMin, vValue, vMax)
35 qx.ui.layout.HorizontalBoxLayout.call(this);
37 // ************************************************************************
39 // ************************************************************************
42 if (qx.core.Client.getInstance().isMshtml()) {
43 this.setStyleProperty("fontSize", "0px");
47 // ************************************************************************
49 // ************************************************************************
50 this._manager = new qx.type.Range();
53 // ************************************************************************
55 // ************************************************************************
56 this._textfield = new qx.ui.form.TextField;
57 this._textfield.setAppearance("spinner-field");
58 this._textfield.setValue(String(this._manager.getValue()));
60 this.add(this._textfield);
63 // ************************************************************************
65 // ************************************************************************
66 this._buttonlayout = new qx.ui.layout.VerticalBoxLayout;
67 this._buttonlayout.setWidth("auto");
68 this.add(this._buttonlayout);
71 // ************************************************************************
73 // ************************************************************************
74 this._upbutton = new qx.ui.basic.Image("widget/arrows/up_small.gif");
75 this._upbutton.setAppearance("spinner-button-up");
76 this._buttonlayout.add(this._upbutton);
79 // ************************************************************************
81 // ************************************************************************
82 this._downbutton = new qx.ui.basic.Image("widget/arrows/down_small.gif");
83 this._downbutton.setAppearance("spinner-button-down");
84 this._buttonlayout.add(this._downbutton);
87 // ************************************************************************
89 // ************************************************************************
90 this._timer = new qx.client.Timer(this.getInterval());
93 // ************************************************************************
95 // ************************************************************************
96 this.addEventListener("keypress", this._onkeypress, this);
97 this.addEventListener("keydown", this._onkeydown, this);
98 this.addEventListener("keyup", this._onkeyup, this);
99 this.addEventListener("mousewheel", this._onmousewheel, this);
101 this._textfield.addEventListener("input", this._oninput, this);
102 this._textfield.addEventListener("blur", this._onblur, this);
103 this._upbutton.addEventListener("mousedown", this._onmousedown, this);
104 this._downbutton.addEventListener("mousedown", this._onmousedown, this);
105 this._manager.addEventListener("change", this._onchange, this);
106 this._timer.addEventListener("interval", this._oninterval, this);
109 // ************************************************************************
111 // ************************************************************************
122 this.setValue(vValue);
129 ---------------------------------------------------------------------------
131 ---------------------------------------------------------------------------
134 qx.OO.changeProperty({ name : "appearance", type : "string", defaultValue : "spinner" });
137 The amount to increment on each event (keypress or mousedown).
139 qx.OO.addProperty({ name : "incrementAmount", type : "number", defaultValue : 1 });
142 The amount to increment on each event (keypress or mousedown).
144 qx.OO.addProperty({ name : "wheelIncrementAmount", type : "number", defaultValue : 1 });
147 The amount to increment on each pageup / pagedown keypress
149 qx.OO.addProperty({ name : "pageIncrementAmount", type : "number", defaultValue : 10 });
152 The current value of the interval (this should be used internally only).
154 qx.OO.addProperty({ name : "interval", type : "number", defaultValue : 100 });
157 The first interval on event based shrink/growth of the value.
159 qx.OO.addProperty({ name : "firstInterval", type : "number", defaultValue : 500 });
162 This configures the minimum value for the timer interval.
164 qx.OO.addProperty({ name : "minTimer", type : "number", defaultValue : 20 });
167 Decrease of the timer on each interval (for the next interval) until minTimer reached.
169 qx.OO.addProperty({ name : "timerDecrease", type : "number", defaultValue : 2 });
172 If minTimer was reached, how much the amount of each interval should growth (in relation to the previous interval).
174 qx.OO.addProperty({ name : "amountGrowth", type : "number", defaultValue : 1.01 });
177 qx.Proto._modifyIncrementAmount = function(propValue, propOldValue, propData)
179 this._computedIncrementAmount = propValue;
188 ---------------------------------------------------------------------------
190 ---------------------------------------------------------------------------
193 qx.Proto._computePreferredInnerWidth = function() {
197 qx.Proto._computePreferredInnerHeight = function() {
206 ---------------------------------------------------------------------------
208 ---------------------------------------------------------------------------
211 qx.Proto._onkeypress = function(e)
213 var vIdentifier = e.getKeyIdentifier();
215 if (vIdentifier == "Enter" && !e.isAltPressed())
217 this._checkValue(true, false, false);
218 this._textfield.selectAll();
251 if (vIdentifier >= "0" && vIdentifier <= "9") {
260 qx.Proto._onkeydown = function(e)
262 var vIdentifier = e.getKeyIdentifier();
264 if (this._intervalIncrease == null)
270 this._intervalIncrease = vIdentifier == "Up";
271 this._intervalMode = "single";
273 this._resetIncrements();
274 this._checkValue(true, false, false);
277 this._timer.startWith(this.getFirstInterval());
283 this._intervalIncrease = vIdentifier == "PageUp";
284 this._intervalMode = "page";
286 this._resetIncrements();
287 this._checkValue(true, false, false);
289 this._pageIncrement();
290 this._timer.startWith(this.getFirstInterval());
297 qx.Proto._onkeyup = function(e)
299 if (this._intervalIncrease != null)
301 switch(e.getKeyIdentifier())
309 this._intervalIncrease = null;
310 this._intervalMode = null;
320 ---------------------------------------------------------------------------
322 ---------------------------------------------------------------------------
325 qx.Proto._onmousedown = function(e)
327 if (!e.isLeftButtonPressed()) {
331 this._checkValue(true);
333 var vButton = e.getCurrentTarget();
335 vButton.addState("pressed");
337 vButton.addEventListener("mouseup", this._onmouseup, this);
338 vButton.addEventListener("mouseout", this._onmouseup, this);
340 this._intervalIncrease = vButton == this._upbutton;
341 this._resetIncrements();
344 this._textfield.selectAll();
346 this._timer.setInterval(this.getFirstInterval());
350 qx.Proto._onmouseup = function(e)
352 var vButton = e.getCurrentTarget();
354 vButton.removeState("pressed");
356 vButton.removeEventListener("mouseup", this._onmouseup, this);
357 vButton.removeEventListener("mouseout", this._onmouseup, this);
359 this._textfield.selectAll();
360 this._textfield.setFocused(true);
363 this._intervalIncrease = null;
366 qx.Proto._onmousewheel = function(e)
368 this._manager.setValue(this._manager.getValue() + this.getWheelIncrementAmount() * e.getWheelDelta());
369 this._textfield.selectAll();
376 ---------------------------------------------------------------------------
378 ---------------------------------------------------------------------------
381 qx.Proto._oninput = function(e) {
382 this._checkValue(true, true);
385 qx.Proto._onchange = function(e)
387 var vValue = this._manager.getValue();
389 this._textfield.setValue(String(vValue));
391 if (vValue == this.getMin())
393 this._downbutton.removeState("pressed");
394 this._downbutton.setEnabled(false);
399 this._downbutton.setEnabled(true);
402 if (vValue == this.getMax())
404 this._upbutton.removeState("pressed");
405 this._upbutton.setEnabled(false);
410 this._upbutton.setEnabled(true);
413 if (this.hasEventListeners("change")) {
414 this.dispatchEvent(new qx.event.type.Event("change"), true);
418 qx.Proto._onblur = function(e) {
419 this._checkValue(false);
428 ---------------------------------------------------------------------------
429 MAPPING TO RANGE MANAGER
430 ---------------------------------------------------------------------------
433 qx.Proto.setValue = function(nValue) {
434 this._manager.setValue(nValue);
437 qx.Proto.getValue = function() {
438 this._checkValue(true);
439 return this._manager.getValue();
442 qx.Proto.resetValue = function() {
443 return this._manager.resetValue();
446 qx.Proto.setMax = function(vMax) {
447 return this._manager.setMax(vMax);
450 qx.Proto.getMax = function() {
451 return this._manager.getMax();
454 qx.Proto.setMin = function(vMin) {
455 return this._manager.setMin(vMin);
458 qx.Proto.getMin = function() {
459 return this._manager.getMin();
471 ---------------------------------------------------------------------------
473 ---------------------------------------------------------------------------
476 qx.Proto._intervalIncrease = null;
478 qx.Proto._oninterval = function(e)
481 this.setInterval(Math.max(this.getMinTimer(), this.getInterval()-this.getTimerDecrease()));
483 if (this._intervalMode == "page")
485 this._pageIncrement();
489 if (this.getInterval() == this.getMinTimer()) {
490 this._computedIncrementAmount = this.getAmountGrowth() * this._computedIncrementAmount;
496 switch(this._intervalIncrease)
499 if (this.getValue() == this.getMax()) {
504 if (this.getValue() == this.getMin()) {
509 this._timer.restartWith(this.getInterval());
517 ---------------------------------------------------------------------------
519 ---------------------------------------------------------------------------
522 qx.Proto._checkValue = function(acceptEmpty, acceptEdit)
524 var el = this._textfield.getElement();
534 el.value = this.resetValue();
535 this._textfield.selectAll();
542 // cache working variable
548 while(val.charAt(0) == "0") {
549 val = val.substr(1, val.length);
552 var f1 = parseInt(val) || 0;
554 if (f1 != el.value) {
560 // fix for negative integer handling
561 if (val == "-" && acceptEmpty && this.getMin() < 0)
563 if (el.value != val) {
573 // main check routine
575 var fixedVal = this._manager._checkValue(val);
577 if (isNaN(fixedVal)) {
578 fixedVal = this._manager.getValue();
581 // handle empty string
582 if (acceptEmpty && val == "")
586 else if (!isNaN(val))
588 // check for editmode in keypress events
591 // fix min/max values
592 if (val > fixedVal && !(val > 0 && fixedVal <= 0) && String(val).length < String(fixedVal).length)
596 else if (val < fixedVal && !(val < 0 && fixedVal >= 0) && String(val).length < String(fixedVal).length)
604 if (doFix && el.value != fixedVal) {
610 this._manager.setValue(fixedVal);
615 qx.Proto._increment = function() {
616 this._manager.setValue(this._manager.getValue() + ((this._intervalIncrease ? 1 : - 1) * this._computedIncrementAmount));
619 qx.Proto._pageIncrement = function() {
620 this._manager.setValue(this._manager.getValue() + ((this._intervalIncrease ? 1 : - 1) * this.getPageIncrementAmount()));
623 qx.Proto._resetIncrements = function()
625 this._computedIncrementAmount = this.getIncrementAmount();
626 this.resetInterval();
634 ---------------------------------------------------------------------------
636 ---------------------------------------------------------------------------
639 qx.Proto.dispose = function()
641 if (this.getDisposed()) {
645 this.removeEventListener("keypress", this._onkeypress, this);
646 this.removeEventListener("keydown", this._onkeydown, this);
647 this.removeEventListener("keyup", this._onkeyup, this);
648 this.removeEventListener("mousewheel", this._onmousewheel, this);
652 this._textfield.removeEventListener("blur", this._onblur, this);
653 this._textfield.removeEventListener("input", this._oninput, this);
654 this._textfield.dispose();
655 this._textfield = null;
658 if (this._buttonlayout)
660 this._buttonlayout.dispose();
661 this._buttonlayout = null;
666 this._upbutton.removeEventListener("mousedown", this._onmousedown, this);
667 this._upbutton.dispose();
668 this._upbutton = null;
671 if (this._downbutton)
673 this._downbutton.removeEventListener("mousedown", this._onmousedown, this);
674 this._downbutton.dispose();
675 this._downbutton = null;
680 this._timer.removeEventListener("interval", this._oninterval, this);
682 this._timer.dispose();
688 this._manager.removeEventListener("change", this._onchange, this);
689 this._manager.dispose();
690 this._manager = null;
693 return qx.ui.layout.HorizontalBoxLayout.prototype.dispose.call(this);