[XForms] First go at the range element. Lots of room for improvement still. Bug 271044, r=aaronr+smaug

This commit is contained in:
allan%beaufour.dk 2005-11-14 08:42:36 +00:00
Родитель f4abea28a6
Коммит 676740b429
14 изменённых файлов: 864 добавлений и 2 удалений

Просмотреть файл

@ -130,6 +130,7 @@ XPIDLSRCS = \
nsIXFormsLabelElement.idl \
nsIXFormsItemSetUIElement.idl \
nsIXFormsAccessors.idl \
nsIXFormsRangeAccessors.idl \
nsIXFormsUploadElement.idl \
nsIXFormsUploadUIElement.idl \
$(NULL)
@ -187,7 +188,9 @@ CPPSRCS = \
nsXFormsControlStub.cpp \
nsXFormsUtilityService.cpp \
nsXFormsDelegateStub.cpp \
nsXFormsRangeElement.cpp \
nsXFormsAccessors.cpp \
nsXFormsRangeAccessors.cpp \
$(NULL)
# Standard Mozilla make rules

Просмотреть файл

@ -9,6 +9,7 @@ xforms.jar:
* content/xforms/xforms-prefs.js (resources/content/xforms-prefs.js)
content/xforms/xforms.xml (resources/content/xforms.xml)
content/xforms/select1.xml (resources/content/select1.xml)
content/xforms/range.xml (resources/content/range.xml)
content/xforms/select.xml (resources/content/select.xml)
content/xforms/bindingex.css (resources/content/bindingex.css)
content/xforms/bindingex.xul (resources/content/bindingex.xul)

Просмотреть файл

@ -49,7 +49,7 @@ interface nsIXFormsAccessors;
* http://developer.mozilla.org/en/docs/XForms:Custom_Controls
*
*/
[scriptable, uuid(5e75904d-73e8-4cee-b02c-4348a071a0e1)]
[scriptable, uuid(902898eb-490e-4c36-a00b-9e74adcfbc43)]
interface nsIXFormsDelegate : nsISupports
{
/**
@ -61,4 +61,14 @@ interface nsIXFormsDelegate : nsISupports
* This should be called by XBL widgets, when they are created.
*/
void widgetAttached();
/**
* Report an error
*
* @param errorMsg The error message id
*
* @todo XXX this should be extended to allow for "raw strings", not
* necessarily kept in bundles.
*/
void reportError(in DOMString errorMsg);
};

Просмотреть файл

@ -0,0 +1,57 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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
* 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>
*
* 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 ***** */
#include "nsIXFormsAccessors.idl"
/**
* Accessors provided by XForms \<range\> controls.
*
* @see http://www.w3.org/TR/xforms/slice8.html#ui-range
*/
[scriptable, uuid(8a6c4540-4c2b-4591-af0e-ef147543eee7)]
interface nsIXFormsRangeAccessors : nsIXFormsAccessors
{
/** The start of the range interval */
DOMString getRangeStart();
/** The end of the range interval */
DOMString getRangeEnd();
/** The step size */
DOMString getRangeStep();
};

Просмотреть файл

@ -36,6 +36,9 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef __NSXFORMSACCESSORS_H__
#define __NSXFORMSACCESSORS_H__
#include "nsIClassInfo.h"
#include "nsIXFormsAccessors.h"
#include "nsIDelegateInternal.h"
@ -72,10 +75,11 @@ protected:
*/
nsresult GetState(PRInt32 aState, PRBool *aStateVal);
private:
/** The delegate owning us */
nsIDelegateInternal* mDelegate;
/** The control DOM element */
nsIDOMElement* mElement;
};
#endif

Просмотреть файл

@ -179,6 +179,14 @@ nsXFormsDelegateStub::GetHasBoundNode(PRBool *aHasBoundNode)
return NS_OK;
}
NS_IMETHODIMP
nsXFormsDelegateStub::ReportError(const nsAString& aErrorMsg)
{
const nsPromiseFlatString& flat = PromiseFlatString(aErrorMsg);
nsXFormsUtils::ReportError(flat, mElement);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsDelegateStub::WidgetAttached()
{

Просмотреть файл

@ -72,6 +72,7 @@ NS_HIDDEN_(nsresult) NS_NewXFormsItemElement(nsIXTFElement **aElement);
NS_HIDDEN_(nsresult) NS_NewXFormsValueElement(nsIXTFElement **aElement);
NS_HIDDEN_(nsresult) NS_NewXFormsChoicesElement(nsIXTFElement **aElement);
NS_HIDDEN_(nsresult) NS_NewXFormsItemSetElement(nsIXTFElement **aElement);
NS_HIDDEN_(nsresult) NS_NewXFormsRangeElement(nsIXTFElement **aElement);
//Action Module Elements
NS_HIDDEN_(nsresult) NS_NewXFormsDispatchElement(nsIXTFElement **aResult);
@ -188,6 +189,8 @@ nsXFormsElementFactory::CreateElement(const nsAString& aTagName,
return NS_NewXFormsSwitchElement(aElement);
if (aTagName.EqualsLiteral("upload"))
return NS_NewXFormsUploadElement(aElement);
if (aTagName.EqualsLiteral("range"))
return NS_NewXFormsRangeElement(aElement);
*aElement = nsnull;
return NS_ERROR_FAILURE;

Просмотреть файл

@ -0,0 +1,108 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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
* 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>
*
* 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 ***** */
#include "nsXFormsRangeAccessors.h"
#include "nsDOMString.h"
#include "nsIDOMElement.h"
#include "nsString.h"
#include "nsXFormsUtils.h"
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsRangeAccessors,
nsXFormsAccessors,
nsIXFormsRangeAccessors,
nsIClassInfo)
// nsXFormsRangeAccessors
nsresult
nsXFormsRangeAccessors::AttributeGetter(const nsAString &aAttr, nsAString &aVal)
{
nsAutoString val;
if (mElement) {
mElement->GetAttribute(aAttr, val);
}
if (val.IsEmpty()) {
SetDOMStringToNull(aVal);
} else {
aVal = val;
}
return NS_OK;
}
// nsIXFormsRangeElement
// XXX this should do a max(type.minumum, @start)
NS_IMETHODIMP
nsXFormsRangeAccessors::GetRangeStart(nsAString &aMin)
{
return AttributeGetter(NS_LITERAL_STRING("start"), aMin);
}
// XXX this should do min(type.maximu, @end)
NS_IMETHODIMP
nsXFormsRangeAccessors::GetRangeEnd(nsAString &aMax)
{
return AttributeGetter(NS_LITERAL_STRING("end"), aMax);
}
// XXX if step is not set, it should be set to something "smart" and also
// needs to be something that is valid for the given type. This could be
// pushed to the widget though.
NS_IMETHODIMP
nsXFormsRangeAccessors::GetRangeStep(nsAString &aStep)
{
return AttributeGetter(NS_LITERAL_STRING("step"), aStep);
}
// nsIClassInfo implementation
static const nsIID sScriptingIIDs[] = {
NS_IXFORMSACCESSORS_IID,
NS_IXFORMSRANGEACCESSORS_IID,
};
NS_IMETHODIMP
nsXFormsRangeAccessors::GetInterfaces(PRUint32 *aCount, nsIID * **aArray)
{
return nsXFormsUtils::CloneScriptingInterfaces(sScriptingIIDs,
NS_ARRAY_LENGTH(sScriptingIIDs),
aCount, aArray);
}

Просмотреть файл

@ -0,0 +1,74 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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
* 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>
*
* 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 ***** */
#include "nsIXFormsRangeAccessors.h"
#include "nsXFormsAccessors.h"
/**
* Implementation for the accessors for a range element,
* nsIXFormsRangeAccessors.
*
* @todo Support out-of/in-range events (XXX)
*/
class nsXFormsRangeAccessors : public nsIXFormsRangeAccessors,
public nsXFormsAccessors
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIXFORMSRANGEACCESSORS
NS_FORWARD_NSIXFORMSACCESSORS(nsXFormsAccessors::)
// Constructor
nsXFormsRangeAccessors(nsIDelegateInternal* aDelegate,
nsIDOMElement* aElement)
: nsXFormsAccessors(aDelegate, aElement)
{
}
// nsIClassInfo overrides
NS_IMETHOD GetInterfaces(PRUint32 *aCount, nsIID * **aArray);
protected:
/**
* Gets the value of an attribute on the element (mElement).
*
* @param aAttr The attribute
* @param aVal The returned value ("DOMNull"s it if it's not there or empty)
*/
nsresult AttributeGetter(const nsAString &aAttr, nsAString &aVal);
};

Просмотреть файл

@ -0,0 +1,87 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** 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
* Novell, Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Allan Beaufour <allan@beaufour.dk>
*
* 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 ***** */
#include "nsXFormsDelegateStub.h"
#include "nsXFormsRangeAccessors.h"
/**
* Implementation of the XForms \<range\> element
* @see http://www.w3.org/TR/xforms/slice8.html#ui-range
*
* @todo Check data binding restrictions (XXX)
*/
class nsXFormsRangeElement : public nsXFormsDelegateStub
{
public:
// nsIXFormsDelegate overrides
NS_IMETHOD GetXFormsAccessors(nsIXFormsAccessors **aAccessor);
#ifdef DEBUG_smaug
virtual const char* Name() { return "range"; }
#endif
};
// nsIXFormsDelegate
NS_IMETHODIMP
nsXFormsRangeElement::GetXFormsAccessors(nsIXFormsAccessors **aAccessor)
{
if (!mAccessor) {
mAccessor = new nsXFormsRangeAccessors(this, mElement);
if (!mAccessor) {
return NS_ERROR_OUT_OF_MEMORY;
}
}
NS_ADDREF(*aAccessor = mAccessor);
return NS_OK;
}
// Creator
NS_HIDDEN_(nsresult)
NS_NewXFormsRangeElement(nsIXTFElement **aResult)
{
*aResult = new nsXFormsRangeElement();
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,484 @@
<?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
- 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>
-
- 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"
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");
}
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);
// check whether out-of-range state has changed, and dispatch event if it has
if (outOfRange != this.outOfRange) {
// XXX we need to set the style too
this.outOfRange = outOfRange;
var event = outOfRange ? "xforms-out-of-range" : "xforms-in-range";
this.dispatchXFormsNotificationEvent(event, this);
}
// 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;
}
this.setSlider(this.calcMousePos(this, xpos), "move");
return;
}
]]>
</body>
</method>
<!-- 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>
<!-- handle mouse moves -->
<method name="handleMouseMove">
<parameter name="event"/>
<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;
}
this.setSlider(this.calcMousePos(this, xpos), "move");
]]>
</body>
</method>
<!-- handle mouse out -->
<method name="handleMouseOut">
<parameter name="event"/>
<body>
if (!this.isMoving) {
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);
}
</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");
}
]]>
</body>
</method>
<method name="focus">
<body>
this.canvas.focus();
return true;
</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;
}
// 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();
}
return true;
]]>
</body>
</method>
</implementation>
</binding>
</bindings>

Просмотреть файл

@ -80,6 +80,10 @@ output {
-moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-output');
}
range {
-moz-binding: url('chrome://xforms/content/range.xml#xformswidget-range');
}
input {
-moz-binding: url('chrome://xforms/content/xforms.xml#xformswidget-input');
}

Просмотреть файл

@ -122,6 +122,7 @@
</body>
</method>
<!-- Dispatch UI Event to the control itself -->
<method name="dispatchDOMUIEvent">
<parameter name="aType"/>
<body>
@ -132,6 +133,20 @@
</body>
</method>
<!--
Dispatch an _XForms notification event_ to a node.
See http://www.w3.org/TR/xforms/slice4.html#evt-notify
-->
<method name="dispatchXFormsNotificationEvent">
<parameter name="aEventName"/>
<parameter name="aTarget"/>
<body>
var ev = document.createEvent("Events");
ev.initEvent(aEventName, true, false);
aTarget.dispatchEvent(ev);
return true;
</body>
</method>
</implementation>
</binding>

Просмотреть файл

@ -58,6 +58,10 @@ labelLink2Error = XForms Error (19): Failed to load Label element from exte
invalidSeparator = XForms Error (20): Submission separator may only be either "&" or ";", but found "%S".
instanceBindError = XForms Error (21): Submission failed trying to replace instance document '%S'. Instance document doesn't exist in same model as submission element.
instanceInstanceLoad = XForms Error (22): Instance document not allowed to load external instance: %S
rangeSetSliderNaN = XForms Error (23): NaN passed to setSlider()
rangeNullObjects = XForms Error (24): One or more of the passed objects were null
rangeNullInit = XForms Error (25): One or more init() parameters is NaN
rangeBeginEndError = XForms Error (26): Begin is higher than end?
encodingMemoryError = XForms Error (23): Not enough available memory to encode file %S, size = %S.
uploadBoundTypeError = XForms Error (24): Upload element not bound to valid datatype. Must be bound to datatype 'xsd:anyURI', 'xsd:base64Binary', or 'xsd:hexBinary'.