Bug 358714 ��� implement accessible object for xforms minimal select in xhtml context, r=aaronr,aaronl, sr=neil

This commit is contained in:
Olli.Pettay%helsinki.fi 2007-01-10 14:39:44 +00:00
Родитель 19b952afd5
Коммит 125264c99e
15 изменённых файлов: 395 добавлений и 60 удалений

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

@ -108,48 +108,55 @@ interface nsIAccessibleProvider : nsISupports
* Constants set is used by XForms elements.
*/
/** Used for xforms elements that provide accessible object for itself as
* well for anonymous content. This property are used for upload,
* input[type="xsd:gDay"] and input[type="xsd:gMonth"] */
const long XFormsContainer = 0x00002000;
/** Used for xforms elements that provide accessible object for itself as
* well for anonymous content. This property are used for upload,
* input[type="xsd:gDay"] and input[type="xsd:gMonth"] */
const long XFormsContainer = 0x00002000;
/** Used for label element */
const long XFormsLabel = 0x00002001;
/** Used for output element */
const long XFormsOuput = 0x00002002;
/** Used for trigger and submit elements */
const long XFormsTrigger = 0x00002003;
/** Used for input and textarea elements */
const long XFormsInput = 0x00002004;
/** Used for input[xsd:boolean] element */
const long XFormsInputBoolean = 0x00002005;
/** Used for input[xsd:date] element */
const long XFormsInputDate = 0x00002006;
/** Used for secret element */
const long XFormsSecret = 0x00002007;
/** Used for range element represented by slider */
const long XFormsSliderRange = 0x00002008;
/** Used for label element */
const long XFormsLabel = 0x00002001;
/** Used for output element */
const long XFormsOuput = 0x00002002;
/** Used for trigger and submit elements */
const long XFormsTrigger = 0x00002003;
/** Used for input and textarea elements */
const long XFormsInput = 0x00002004;
/** Used for input[xsd:boolean] element */
const long XFormsInputBoolean = 0x00002005;
/** Used for input[xsd:date] element */
const long XFormsInputDate = 0x00002006;
/** Used for secret element */
const long XFormsSecret = 0x00002007;
/** Used for range element represented by slider */
const long XFormsSliderRange = 0x00002008;
/** Used for select and select1 that are implemented using host document's
* native widget. For example, a select1 in a xhtml document may be
* represented by the native html control html:select */
const long XFormsSelect = 0x00002009;
/** Used for xforms choices element */
const long XFormsChoices = 0x00002010;
/** Used for xforms full select/select1 elements that may be represented by
* group of checkboxes and radiogroup */
const long XFormsSelectFull = 0x00002011;
/** Used for xforms item element that is used inside xforms select elements
* represented by group of checkboxes */
const long XFormsItemCheckgroup = 0x00002012;
/** Used for xforms item element that is used inside xforms select1 elements
* represented by radio group */
const long XFormsItemRadiogroup = 0x00002013;
/** Used for select and select1 that are implemented using host document's
* native widget. For example, a select1 in a xhtml document may be
* represented by the native html control html:select */
const long XFormsSelect = 0x00002009;
/** Used for xforms choices element */
const long XFormsChoices = 0x00002010;
/** Used for xforms full select/select1 elements that may be represented by
* group of checkboxes and radiogroup */
const long XFormsSelectFull = 0x00002011;
/** Used for xforms item element that is used inside xforms select elements
* represented by group of checkboxes */
const long XFormsItemCheckgroup = 0x00002012;
/** Used for xforms item element that is used inside xforms select1 elements
* represented by radio group */
const long XFormsItemRadiogroup = 0x00002013;
/** Used for xforms select1 element that is represented by combobox */
const long XFormsSelectCombobox = 0x00002014;
/** Used for xforms item element that is used inside xforms select1
* elements represented by combobox */
const long XFormsItemCombobox = 0x00002015;
/** Used for dropmarker widget that is used by xforms elements */
const long XFormsDropmarkerWidget = 0x00002101;
/** Used for calendar widget that is used by xforms elements */
const long XFormsCalendarWidget = 0x00002102;
/** Used for dropmarker widget that is used by xforms elements */
const long XFormsDropmarkerWidget = 0x00002101;
/** Used for calendar widget that is used by xforms elements */
const long XFormsCalendarWidget = 0x00002102;
/** Used for popup widget that is used by xforms minimal select1 elements */
const long XFormsComboboxPopupWidget = 0x00002103;
/**
* Return one of constants declared above.

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

@ -1587,6 +1587,12 @@ nsresult nsAccessibilityService::GetAccessibleByType(nsIDOMNode *aNode,
case nsIAccessibleProvider::XFormsItemRadiogroup:
*aAccessible = new nsXFormsItemRadiogroupAccessible(aNode, weakShell);
break;
case nsIAccessibleProvider::XFormsSelectCombobox:
*aAccessible = new nsXFormsSelectComboboxAccessible(aNode, weakShell);
break;
case nsIAccessibleProvider::XFormsItemCombobox:
*aAccessible = new nsXFormsItemComboboxAccessible(aNode, weakShell);
break;
case nsIAccessibleProvider::XFormsDropmarkerWidget:
*aAccessible = new nsXFormsDropmarkerWidgetAccessible(aNode, weakShell);
@ -1594,6 +1600,9 @@ nsresult nsAccessibilityService::GetAccessibleByType(nsIDOMNode *aNode,
case nsIAccessibleProvider::XFormsCalendarWidget:
*aAccessible = new nsXFormsCalendarWidgetAccessible(aNode, weakShell);
break;
case nsIAccessibleProvider::XFormsComboboxPopupWidget:
*aAccessible = new nsXFormsComboboxPopupWidgetAccessible(aNode, weakShell);
break;
#endif
default:

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

@ -102,7 +102,7 @@ nsXFormsAccessible::GetBoundChildElementValue(const nsAString& aTagName,
}
void
nsXFormsAccessible::CacheSelectChildren()
nsXFormsAccessible::CacheSelectChildren(nsIDOMNode *aContainerNode)
{
if (!mWeakShell) {
// This node has been shut down
@ -117,8 +117,13 @@ nsXFormsAccessible::CacheSelectChildren()
if (!accService)
return;
nsCOMPtr<nsIDOMNode> container(aContainerNode);
if (!container)
container = mDOMNode;
nsCOMPtr<nsIDOMNodeList> children;
sXFormsService->GetSelectChildrenFor(mDOMNode, getter_AddRefs(children));
sXFormsService->GetSelectChildrenFor(container, getter_AddRefs(children));
if (!children)
return;

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

@ -100,7 +100,9 @@ protected:
// element. Note, those select/select1 elements that use native widget
// for representation don't use the method since their item/choices elements
// are hidden and therefore aren't accessible.
void CacheSelectChildren();
//
// @param aContainerNode - node that contains item elements
void CacheSelectChildren(nsIDOMNode *aContainerNode = nsnull);
};

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

@ -562,3 +562,93 @@ nsXFormsItemRadiogroupAccessible::GetActionName(PRUint8 aIndex, nsAString& aName
return NS_OK;
}
// nsXFormsSelectComboboxAccessible
nsXFormsSelectComboboxAccessible::
nsXFormsSelectComboboxAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell):
nsXFormsSelectableAccessible(aNode, aShell)
{
}
NS_IMETHODIMP
nsXFormsSelectComboboxAccessible::GetRole(PRUint32 *aRole)
{
NS_ENSURE_ARG_POINTER(aRole);
*aRole = ROLE_COMBOBOX;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectComboboxAccessible::GetState(PRUint32 *aState)
{
nsresult rv = nsXFormsSelectableAccessible::GetState(aState);
NS_ENSURE_SUCCESS(rv, rv);
PRBool isOpen = PR_FALSE;
rv = sXFormsService->IsDropmarkerOpen(mDOMNode, &isOpen);
NS_ENSURE_SUCCESS(rv, rv);
if (isOpen)
*aState = STATE_EXPANDED;
else
*aState = STATE_COLLAPSED;
*aState |= STATE_HASPOPUP | STATE_FOCUSABLE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsSelectComboboxAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
{
NS_ENSURE_ARG_POINTER(aAllowsAnonChildren);
*aAllowsAnonChildren = PR_TRUE;
return NS_OK;
}
// nsXFormsItemComboboxAccessible
nsXFormsItemComboboxAccessible::
nsXFormsItemComboboxAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell):
nsXFormsSelectableItemAccessible(aNode, aShell)
{
}
NS_IMETHODIMP
nsXFormsItemComboboxAccessible::GetRole(PRUint32 *aRole)
{
NS_ENSURE_ARG_POINTER(aRole);
*aRole = ROLE_LISTITEM;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemComboboxAccessible::GetState(PRUint32 *aState)
{
nsresult rv = nsXFormsSelectableItemAccessible::GetState(aState);
NS_ENSURE_SUCCESS(rv, rv);
if (*aState & STATE_UNAVAILABLE)
return NS_OK;
*aState |= STATE_SELECTABLE;
if (IsItemSelected())
*aState |= STATE_SELECTED;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsItemComboboxAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
{
if (aIndex != eAction_Click)
return NS_ERROR_INVALID_ARG;
nsAccessible::GetTranslatedString(NS_LITERAL_STRING("select"), aName);
return NS_OK;
}

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

@ -241,5 +241,41 @@ public:
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
};
/**
* Accessible object for xforms:select1 of minimal appearance that is
* represented by combobox.
*/
class nsXFormsSelectComboboxAccessible : public nsXFormsSelectableAccessible
{
public:
nsXFormsSelectComboboxAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *aState);
// Allows accessible nodes in anonymous content of xforms element by
// always returning PR_TRUE value.
NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
};
/**
* Accessible object for xforms:item element when it is represented by a
* listitem. This occurs when the item is contained in a xforms:select with
* minimal appearance. Such a xforms:select is represented by a combobox.
*/
class nsXFormsItemComboboxAccessible : public nsXFormsSelectableItemAccessible
{
public:
nsXFormsItemComboboxAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *aState);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
};
#endif

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

@ -127,3 +127,73 @@ nsXFormsCalendarWidgetAccessible::GetRole(PRUint32 *aRole)
return NS_OK;
}
// nsXFormsComboboxPopupWidgetAccessible
nsXFormsComboboxPopupWidgetAccessible::
nsXFormsComboboxPopupWidgetAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell):
nsXFormsAccessible(aNode, aShell)
{
}
NS_IMETHODIMP
nsXFormsComboboxPopupWidgetAccessible::GetRole(PRUint32 *aRole)
{
NS_ENSURE_ARG_POINTER(aRole);
*aRole = ROLE_LIST;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsComboboxPopupWidgetAccessible::GetState(PRUint32 *aState)
{
NS_ENSURE_ARG_POINTER(aState);
nsXFormsAccessible::GetState(aState);
PRBool isOpen = PR_FALSE;
nsresult rv = sXFormsService->IsDropmarkerOpen(mDOMNode, &isOpen);
NS_ENSURE_SUCCESS(rv, rv);
*aState |= STATE_FOCUSABLE;
if (isOpen)
*aState = STATE_FLOATING;
else
*aState = STATE_INVISIBLE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsComboboxPopupWidgetAccessible::GetValue(nsAString& aValue)
{
aValue.Truncate();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsComboboxPopupWidgetAccessible::GetName(nsAString& aName)
{
aName.Truncate();
return NS_OK;
}
NS_IMETHODIMP
nsXFormsComboboxPopupWidgetAccessible::GetDescription(nsAString& aDescription)
{
aDescription.Truncate();
return NS_OK;
}
void
nsXFormsComboboxPopupWidgetAccessible::CacheChildren()
{
nsCOMPtr<nsIDOMNode> parent;
mDOMNode->GetParentNode(getter_AddRefs(parent));
// Parent node must be an xforms:select1 element.
CacheSelectChildren(parent);
}

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

@ -74,4 +74,24 @@ public:
NS_IMETHOD GetRole(PRUint32 *aRole);
};
/**
* Accessible object for popup menu of minimal xforms select1 element that is
* represented by combobox.
*/
class nsXFormsComboboxPopupWidgetAccessible : public nsXFormsAccessible
{
public:
nsXFormsComboboxPopupWidgetAccessible(nsIDOMNode *aNode,
nsIWeakReference *aShell);
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetState(PRUint32 *aState);
NS_IMETHOD GetValue(nsAString& aValue);
NS_IMETHOD GetName(nsAString& aName);
NS_IMETHOD GetDescription(nsAString& aDescription);
void CacheChildren();
};
#endif

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

@ -136,15 +136,16 @@ public:
NS_IMETHOD GetEditor(nsIDOMNode *aElement, nsIEditor **aEditor) = 0;
/**
* Return true if dropmarker is in open state, otherwise false. Failure if
* given element is not dropmarker or its parent element isn't supposed to
* have dropmarker.
* Return true if dropmarker is in open state (combobox popup is open),
* otherwise false. Failure if given 'aElement' node is not direct child of
* combobox element or is not combobox itself.
*/
NS_IMETHOD IsDropmarkerOpen(nsIDOMNode *aElement, PRBool* aIsOpen) = 0;
/**
* Toggles dropmarker state. Failure if given element is not dropmarker or
* its parent element isn't supposed to have dropmarker.
* Toggles dropmarker state (close/open combobox popup). Failure if given
* 'aElement' node is not direct child of combobox element or is not combobox
* itself.
*/
NS_IMETHOD ToggleDropmarkerState(nsIDOMNode *aElement) = 0;

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

@ -42,6 +42,9 @@
#include "nsXFormsAtoms.h"
#include "nsIDOMNodeList.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentEvent.h"
#include "nsIDOMEvent.h"
#include "nsIPrivateDOMEvent.h"
#include "nsString.h"
#include "nsXFormsUtils.h"
#include "nsIXFormsValueElement.h"
@ -397,6 +400,33 @@ nsXFormsItemElement::SetActive(PRBool aActive)
{
/// @see comment in nsIXFormsItemElement.idl
if (aActive) {
// Fire 'DOMMenuItemActive' event. This event is used by accessible module.
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
nsCOMPtr<nsIDOMDocumentEvent> doc = do_QueryInterface(domDoc);
NS_ENSURE_STATE(doc);
nsCOMPtr<nsIDOMEvent> event;
doc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
event->InitEvent(NS_LITERAL_STRING("DOMMenuItemActive"),
PR_TRUE, PR_TRUE);
nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mElement));
NS_ENSURE_STATE(node);
nsXFormsUtils::SetEventTrusted(event, node);
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mElement));
NS_ENSURE_STATE(target);
PRBool defaultActionEnabled = PR_TRUE;
nsresult rv = target->DispatchEvent(event, &defaultActionEnabled);
NS_ENSURE_SUCCESS(rv, rv);
}
NS_NAMED_LITERAL_STRING(active, "_moz_active");
return aActive ?

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

@ -72,9 +72,11 @@ NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);\
#define GET_COMBOBOX_UIWIDGET \
NS_ENSURE_ARG(aElement);\
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));\
nsCOMPtr<nsIContent> parent(content->GetBindingParent());\
nsCOMPtr<nsIXFormsComboboxUIWidget> widget(do_QueryInterface(parent));\
nsCOMPtr<nsIXFormsComboboxUIWidget> widget(do_QueryInterface(aElement));\
if (!widget) {\
nsCOMPtr<nsIContent> content(do_QueryInterface(aElement));\
widget = do_QueryInterface(content->GetBindingParent());\
}\
NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);\
#define GET_XFORMS_SELECT1 \
@ -367,6 +369,8 @@ nsresult
nsXFormsUtilityService::GetSelectChildrenForNodeInternal(nsIDOMNode *aElement,
nsNodeList *aNodeList)
{
NS_ENSURE_ARG(aElement);
nsCOMPtr<nsIDOMNodeList> children;
aElement->GetChildNodes(getter_AddRefs(children));
NS_ENSURE_TRUE(children, NS_ERROR_FAILURE);

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

@ -52,13 +52,6 @@
<!-- The strange indentation is because of the whitespace nodes.-->
<content>
<children includes="label|hint"/>
<html:div class="-moz-xforms-select1-popup" anonid="popup"
onmouseover="this.parentNode.shouldHandleBlur = false;
this.parentNode.mouseOver(event);"
onmouseup="this.parentNode.mouseUp(event);"
onmouseout="this.parentNode.shouldHandleBlur = true;">
<children/>
</html:div>
<html:span class="-moz-select1-container"
anonid="container"><html:input
class="-moz-xforms-select1-input xf-value"
@ -77,9 +70,17 @@
onmouseup="this.parentNode.parentNode.shouldHandleBlur = true;"
onclick="this.parentNode.parentNode.togglePopup();
this.previousSibling.focus();"
/></html:span></content>
/></html:span>
<html:div mozType:comboboxpopup="true" anonid="popup"
onmouseover="this.parentNode.shouldHandleBlur = false;
this.parentNode.mouseOver(event);"
onmouseup="this.parentNode.mouseUp(event);"
onmouseout="this.parentNode.shouldHandleBlur = true;">
<children/>
</html:div>
</content>
<implementation implements="nsIXFormsUIWidget, nsIXFormsNSSelect1Element, nsIXFormsNSEditableElement, nsIXFormsComboboxUIWidget">
<implementation implements="nsIXFormsNSSelect1Element, nsIXFormsNSEditableElement, nsIXFormsComboboxUIWidget, nsIAccessibleProvider">
<!-- nsIXFormsNSEditableElement -->
<property name="editor" readonly="true"
@ -120,6 +121,13 @@
</setter>
</property>
<!-- nsIAccessibleProvider -->
<property name="accessibleType" readonly="true">
<getter>
return Components.interfaces.nsIAccessibleProvider.XFormsSelectCombobox;
</getter>
</property>
<field name="_inputField">null</field>
<field name="_dropMarker">null</field>
<field name="_popup">null</field>
@ -201,6 +209,12 @@
if (this._selected) {
// Remove extra white space characters from the beginning of the label.
this.inputField.value = this._selected.labelText.replace(/^[\s\n]+/, "");
// Fire 'ValueChange' event. This event is used by accessible
// module.
var event = this.ownerDocument.createEvent("Events");
event.initEvent("ValueChange", false, false);
this.dispatchEvent(event);
}
]]>
</body>
@ -1176,7 +1190,13 @@
</html:div>
</content>
<implementation>
<implementation implements="nsIAccessibleProvider">
<property name="accessibleType" readonly="true">
<getter>
return Components.interfaces.nsIAccessibleProvider.XFormsItemCombobox;
</getter>
</property>
<field name="_content">null</field>
<property name="content" readonly="true">
<getter>

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

@ -755,5 +755,21 @@
</implementation>
</binding>
<!-- POPUP for MINIMAL SELECT1 -->
<binding id="comboboxpopup">
<resources>
<stylesheet src="chrome://xforms/skin/widgets-xhtml.css"/>
</resources>
<implementation implements="nsIAccessibleProvider">
<property name="accessibleType" readonly="true">
<getter>
return Components.interfaces.nsIAccessibleProvider.XFormsComboboxPopupWidget;
</getter>
</property>
</implementation>
</binding>
</bindings>

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

@ -498,6 +498,8 @@ select1 itemset, select itemset {
}
/* choices widget */
html|*:root select1:not([appearance]) choices,
html|*:root select1[appearance="minimal] choices,
select[appearance='full'] choices,
select1[appearance='full'] choices {
-moz-binding: url('chrome://xforms/content/selects.xml#choices');
@ -759,3 +761,7 @@ xul|*:root xul|dropmarker[mozType|dropmarker] {
-moz-binding: url('chrome://xforms/content/widgets-xul.xml#dropmarker');
}
html|*:root html|div[mozType|comboboxpopup] {
-moz-binding: url('chrome://xforms/content/widgets-xhtml.xml#comboboxpopup');
}

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

@ -135,3 +135,22 @@ input[mozType|dropmarker]:active:hover {
border-style: outset;
}
/* combobox popup (used inside minimal select1) */
div[mozType|comboboxpopup="true"] {
border-width: 1px;
top: 0px;
left: 0px;
border: 1px outset black !important;
background-color: -moz-Field;
font: -moz-list;
text-align: start;
visibility: hidden;
overflow-y: auto;
overflow-x: hidden;
position: absolute;
-moz-user-select: none;
z-index: 2147482647;
cursor: default;
}