Closed Bug 352462 Opened 18 years ago Closed 18 years ago

refactor range to provide common binding

Categories

(Core Graveyard :: XForms, defect)

defect
Not set
normal

Tracking

(Not tracked)

RESOLVED FIXED

People

(Reporter: surkov, Assigned: surkov)

References

Details

(Keywords: fixed1.8.0.8, fixed1.8.1.1)

Attachments

(1 file, 2 obsolete files)

Marking blocked by bug 331987 to keep the things separetely I guess it allows to make patch easier for review.
Attached patch patch (obsolete) — Splinter Review
Attachment #238778 - Flags: review?(doronr)
Status: NEW → ASSIGNED
Attached patch patch2 (obsolete) — Splinter Review
Forgot to add new file to previous patch.
Attachment #238778 - Attachment is obsolete: true
Attachment #238779 - Flags: review?(doronr)
Attachment #238778 - Flags: review?(doronr)
Comment on attachment 238779 [details] [diff] [review]
patch2

>Index: extensions/xforms/jar.mn
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/jar.mn,v
>retrieving revision 1.21
>diff -u -8 -p -r1.21 jar.mn
>--- extensions/xforms/jar.mn	30 Aug 2006 15:41:29 -0000	1.21
>+++ extensions/xforms/jar.mn	16 Sep 2006 12:19:30 -0000
>@@ -17,16 +17,17 @@ xforms.jar:
>   content/xforms/xforms.xml                    (resources/content/xforms.xml)
>   content/xforms/xforms-xhtml.xml              (resources/content/xforms-xhtml.xml)
>   content/xforms/xforms-xul.xml                (resources/content/xforms-xul.xml)
>   content/xforms/input.xml                     (resources/content/input.xml)
>   content/xforms/input-xhtml.xml               (resources/content/input-xhtml.xml)
>   content/xforms/input-xul.xml                 (resources/content/input-xul.xml)
>   content/xforms/select1.xml                   (resources/content/select1.xml)
>   content/xforms/range.xml                     (resources/content/range.xml)
>+  content/xforms/range-xhtml.xml               (resources/content/range-xhtml.xml)
>   content/xforms/select.xml                    (resources/content/select.xml)
>   content/xforms/select-xhtml.xml              (resources/content/select-xhtml.xml)
>   content/xforms/select-xul.xml                (resources/content/select-xul.xml)
>   content/xforms/bindingex.css                 (resources/content/bindingex.css)
>   content/xforms/bindingex.xul                 (resources/content/bindingex.xul)
>   content/xforms/calendar.png                  (resources/content/calendar.png)
> * locale/en-US/xforms/contents.rdf             (resources/locale/en-US/contents.rdf)
>   locale/en-US/xforms/xforms.properties        (resources/locale/en-US/xforms.properties)
>Index: extensions/xforms/resources/content/range-xhtml.xml
>===================================================================
>RCS file: extensions/xforms/resources/content/range-xhtml.xml
>diff -N extensions/xforms/resources/content/range-xhtml.xml
>--- /dev/null	1 Jan 1970 00:00:00 -0000
>+++ extensions/xforms/resources/content/range-xhtml.xml	16 Sep 2006 12:19:31 -0000
>@@ -0,0 +1,99 @@
>+<?xml version="1.0" encoding="utf-8"?>
>+
>+<!-- ***** BEGIN LICENSE BLOCK *****
>+   - Version: MPL 1.1/GPL 2.0/LGPL 2.1
>+   -
>+   - The contents of this file are subject to the Mozilla Public License Version
>+   - 1.1 (the "License"); you may not use this file except in compliance with
>+   - the License. You may obtain a copy of the License at
>+   - http://www.mozilla.org/MPL/
>+   -
>+   - Software distributed under the License is distributed on an "AS IS" basis,
>+   - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
>+   - for the specific language governing rights and limitations under the
>+   - License.
>+   -
>+   - The Original Code is Mozilla XForms support.
>+   -
>+   - The Initial Developer of the Original Code is
>+   - Alexander Surkov.
>+   - Portions created by the Initial Developer are Copyright (C) 2006
>+   - the Initial Developer. All Rights Reserved.
>+   -
>+   - Contributor(s):
>+   -  Alexander Surkov <surkov.alexander@gmail.com> (original author)
>+   -
>+   - Alternatively, the contents of this file may be used under the terms of
>+   - either the GNU General Public License Version 2 or later (the "GPL"), or
>+   - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
>+   - in which case the provisions of the GPL or the LGPL are applicable instead
>+   - of those above. If you wish to allow use of your version of this file only
>+   - under the terms of either the GPL or the LGPL, and not to allow others to
>+   - use your version of this file under the terms of the MPL, indicate your
>+   - decision by deleting the provisions above and replace them with the notice
>+   - and other provisions required by the GPL or the LGPL. If you do not delete
>+   - the provisions above, a recipient may use your version of this file under
>+   - the terms of any one of the MPL, the GPL or the LGPL.
>+   -
>+   - ***** END LICENSE BLOCK ***** -->
>+
>+<bindings xmlns="http://www.mozilla.org/xbl"
>+          xmlns:xbl="http://www.mozilla.org/xbl"
>+          xmlns:html="http://www.w3.org/1999/xhtml"
>+          xmlns:mozType="http://www.mozilla.org/projects/xforms/2005/type">
>+
>+  <!-- The file contains implementations of xforms range element for xhtml
>+    context. All xforms range bindings should be extended from
>+    'xformswidget-range-base' binding declared in 'range.xml' file.
>+  -->
>+
>+  <!-- RANGE: <NUMBER> -->
>+  <binding id="xformswidget-range"
>+           extends="chrome://xforms/content/range.xml#xformswidget-range-base">
>+
>+    <content mozType:deferredrefresh="true">
>+      <children includes="label"/>
>+      <html:span mozType:slider="true" anonid="slider"
>+                 xbl:inherits="min=start,max=end,step=step"/>
>+      <children/>
>+    </content>
>+
>+    <implementation>
>+      <method name="getControlElement">
>+        <body>
>+          return {
>+            __proto__: this.ownerDocument.
>+              getAnonymousElementByAttribute(this, "anonid", "slider"),
>+
>+            set readonly() {
>+              // XXX: bug 343523
>+            },
>+            get start() {
>+              return this.min;
>+            },
>+            set start(aValue) {
>+              this.min = aValue;
>+            },
>+            get end() {
>+              return this.max;
>+            },
>+            set end(aValue) {
>+              this.max = aValue;
>+            }
>+          };
>+        </body>
>+      </method>
>+
>+      <constructor>
>+        // Call widgetAttached() after timeout to let slider widget to be
>+        // loaded.
>+        this.ownerDocument.defaultView.setTimeout(
>+          function(aDelegate)
>+          {
>+            aDelegate.widgetAttached();
>+          }, 0, this.delegate);
>+      </constructor>
>+    </implementation>
>+  </binding>
>+
>+</bindings>
>Index: extensions/xforms/resources/content/range.xml
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/range.xml,v
>retrieving revision 1.5
>diff -u -8 -p -r1.5 range.xml
>--- extensions/xforms/resources/content/range.xml	21 Aug 2006 21:24:08 -0000	1.5
>+++ extensions/xforms/resources/content/range.xml	16 Sep 2006 12:19:31 -0000
>@@ -16,502 +16,124 @@
>    -
>    - The Initial Developer of the Original Code is
>    - Novell, Inc.
>    - Portions created by the Initial Developer are Copyright (C) 2005
>    - the Initial Developer. All Rights Reserved.
>    -
>    - Contributor(s):
>    -  Allan Beaufour <abeaufour@novell.com>
>+   -  Alexander Surkov <surkov.alexander@gmail.com>
>    -
>    - Alternatively, the contents of this file may be used under the terms of
>    - either the GNU General Public License Version 2 or later (the "GPL"), or
>    - the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
>    - in which case the provisions of the GPL or the LGPL are applicable instead
>    - of those above. If you wish to allow use of your version of this file only
>    - under the terms of either the GPL or the LGPL, and not to allow others to
>    - use your version of this file under the terms of the MPL, indicate your
>    - decision by deleting the provisions above and replace them with the notice
>    - and other provisions required by the GPL or the LGPL. If you do not delete
>    - the provisions above, a recipient may use your version of this file under
>    - the terms of any one of the MPL, the GPL or the LGPL.
>    -
>    - ***** END LICENSE BLOCK ***** -->
> 
>-<!--
>-   ASSUMPTIONS:
>-   *> @begin is valid, @end and @init value might not be
>-      this means that steps and ticks are calculated with begin as starting point
>-   *> Takes integers and floats
>-
>-   TODO: XXX
>-   *> limit amount of ticks
>-   *> handle undefined begin / end
>-   *> handle end < begin (including negative steps)
>-   *> @incremental should round if it is bound to integer
>-
>-   BUGS: XXX
>-   *> leaves a trace behind, hor.bar gets darker, etc... fix transparency
>--->
>-
> <bindings xmlns="http://www.mozilla.org/xbl"
>           xmlns:html="http://www.w3.org/1999/xhtml">
>-      
>-  <binding id="xformswidget-range"
>-           extends="chrome://xforms/content/xforms.xml#xformswidget-base">
>-    <content>
>-      <children includes="label"/>
>-      <html:span anonid="labelBegin" style="margin-right: 3px;"></html:span>
>-      <!-- width and height set by CSS? -->
>-      <html:canvas tabindex="0" anonid="canvas" width="260" height="40"
>-                   class="xf-value"
>-                   onkeydown="this.parentNode.handleKey(event)"
>-                   onmousedown="this.parentNode.handleMouseDown(event)"
>-                   onmouseup="this.parentNode.handleMouseUp(event)"
>-                   onmouseout="this.parentNode.handleMouseOut(event)"
>-                   onmousemove="this.parentNode.handleMouseMove(event)">
>-      </html:canvas>
>-      <html:span anonid="labelEnd" style="margin-left: 3px;"> </html:span>
>-      <children/>
>-    </content>
>-
>-    <implementation implements="nsIXFormsUIWidget">
>-      <!-- The "skin", should be set via CSS -->
>-      <field name="strokeStyle" readonly="true">"#8f9ca4"</field>
>-      <field name="strokeStyleMove" readonly="true">"red"</field>
>-      <field name="fillStyle" readonly="true">"#eff3f1"</field>
>-
>-      <!-- Is the range initialized -->
>-      <field name="isInitialized">false</field>
>-
>-      <!-- out of range -->
>-      <field name="outOfRange">false</field>
>-
>-      <!-- are we currently moving the slider? -->
>-      <field name="isMoving">false</field>
>-
>-      <!-- creates the sliderpath -->
>-      <method name="sliderPath">
>-        <parameter name="aPos"/>
>-        <body>
>-          this.ctx.beginPath();
>-          var h = this.height - this.tickheight;
>-          this.ctx.moveTo(aPos, h);
>-          this.ctx.lineTo(aPos - this.sliderwidth, h - this.slidertip);
>-          this.ctx.lineTo(aPos - this.sliderwidth, this.tickheight);
>-          this.ctx.lineTo(aPos + this.sliderwidth, this.tickheight);
>-          this.ctx.lineTo(aPos + this.sliderwidth, h - this.slidertip);
>-          this.ctx.closePath();
>-        </body>
>-      </method>
>-
>-      <!-- creates the sliderpath -->
>-      <method name="drawSlider">
>-        <parameter name="aPos"/>
>-        <parameter name="aMove"/>
>-        <body>
>-          this.ctx.save();
>-
>-          // do path
>-          this.ctx.lineWidth = 1;
>-          this.sliderPath(aPos);
>-          this.ctx.strokeStyle = aMove ? this.strokeStyleMove : this.strokeStyle;
>-          this.ctx.stroke();
>-          this.sliderPath(aPos);
>-          this.ctx.fillStyle = this.fillStyle;
>-          this.ctx.fill();
>-          
>-          this.ctx.restore();
>-        </body>
>-      </method>
>-
>-      <!-- takes a value and calculates the x position -->
>-      <method name="calcPos">
>-        <parameter name="val"/>
>-        <body>
>-          var pos = val - this.rBegin;
>-          if (this.rStep) {
>-            pos = (pos / this.rStep) * this.stepsp;
>-          } else {
>-            pos = (pos / (this.rEnd - this.rBegin)) * this.barwidth;
>-          }
>-          return Math.round(pos) + this.margin;
>-        </body>
>-      </method>
>-
>-      <!-- sets the slider to a new value -->
>-      <method name="setSlider">
>-        <!-- The new value -->
>-        <parameter name="aVal"/>
>-        <!-- The mode:
>-             - move: just moving the slider around, not setting the value
>-
>-             - set: enforce slider position from instance data,
>-                    ie. do not correct it to fit a step, etc.
>-
>-             - [default]: set the slider to the given value, adjusting it
>-                          to fit inside the allowed range
>-        -->
>-        <parameter name="aMode"/>
>-
>-        <body>
>-          <![CDATA[
>-
>-          aVal = parseFloat(aVal);
>-          if (aMode != "set" && isNaN(aVal)) {
>-            return this.delegate.reportError("rangeSetSliderNaN");
>-          }
>-
>-          if (this.isIncremental && aMode == "move") {
>-            // Incremental moves are actually sets.
>-            aMode = "set";
>-          }
>-
>-          var outOfRange = false;
>-          if (aMode != "move") {
>-            if (aMode == "set" && 
>-                (isNaN(aVal) || aVal > this.adjEnd || aVal < this.rBegin)) {
>-              outOfRange = true;
>-            } else {
>-              if (this.rStep) {
>-                // adjust aVal to limits
>-                valmod = (aVal - this.rBegin) % this.rStep;
>-                if (valmod) {
>-                  if (aMode == "set") {
>-                    outOfRange = true;
>-                  } else if (valmod < (this.rStep / 2)) {
>-                    aVal -= valmod;
>-                  } else {
>-                    aVal += this.rStep - valmod;
>-                  }
>-                }
>-              }
>-              if (aVal > this.adjEnd) {
>-                aVal = this.adjEnd;
>-              } else if (aVal < this.rBegin) {
>-                aVal = this.rBegin;
>-              }
>-            }
>-          }
>-
>-          if (!outOfRange && (aMode != "move" || this.isIncremental)) {
>-            // Store new value
>-            this.accessors.setValue(aVal);
>-          }
> 
>-          if (this.rVal == aVal && !this.justMoved) {
>-            // slider is already drawn at correct position
>-            return;
>-          }
>-
>-          this.ctx.save();
>-
>-          // clear old slider
>-          this.ctx.clearRect(this.calcPos(this.rVal) - this.sliderwidth - 1, this.tickheight - 1,
>-                             this.sliderwidth * 2 + 2, this.tickheight * 3 + 2);
>-
>-          // (re)draw horisontal bar
>-          this.ctx.lineWidth = 1;
>-          this.ctx.fillStyle = this.fillStyle;
>-          this.ctx.strokeStyle = this.strokeStyle;
>-          mid = Math.round(this.height / 2);
>-          // XXX only needs to be redrawn for old slider pos
>-          this.ctx.fillRect(this.margin, mid - 1, this.barwidth, 3);
>-          this.ctx.strokeRect(this.margin, mid - 1, this.barwidth, 3);
>-
>-          // Let the accessor know the outOfRange state.  The accessor will
>-          // take care of the control styling and dispatching the appropriate
>-          // events if the in/out of range condition has changed from its
>-          // previous state.
>-          if (outOfRange != this.outOfRange) {
>-            this.outOfRange = outOfRange;
>-            this.accessors.setInRange(!outOfRange);
>-          }
>-
>-          // if out-of-range, we cannot represent the value
>-          if (outOfRange) {
>-            this.rVal = null;
>-            return null;
>-          }
>-
>-          // draw slider at new position
>-          this.justMoved = (aMode == "move");
>-          this.drawSlider(this.calcPos(aVal), this.justMoved);
>-
>-          this.ctx.restore();
>-
>-          // Store new value
>-          return this.rVal = aVal;
>-          ]]>
>-        </body>
>-      </method>
>-
>-      <!-- get x,y offset for mouse events -->
>-      <method name="getOffset">
>-        <parameter name="event"/>
>-        <body>
>-          var obj;
>-          if (document.getBoxObjectFor) {
>-            obj = document.getBoxObjectFor(this.canvas);
>-          } else {
>-            obj = { x: event.target.offsetLeft, y: event.target.offsetTop };
>-          }
>-          return obj;
>-        </body>
>-      </method>
>-
>-      <!-- calculate slider position from mouse position -->
>-      <method name="calcMousePos">
>-        <parameter name="obj"/>
>-        <parameter name="x"/>
>-        <body>
>-          x -= obj.margin;
>-          if (obj.rStep) {
>-            x = (x / obj.stepsp) * obj.rStep;
>-          } else {
>-            x = (x / this.barwidth) * (this.rEnd - this.rBegin);
>-          }
>-          return x + obj.rBegin;  
>-        </body>
>-      </method>
>-
>-      <!-- handle mouse down -->
>-      <method name="handleMouseDown">
>-        <parameter name="event"/>
>-        <body>
>-          <![CDATA[
>-          if (event.button == 0) {
>-            this.currentOffset = this.getOffset(event);
>-            this.originalVal = this.rVal;
>-            this.isMoving = true;
>-            var xpos = event.clientX - this.currentOffset.x;
>-            if (xpos < this.margin) {
>-              xpos = this.margin;
>-            }
>-            if (xpos > (this.barwidth + this.margin)) {
>-              xpos = this.barwidth;
>-            }
>-            var mode = this.isIncremental ? null : "move"
>-            this.setSlider(this.calcMousePos(this, xpos), mode);
>-            return;
>-          }
>-          ]]>
>-        </body>
>-      </method>
>+  <!-- RANGE: <NUMBER>
>+    This binding is base for xforms range controls. It assumes successors
>+    bindings implement getElementControl() method that returns the object:
>+    {
>+      get/set value(); // get/set "number" value
>+      set readonly(); // makes range disabled
>+      get/set start(); // get/set @start attribute, type is "number"
>+      get/set end(); // get/set @end attribute, type is "number"
>+      get/set step(); // get/set @step attribute, type is "number"
>+      focus() // set the focus
>+    }
>+  -->
> 
>-      <!-- handle mouse up -->
>-      <method name="handleMouseUp">
>-        <parameter name="event"/>
>-        <body>
>-          if (event.button != 0 || !this.isMoving) {
>-            return;
>-          }
>-          var x = event.clientX - this.currentOffset.x;
>-          this.setSlider(this.calcMousePos(this, x));
>-          this.isMoving = false;
>-        </body>
>-      </method>
>+  <binding id="xformswidget-range-base"
>+           extends="chrome://xforms/content/xforms.xml#xformswidget-base">
> 
>-      <!-- handle mouse moves -->
>-      <method name="handleMouseMove">
>-        <parameter name="event"/>
>+    <implementation>
>+      <method name="refresh">
>         <body>
>-          <![CDATA[
>-          if (!this.isMoving) {
>-            return;
>-          }
>-          var xpos = event.clientX - this.currentOffset.x;
>-          if (xpos < this.margin) {
>-            xpos = this.margin;
>-          }
>-          if (xpos > (this.barwidth + this.margin)) {
>-            xpos = this.barwidth + this.margin;
>-          }
>-          var mode = this.isIncremental ? null : "move"
>-          this.setSlider(this.calcMousePos(this, xpos), mode);
>-          ]]>
>-        </body>
>-      </method>
>+        <![CDATA[
>+          this.control.readonly = this.accessors.isReadonly();
> 
>-      <!-- handle mouse out -->
>-      <method name="handleMouseOut">
>-        <parameter name="event"/>
>-        <body>
>-          if (!this.isMoving) {
>+          var value = parseFloat(this.accessors.getValue());
>+          if (!value)
>             return;
>-          }
>-          this.isMoving = false;
>-          this.setSlider(this.originalVal);
>-        </body>
>-      </method>
> 
>-      <method name="handleKey">
>-        <parameter name="event"/>
>-        <body>
>-          var move;
>-          if (this.rStep) {
>-            move = this.rStep;
>-          } else {
>-            move = (this.rEnd - this.rBegin) / 20;
>-          }
>-
>-          if (event.keyCode == event.DOM_VK_LEFT) {
>-            this.setSlider(this.rVal - move);
>-          } else if (event.keyCode == event.DOM_VK_RIGHT) {
>-            this.setSlider(this.rVal + move);
>-          } else if (event.keyCode == event.DOM_VK_PAGE_DOWN) {
>-            this.setSlider(this.rVal - move * 2);
>-          } else if (event.keyCode == event.DOM_VK_PAGE_UP) {
>-            this.setSlider(this.rVal + move * 2);
>-          } else if (event.keyCode == event.DOM_VK_HOME) {
>-            this.setSlider(this.rBegin);
>-          } else if (event.keyCode == event.DOM_VK_END) {
>-            this.setSlider(this.rEnd);
>-          }
>-        </body>
>-      </method>
>-
>-      <method name="refresh">
>-        <body>
>-          <![CDATA[
>-          if (!this.isInitialized) {
>-            if (!this.delegate) {
>-              return;
>-            }
>-            var labelBegin = document.getAnonymousElementByAttribute(this, "anonid", "labelBegin");
>-            var labelEnd = document.getAnonymousElementByAttribute(this, "anonid", "labelEnd");
>-            var canvas = document.getAnonymousElementByAttribute(this, "anonid", "canvas");
>-            this.isInitialized = this.createRange(canvas, labelBegin, labelEnd,
>-                                                  this.accessors.getRangeStart(),
>-                                                  this.accessors.getRangeEnd(),
>-                                                  this.accessors.getRangeStep());
>-          }
>-
>-          // XXX: does not clear range if bound node "disappears"
>-          if (this.isInitialized && this.accessors.hasBoundNode()) {
>-            this.setSlider(this.accessors.getValue(), "set");
>-          }
>-          ]]>
>+          var inrange = this.start >= value && value <= this.end;
>+          this.accessors.setInRange(inrange);
>+          this.control.set(this.start, this.end, this.step, value);
>+          //this.control.value = value;
>+        ]]>
>         </body>
>       </method>
> 
>       <method name="focus">
>         <body>
>-          this.canvas.focus();
>-          return true;
>+          this.control.focus();
>         </body>
>       </method>
> 
>       <method name="getCurrentValue">
>         <body>
>-          throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
>+          var value = this.control.value;
>+          return isNaN(value) ? "" : value;
>         </body>
>       </method>
> 
>-      <!-- create new range object -->
>-      <method name="createRange">
>-        <parameter name="aCanvas"/>
>-        <parameter name="aLabelBegin"/>
>-        <parameter name="aLabelEnd"/>
>-        <parameter name="aBegin"/>
>-        <parameter name="aEnd"/>
>-        <parameter name="aStep"/>
>-        <body>
>-          <![CDATA[
>-          if (!(aCanvas && aLabelBegin && aLabelEnd)) {
>-            this.delegate.reportError("rangeNullObjects");
>-            return false;
>-          }
>-
>-          this.rBegin = parseFloat(aBegin);
>-          this.rEnd = parseFloat(aEnd);
>-          this.rStep = parseFloat(aStep);
>-          this.rVal = this.rBegin;
>-          this.isIncremental = this.getAttribute("incremental") == "true";
>-          this.justMoved = false;
>-
>-          if (isNaN(this.rBegin) || isNaN(this.rEnd)) {
>-            this.delegate.reportError("rangeNullInit");
>-            return false;
>-          }
>-
>-          // XXX should we handle this?
>-          if (this.rBegin >= this.rEnd) {
>-            this.delegate.reportError("rangeBeginEndError");
>-            return false;
>-          }
>-
>-          if (isNaN(this.rStep)) {
>-            this.rStep = null;
>-          } else if (this.rStep < 0) {
>-            // XXX better handling
>-            this.rStep = -this.rStep;
>-          }
>-
>-          // Sanitize @step for xsd:integer
>-          // XXX: we need a schemavalidator.isDerivedFrom(type, "xsd:integer");
>-          if (this.getAttribute("type") == "http://www.w3.org/2001/XMLSchema#integer") {
>-            if (!this.rStep) {
>-              this.rStep = 1;
>-            } else {
>-              this.rStep = Math.round(this.rStep);
>-            }
>-          }
>-
>-          // set labels
>-          aLabelBegin.appendChild(document.createTextNode(this.rBegin));
>-          aLabelEnd.appendChild(document.createTextNode(this.rEnd));
>-
>-          // get canvas
>-          this.canvas = aCanvas;
>-          this.height = this.canvas.height;
>-
>-          // get and set context
>-          this.ctx = this.canvas.getContext("2d");
>-          this.ctx.globalAlpha = 1.0;
>-          this.ctx.lineWidth = 1;
>-
>-          // size of horisontal bar
>-          this.margin = Math.round(this.canvas.width / 45);
>-          if (this.margin < 4) {
>-            this.margin = 4;
>-          }
>-          this.barwidth = this.canvas.width - (2 * this.margin);
>-
>-          // slider size
>-          this.sliderwidth = this.margin - 1;
>-          if (this.sliderwidth < 4) {
>-            this.sliderwidth = 4;
>-          }
>-          this.slidertip = Math.round(this.height / 10);
>-          this.tickheight = this.slidertip * 2;
>-
>-          if (!this.rStep) {
>-            this.adjEnd = this.rEnd;
>-            return true;
>-          }
>-
>-          // begin and end might not be a step
>-          this.adjEnd = this.rEnd - ((this.rEnd - this.rBegin) % this.rStep);
>-          this.steps  = (this.adjEnd - this.rBegin) / this.rStep;
>-          this.stepsp = (this.barwidth * (this.adjEnd / this.rEnd)) / this.steps;
>-          this.width = this.steps * this.stepsp;
>-
>-          // ticks (== steps for the moment)
>-          this.ticks = this.steps;
>-          this.ticksp = this.stepsp;
>-
>-          for (var i = 0; i <= this.ticks; ++i) {
>-            var pos = Math.round(this.margin + i * this.ticksp);
>-            this.ctx.moveTo(pos, this.height - this.tickheight + 1);
>-            this.ctx.lineTo(pos, this.height);
>-            this.ctx.closePath();
>-            this.ctx.stroke();
>-          }
>+      <property name="start"
>+                onget="return this.control.start;"
>+                onset="this.setAttribute('start', val); this.control.start = val;"/>
>+
>+      <property name="end"
>+                onget="return this.control.end;"
>+                onset="this.setAttribute('end', val); this.control.end = val;"/>
>+
>+      <property name="step"
>+                onget="return this.control.step;"	
>+                onset="this.setAttribute('step', val); this.control.step = val;"/>
>+
>+      <property name="incremental">
>+        <getter>
>+          return this.getAttribute("incremental") == "true";
>+        </getter>
>+        <setter>
>+          if (val)
>+            this.setAttribute("incremental", "true");
>+          else
>+            this.removeAttribute("incremental");
>+        </setter>
>+      </property>
>+
>+      <property name="accessors" readonly="true">
>+        <getter>
>+        <![CDATA[
>+          if (!this._accessors && this.delegate) {
>+            this._accessors = this.delegate.getXFormsAccessors().
>+              QueryInterface(Components.interfaces.nsIXFormsRangeAccessors);
>+          }
>+          return this._accessors;
>+        ]]>
>+        </getter>
>+      </property>
> 
>+      <method name="updateInstanceData">
>+        <parameter name="aIncremental"/>
>+        <body>
>+          if (!this.accessors.hasBoundNode())
>+            return;
> 
>-          return true;
>-          ]]>
>+          if (!aIncremental || this.incremental)
>+            this.accessors.setValue(this.control.value);
>         </body>
>       </method>
>     </implementation>
>   </binding>
>+
> </bindings>
>Index: extensions/xforms/resources/content/widgets-xhtml.xml
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/widgets-xhtml.xml,v
>retrieving revision 1.6
>diff -u -8 -p -r1.6 widgets-xhtml.xml
>--- extensions/xforms/resources/content/widgets-xhtml.xml	12 Sep 2006 23:06:44 -0000	1.6
>+++ extensions/xforms/resources/content/widgets-xhtml.xml	16 Sep 2006 12:19:31 -0000
>@@ -366,17 +366,16 @@
>       <method name="focus">
>         <body>
>           this.canvas.focus();
>           return true;
>         </body>
>       </method>
> 
>     <!-- private -->
>-
>       <method name="setMin">
>         <parameter name="aValue"/>
>         <parameter name="aRefresh"/>
>         <body>
>           if (!isNaN(parseFloat(aValue))) {
>             this.setAttribute("min", aValue);
>             this.minLabel.textContent = aValue;
>             if (aRefresh) {
>@@ -494,17 +493,20 @@
>         ]]>
>         </getter>
>       </property>
> 
>       <!-- Draw slider. -->
>       <method name="drawSlider">
>         <parameter name="aPos"/>
>         <body>
>+        <![CDATA[
>           var boxobj = this.sliderController;
>+          if (boxobj.barHeight <= 0 || boxobj.barWidth <=0)
>+            return;
> 
>           this.context.save();
>           this.context.lineWidth = 1;
> 
>           this.context.beginPath();
>           var h1 = boxobj.barHeight - Math.round(boxobj.barHeight / 5);
>           var h2 = h1 - Math.round(boxobj.barHeight / 10);
>           var h3 = Math.round(boxobj.barHeight / 5);
>@@ -518,52 +520,60 @@
> 
>           this.context.strokeStyle =this.currStrokeStyle;
>           this.context.stroke();
> 
>           this.context.fillStyle = this.fillStyle;
>           this.context.fill();
> 
>           this.context.restore();
>+        ]]>
>         </body>
>       </method>
> 
>       <!-- Erase slider. -->
>       <method name="eraseSlider">
>         <parameter name="aPos"/>
>         <body>
>+        <![CDATA[
>           var boxobj = this.sliderController;
>+          if (boxobj.barHeight <= 0 || boxobj.barWidth <= 0)
>+            return;
> 
>           // clear old slider
>           this.context.
>             clearRect(aPos - boxobj.sliderWidth -1, 0,
>                       boxobj.sliderWidth * 2 + 2,
>                       boxobj.barHeight - Math.round(boxobj.barHeight / 5) + 1);
> 
>           // (re)draw horisontal bar
>           this.context.lineWidth = 1;
>           this.context.fillStyle = this.fillStyle;
>           this.context.strokeStyle = this.strokeStyle;
> 
>           // XXX: only needs to be redrawn for old slider pos
>           mid = Math.round(boxobj.barHeight / 2);
>           this.context.fillRect(boxobj.barMargin, mid - 1, boxobj.barWidth, 3);
>           this.context.strokeRect(boxobj.barMargin, mid - 1, boxobj.barWidth, 3);
>+        ]]>
>         </body>
>       </method>
> 
>       <!-- Draw scale. -->
>       <method name="drawScale">
>         <body>
>         <![CDATA[
>           this.context.lineWidth = 1;
>           this.context.fillStyle = this.fillStyle;
>           this.context.strokeStyle = this.strokeStyle;
> 
>           var boxobj = this.sliderController;
>+          if (boxobj.barHeight <= 0 || boxobj.barWidth <=0)
>+            return;
>+
>           var mid = Math.round(boxobj.barHeight / 2);
>           this.context.fillRect(boxobj.barMargin, mid - 1, boxobj.barWidth, 3);
>           this.context.strokeRect(boxobj.barMargin, mid - 1, boxobj.barWidth, 3);
> 
>           var h = boxobj.barHeight - Math.round(boxobj.barHeight / 5) + 1;
>           for (var i = 0; i <= boxobj.scalePointCount; ++i) {
>             var pos = Math.round(i * boxobj.scalePointIndent) +
>               boxobj.barMargin;
>Index: extensions/xforms/resources/content/xforms.css
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/xforms.css,v
>retrieving revision 1.44
>diff -u -8 -p -r1.44 xforms.css
>--- extensions/xforms/resources/content/xforms.css	30 Aug 2006 15:16:06 -0000	1.44
>+++ extensions/xforms/resources/content/xforms.css	16 Sep 2006 12:19:31 -0000
>@@ -209,18 +209,26 @@ html|*:root output[mozType|type="http://
> xul|*:root output[mozType|type="http://www.w3.org/2001/XMLSchema#anyURI"][mozType|mediatype^="image"] {
>   -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-output-mediatype-anyURI');
> }
> xul|*:root output[mozType|type="http://www.w3.org/2001/XMLSchema#base64Binary"][mozType|mediatype^="image"] {
>   -moz-binding: url('chrome://xforms/content/xforms-xhtml.xml#xformswidget-output-mediatype-base64Binary');
> }
> 
> /* range widgets */
>-range {
>-  -moz-binding: url('chrome://xforms/content/range.xml#xformswidget-range');
>+html|*:root range[mozType|typelist~="http://www.w3.org/2001/XMLSchema#decimal"],
>+html|*:root range[mozType|typelist~="http://www.w3.org/2001/XMLSchema#float"],
>+html|*:root range[mozType|typelist~="http://www.w3.org/2001/XMLSchema#double"] {
>+  -moz-binding: url('chrome://xforms/content/range-xhtml.xml#xformswidget-range');
>+}
>+
>+html|*:root range[mozType|typelist~="http://www.w3.org/2001/XMLSchema#decimal"] html|span[mozType|slider],
>+html|*:root range[mozType|typelist~="http://www.w3.org/2001/XMLSchema#float"] html|span[mozType|slider],
>+html|*:root range[mozType|typelist~="http://www.w3.org/2001/XMLSchema#double"] html|span[mozType|slider] {
>+  -moz-binding: url('chrome://xforms/content/widgets-xhtml.xml#slider');
> }
> 
> /* input widgets */
> 
>   /* input */
> html|*:root input {
>   -moz-binding: url('chrome://xforms/content/input-xhtml.xml#xformswidget-input');
> }
>Index: extensions/xforms/resources/content/xforms.xml
>===================================================================
>RCS file: /cvsroot/mozilla/extensions/xforms/resources/content/xforms.xml,v
>retrieving revision 1.44
>diff -u -8 -p -r1.44 xforms.xml
>--- extensions/xforms/resources/content/xforms.xml	24 Aug 2006 21:14:44 -0000	1.44
>+++ extensions/xforms/resources/content/xforms.xml	16 Sep 2006 12:19:31 -0000
>@@ -163,17 +163,18 @@
>         <getter>
>           var value = this.accessors.getValue();
>           return value != null ? value : "";
>         </getter>
>       </property>
> 
>     <!-- private -->
>       <constructor>
>-        this.delegate.widgetAttached();
>+        if (!this.hasAttributeNS(this.MOZTYPE_NS, "deferredrefresh"))
>+          this.delegate.widgetAttached();
>       </constructor>
> 
>       <destructor>
>         this._delegate = null;
>         this._accessors = null;
>       </destructor>
> 
>       <property name="delegate" readonly="true">
Attachment #238779 - Flags: review?(doronr) → review+
Attachment #238779 - Flags: review?(Olli.Pettay)
Comment on attachment 238779 [details] [diff] [review]
patch2


Could you explain why deferredrefresh is needed
(I guess otherwise the slider binding isn't loaded on time).
I don't really like that, but perhaps there isn't any better way.
(In reply to comment #4)
> (From update of attachment 238779 [details] [diff] [review] [edit])
> 
> Could you explain why deferredrefresh is needed
> (I guess otherwise the slider binding isn't loaded on time).
> I don't really like that, but perhaps there isn't any better way.
> 

The problem is when 'xformswidget-accessors' binding gets loaded then it calles 'widgetAttached' and then control is refreshed but it happens before than canvas is ready to work. It means canvas width and height are 0. Therefore I tried to deffer call of widgetAttached. But probably the other way is some magic with event on which xforms initialization is started.
Blocks: 334603
Blocks: 343525
(In reply to comment #5)
> But probably the other way is some
> magic with event on which xforms initialization is started.
> 

Do you think that could be possible? Or is the deferredrefresh really needed.
Maybe the slider widget could inform its "parent widget" (or 
"owner widget" or whatever call it) when it is ready and range
could then call widgetAttached...

(In reply to comment #6)
> (In reply to comment #5)
> > But probably the other way is some
> > magic with event on which xforms initialization is started.
> > 
> 
> Do you think that could be possible?

I tried to add event 'DOMContentLoaded' handler on capture but that didn't helped. I guess event 'load' can't be used. So I don't see a possibility.

> Or is the deferredrefresh really needed.

I guess yes, if even slider can fire event when it get loaded then widgetAttached() shouldn't be called in constructor of 'xformswidget-accessors'.

> Maybe the slider widget could inform its "parent widget" (or 
> "owner widget" or whatever call it) when it is ready and range
> could then call widgetAttached...

The problem is I can't know when canvas is ready to work, when slider widget is loaded (constructor is called) then canvas is not still ready. Therefore I use setTimeout().

Comment on attachment 238779 [details] [diff] [review]
patch2

well, r=me then I guess.
(But hoping a better solution will be found)
Attachment #238779 - Flags: review?(Olli.Pettay) → review+
Attached patch patch3Splinter Review
Attachment #238779 - Attachment is obsolete: true
Checked in to trunk
Status: ASSIGNED → RESOLVED
Closed: 18 years ago
Resolution: --- → FIXED
Whiteboard: xf-to-branch
checked into 1.8.0 on 2006/09/27
Keywords: fixed1.8.0.8
checked into 1.8 branch on 2006/11/21
Keywords: fixed1.8.1.1
Whiteboard: xf-to-branch
Product: Core → Core Graveyard
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: