Bug 354728. Support nsIAccessibleText/nsIAccessibleEditableText for xforms controls. Patch by Alexander Surkov. r=aaronlev, r=aaronr, sr=neil

git-svn-id: svn://10.0.0.236/trunk@214752 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
aaronleventhal%moonset.net 2006-11-06 02:50:37 +00:00
parent 0968008d00
commit d0f7a19726
15 changed files with 265 additions and 52 deletions

View File

@ -50,6 +50,7 @@ LIBXUL_LIBRARY = 1
REQUIRES = content \
docshell \
dom \
editor \
gfx \
intl \
layout \
@ -78,5 +79,6 @@ include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES = \
-I$(srcdir) \
-I$(srcdir)/../base \
-I$(srcdir)/../html \
$(NULL)

View File

@ -43,6 +43,7 @@
#include "nsIDOMElement.h"
#include "nsIDOMNodeList.h"
#include "nsIXFormsUtilityService.h"
#include "nsIPlaintextEditor.h"
// nsXFormsAccessible
@ -50,7 +51,7 @@ nsIXFormsUtilityService *nsXFormsAccessible::sXFormsService = nsnull;
nsXFormsAccessible::
nsXFormsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
nsAccessibleWrap(aNode, aShell)
nsHyperTextAccessible(aNode, aShell)
{
if (!sXFormsService) {
nsresult rv = CallGetService("@mozilla.org/xforms-utility-service;1",
@ -126,7 +127,7 @@ nsXFormsAccessible::GetState(PRUint32 *aState)
rv = sXFormsService->IsValid(mDOMNode, &isValid);
NS_ENSURE_SUCCESS(rv, rv);
rv = nsAccessible::GetState(aState);
rv = nsHyperTextAccessible::GetState(aState);
NS_ENSURE_SUCCESS(rv, rv);
if (!isRelevant)
@ -209,3 +210,83 @@ nsXFormsContainerAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonCh
return NS_OK;
}
// nsXFormsEditableAccessible
nsXFormsEditableAccessible::
nsXFormsEditableAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell):
nsXFormsAccessible(aNode, aShell)
{
}
NS_IMETHODIMP
nsXFormsEditableAccessible::GetExtState(PRUint32 *aExtState)
{
NS_ENSURE_ARG_POINTER(aExtState);
*aExtState = 0;
nsresult rv = nsXFormsAccessible::GetExtState(aExtState);
NS_ENSURE_SUCCESS(rv, rv);
if (!mEditor)
return NS_OK;
PRBool isReadonly = PR_FALSE;
rv = sXFormsService->IsReadonly(mDOMNode, &isReadonly);
NS_ENSURE_SUCCESS(rv, rv);
if (!isReadonly) {
PRBool isRelevant = PR_FALSE;
rv = sXFormsService->IsRelevant(mDOMNode, &isRelevant);
NS_ENSURE_SUCCESS(rv, rv);
if (isRelevant) {
*aExtState |= EXT_STATE_EDITABLE | EXT_STATE_SELECTABLE_TEXT;
}
}
PRUint32 flags;
mEditor->GetFlags(&flags);
if (flags & nsIPlaintextEditor::eEditorSingleLineMask)
*aExtState |= EXT_STATE_SINGLE_LINE;
else
*aExtState |= EXT_STATE_MULTI_LINE;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsEditableAccessible::Init()
{
nsCOMPtr<nsIEditor> editor;
sXFormsService->GetEditor(mDOMNode, getter_AddRefs(editor));
SetEditor(editor);
return nsXFormsAccessible::Init();
}
NS_IMETHODIMP
nsXFormsEditableAccessible::Shutdown()
{
SetEditor(nsnull);
return nsXFormsAccessible::Shutdown();
}
already_AddRefed<nsIEditor>
nsXFormsEditableAccessible::GetEditor()
{
nsIEditor *editor = mEditor;
NS_IF_ADDREF(editor);
return editor;
}
void
nsXFormsEditableAccessible::SetEditor(nsIEditor *aEditor)
{
if (mEditor)
mEditor->RemoveEditActionListener(this);
mEditor = aEditor;
if (mEditor)
mEditor->AddEditActionListener(this);
}

View File

@ -39,7 +39,7 @@
#ifndef _nsXFormsAccessible_H_
#define _nsXFormsAccessible_H_
#include "nsAccessibleWrap.h"
#include "nsHyperTextAccessible.h"
#include "nsIXFormsUtilityService.h"
#define NS_NAMESPACE_XFORMS "http://www.w3.org/2002/xforms"
@ -49,7 +49,7 @@
* XForms hint and XForms label elements should have accessible object. This
* class is base class for accessible objects for these XForms elements.
*/
class nsXFormsAccessible : public nsAccessibleWrap
class nsXFormsAccessible : public nsHyperTextAccessible
{
public:
nsXFormsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
@ -110,5 +110,29 @@ public:
NS_IMETHOD GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren);
};
/**
* The class is base for accessible objects for XForms elements that have
* editable area.
*/
class nsXFormsEditableAccessible : public nsXFormsAccessible
{
public:
nsXFormsEditableAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell);
NS_IMETHOD GetExtState(PRUint32 *aState);
NS_IMETHOD Init();
NS_IMETHOD Shutdown();
protected:
virtual void SetEditor(nsIEditor *aEditor);
virtual already_AddRefed<nsIEditor> GetEditor();
private:
nsCOMPtr<nsIEditor> mEditor;
};
#endif

View File

@ -147,7 +147,7 @@ nsXFormsTriggerAccessible::DoAction(PRUint8 aIndex)
nsXFormsInputAccessible::
nsXFormsInputAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell):
nsXFormsAccessible(aNode, aShell)
nsXFormsEditableAccessible(aNode, aShell)
{
}
@ -160,36 +160,6 @@ nsXFormsInputAccessible::GetRole(PRUint32 *aRole)
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInputAccessible::GetExtState(PRUint32 *aExtState)
{
NS_ENSURE_ARG_POINTER(aExtState);
*aExtState = 0;
NS_ENSURE_TRUE(mDOMNode, NS_ERROR_FAILURE);
nsresult rv = nsXFormsAccessible::GetExtState(aExtState);
NS_ENSURE_SUCCESS(rv, rv);
PRBool state = PR_FALSE;
rv = sXFormsService->IsReadonly(mDOMNode, &state);
NS_ENSURE_SUCCESS(rv, rv);
if (!state) {
rv = sXFormsService->IsRelevant(mDOMNode, &state);
NS_ENSURE_SUCCESS(rv, rv);
if (state) {
*aExtState |= EXT_STATE_EDITABLE | EXT_STATE_SELECTABLE_TEXT;
}
}
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
if (content->NodeInfo()->Equals(nsAccessibilityAtoms::textarea))
*aExtState |= EXT_STATE_MULTI_LINE;
else
*aExtState |= EXT_STATE_SINGLE_LINE;
}
NS_IMETHODIMP
nsXFormsInputAccessible::GetNumActions(PRUint8* aCount)
{

View File

@ -86,18 +86,14 @@ public:
/**
* Accessible object for xforms:input and xforms:textarea.
*
* XXX: nsXFormsInputAccessible should implement nsIAccessibleEditableText
* interface.
*/
class nsXFormsInputAccessible : public nsXFormsAccessible
class nsXFormsInputAccessible : public nsXFormsEditableAccessible
{
public:
nsXFormsInputAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell);
NS_IMETHOD GetRole(PRUint32 *aRole);
NS_IMETHOD GetExtState(PRUint32 *aState);
NS_IMETHOD GetNumActions(PRUint8 *aCount);
NS_IMETHOD GetActionName(PRUint8 aIndex, nsAString& aName);
NS_IMETHOD DoAction(PRUint8 aIndex);

View File

@ -39,8 +39,10 @@
#ifndef nsIXFormsUtilityService_h
#define nsIXFormsUtilityService_h
#include "nsIDOMNode.h"
#include "nsISupports.h"
class nsIDOMNode;
class nsIEditor;
/* For IDL files that don't want to include root IDL files. */
#ifndef NS_NO_VTABLE
@ -48,10 +50,10 @@
#endif
/* nsIXFormsUtilityService */
#define NS_IXFORMSUTILITYSERVICE_IID_STR "aad08d14-dff8-4acb-bcd0-b6376295c82f"
#define NS_IXFORMSUTILITYSERVICE_IID_STR "43ad19a6-5639-4b05-8305-1eb729063912"
#define NS_IXFORMSUTILITYSERVICE_IID \
{ 0xaad08d14, 0xdff8, 0x4acb, \
{ 0xbc, 0xd0, 0xb6, 0x37, 0x62, 0x95, 0xc8, 0x2f } }
{ 0x43ad19a6, 0x5639, 0x4b05, \
{ 0x83, 0x5, 0x1e, 0xb7, 0x29, 0x6, 0x39, 0x12 } }
/**
* Private interface implemented by the nsXFormsUtilityService in XForms
@ -123,6 +125,12 @@ public:
* given element is not xforms:range.
*/
NS_IMETHOD GetRangeStep(nsIDOMNode *aElement, nsAString& aValue) = 0;
/**
* Return nsIEditor for xforms element if element is editable, null if it is
* not editable. Failure if given element doesn't support editing.
*/
NS_IMETHOD GetEditor(nsIDOMNode *aElemenet, nsIEditor **aEditor) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIXFormsUtilityService,

View File

@ -150,6 +150,7 @@ XPIDLSRCS = \
nsIXFormsCopyElement.idl \
nsIXFormsEphemeralMessageUI.idl \
nsIXFormsRangeConditionAccessors.idl \
nsIXFormsNSEditableElement.idl \
nsIXFormsXPathFunctions.idl \
$(NULL)

View File

@ -0,0 +1,60 @@
/* -*- 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
* Mozilla Foundation.
* 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 of 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 "nsISupports.idl"
interface nsIEditor;
/**
* Interface should be implemented by XFroms elements that support editing, i.e.
* that contain editor, for example, HTML input.
*
* For example, XForms select1 implements this interface because if it has
* attribute selection='open' then it contains HTML input element that is used
* to specify value of XForms select1. So that getEditor method returns
* nsIEdtior for HTML input element if select1 has open selection or null
* if it hasn't.
*/
[scriptable, uuid(4b609c89-5f7a-40db-83ae-6bab44a2c7e2)]
interface nsIXFormsNSEditableElement : nsISupports
{
/**
* Returns editor if element is editable. Otherwise returns nsnull.
*/
nsIEditor getEditor();
};

View File

@ -44,6 +44,7 @@
#include "nsIXFormsRangeConditionAccessors.h"
#include "nsIXFormsRangeAccessors.h"
#include "nsIXFormsUIWidget.h"
#include "nsIXFormsNSEditableElement.h"
#include "nsXFormsUtils.h"
NS_IMPL_ISUPPORTS1(nsXFormsUtilityService, nsIXFormsUtilityService)
@ -166,3 +167,15 @@ nsXFormsUtilityService::GetRangeStep(nsIDOMNode *aElement, nsAString& aValue)
return raccessors->GetRangeStep(aValue);
}
NS_IMETHODIMP
nsXFormsUtilityService::GetEditor(nsIDOMNode *aElement, nsIEditor **aEditor)
{
NS_ENSURE_ARG(aElement);
NS_ENSURE_ARG_POINTER(aEditor);
nsCOMPtr<nsIXFormsNSEditableElement> editable(do_QueryInterface(aElement));
NS_ENSURE_TRUE(editable, NS_ERROR_FAILURE);
return editable->GetEditor(aEditor);
}

View File

@ -62,5 +62,7 @@ public:
NS_IMETHOD GetRangeStart(nsIDOMNode *aElement, nsAString& aValue);
NS_IMETHOD GetRangeEnd(nsIDOMNode *aElement, nsAString& aValue);
NS_IMETHOD GetRangeStep(nsIDOMNode *aElement, nsAString& aValue);
NS_IMETHOD GetEditor(nsIDOMNode *aElement, nsIEditor **aEditor);
};

View File

@ -58,9 +58,27 @@
xmlns:mozType="http://www.mozilla.org/projects/xforms/2005/type">
<!-- INPUT: base widget for input: <default>, textarea: <default> and
secret: <default> controls.
Binding assumes getControlElement returns object that has properties
required by 'xformswidget-input-base' binding plus 'editor' property to
get nsIEditor for embedded editor. You shouldn't use this binding if xforms
input element isn't supposed to have an editor.
-->
<binding id="xformswidget-input-base"
extends="chrome://xforms/content/input.xml#xformswidget-input-base">
<implementation implements="nsIXFormsNSEditableElement">
<property name="editor" readonly="true"
onget="return this.control.editor;"/>
</implementation>
</binding>
<!-- INPUT: <DEFAULT> -->
<binding id="xformswidget-input"
extends="chrome://xforms/content/input.xml#xformswidget-input-base">
extends="#xformswidget-input-base">
<content>
<children includes="label"/>
<html:input class="xf-value" anonid="control" xbl:inherits="accesskey"/>
@ -187,7 +205,7 @@
<!-- INPUT: DATE -->
<binding id="xformswidget-input-date"
extends="chrome://xforms/content/input.xml#xformswidget-input-base">
extends="#xformswidget-input-base">
<content>
<children includes="label"/>
<html:input anonid="control" xbl:inherits="accesskey" size="10"
@ -644,7 +662,7 @@
<!-- SECRET: <DEFAULT> -->
<binding id="xformswidget-secret"
extends="chrome://xforms/content/input-xhtml.xml#xformswidget-input">
extends="#xformswidget-input">
<content>
<children includes="label"/>
<html:input anonid="control" xbl:inherits="accesskey" type="password"/>
@ -663,7 +681,7 @@
<!-- TEXTAREA: <DEFAULT> -->
<binding id="xformswidget-textarea"
extends="chrome://xforms/content/input.xml#xformswidget-input-base">
extends="#xformswidget-input-base">
<content>
<children includes="label"/>
<html:textarea class="xf-value" anonid="control"

View File

@ -52,12 +52,21 @@
<!-- INPUT: base widget for input: <default>, textarea: <default> and
secret: <default> controls
secret: <default> controls.
Binding assumes getControlElement returns object that has properties
required by 'xformswidget-input-base' binding plus 'editor' property to
get nsIEditor for embedded editor. You shouldn't use this binding if xforms
input element isn't supposed to have an editor.
-->
<binding id="xformswidget-input-base"
extends="chrome://xforms/content/input.xml#xformswidget-input-base">
<implementation>
<implementation implements="nsIXFormsNSEditableElement">
<property name="editor" readonly="true"
onget="return this.control.editor;"/>
<method name="getControlElement">
<body>
var control = this.ownerDocument.

View File

@ -404,6 +404,15 @@
</content>
<implementation>
<property name="editor" readonly="true">
<getter>
if (!this.control.hasAttribute("editable"))
return null;
return this.control.editor;
</getter>
</property>
<method name="removeAllItems">
<body>
var popup = this.control.menupopup;

View File

@ -53,6 +53,9 @@
readonly - set/get readonly state
editor - return nsIEditor object if native widget contains editor, otherwise
return null
appendItem(label, value, group) - appends item, returns item control
@param label - label control
@param value - item's value
@ -91,7 +94,10 @@
<binding id="xformswidget-selectcontrols-base"
extends="chrome://xforms/content/xforms.xml#xformswidget-base">
<implementation implements="nsIXFormsUIWidget">
<implementation implements="nsIXFormsUIWidget, nsIXFormsNSEditableElement">
<property name="editor" readonly="true"
onget="return this.control.editor;"/>
<!-- Make sure we don't refresh while we are refreshing (race condition).
This happens when we are inside a repeat for example. We use the
@ -1070,6 +1076,15 @@
-->
<binding id="controlwidget-base">
<implementation>
<!-- Return nsIEditor object if native widget contains editor.
Of the widgets that extend this binding, only the
xforms:select1[appearance='minimal'] implementation for XUL has an
editor.
-->
<property name="editor" readonly="true"
onget="return null"/>
<!-- Return parent xf:select/xf:select1 control. -->
<property name="parentControl" readonly="true">
<getter>

View File

@ -78,7 +78,12 @@
this.previousSibling.focus();"
/></html:span></content>
<implementation implements="nsIXFormsUIWidget, nsIXFormsNSSelect1Element">
<implementation implements="nsIXFormsUIWidget, nsIXFormsNSSelect1Element, nsIXFormsNSEditableElement">
<!-- nsIXFormsNSEditableElement -->
<property name="editor" readonly="true"
onget="return this.selectionOpen ? this.inputField.editor : null;"/>
<!-- nsIXFormsNSSelect1Element -->
<property name="selectedItem">
<getter>