michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "HTMLListAccessible.h" michael@0: michael@0: #include "DocAccessible.h" michael@0: #include "nsAccUtils.h" michael@0: #include "Role.h" michael@0: #include "States.h" michael@0: michael@0: #include "nsBlockFrame.h" michael@0: #include "nsBulletFrame.h" michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::a11y; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // HTMLListAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: NS_IMPL_ISUPPORTS_INHERITED0(HTMLListAccessible, HyperTextAccessible) michael@0: michael@0: role michael@0: HTMLListAccessible::NativeRole() michael@0: { michael@0: if (mContent->Tag() == nsGkAtoms::dl) michael@0: return roles::DEFINITION_LIST; michael@0: michael@0: return roles::LIST; michael@0: } michael@0: michael@0: uint64_t michael@0: HTMLListAccessible::NativeState() michael@0: { michael@0: return HyperTextAccessibleWrap::NativeState() | states::READONLY; michael@0: } michael@0: michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // HTMLLIAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: HTMLLIAccessible:: michael@0: HTMLLIAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: HyperTextAccessibleWrap(aContent, aDoc), mBullet(nullptr) michael@0: { michael@0: mType = eHTMLLiType; michael@0: michael@0: nsBlockFrame* blockFrame = do_QueryFrame(GetFrame()); michael@0: if (blockFrame && blockFrame->HasBullet()) { michael@0: mBullet = new HTMLListBulletAccessible(mContent, mDoc); michael@0: Document()->BindToDocument(mBullet, nullptr); michael@0: } michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS_INHERITED0(HTMLLIAccessible, HyperTextAccessible) michael@0: michael@0: void michael@0: HTMLLIAccessible::Shutdown() michael@0: { michael@0: mBullet = nullptr; michael@0: michael@0: HyperTextAccessibleWrap::Shutdown(); michael@0: } michael@0: michael@0: role michael@0: HTMLLIAccessible::NativeRole() michael@0: { michael@0: if (mContent->Tag() == nsGkAtoms::dt) michael@0: return roles::TERM; michael@0: michael@0: return roles::LISTITEM; michael@0: } michael@0: michael@0: uint64_t michael@0: HTMLLIAccessible::NativeState() michael@0: { michael@0: return HyperTextAccessibleWrap::NativeState() | states::READONLY; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: HTMLLIAccessible::GetBounds(int32_t* aX, int32_t* aY, michael@0: int32_t* aWidth, int32_t* aHeight) michael@0: { michael@0: nsresult rv = AccessibleWrap::GetBounds(aX, aY, aWidth, aHeight); michael@0: if (NS_FAILED(rv) || !mBullet || mBullet->IsInside()) michael@0: return rv; michael@0: michael@0: int32_t bulletX = 0, bulletY = 0, bulletWidth = 0, bulletHeight = 0; michael@0: rv = mBullet->GetBounds(&bulletX, &bulletY, &bulletWidth, &bulletHeight); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: *aWidth += *aX - bulletX; michael@0: *aX = bulletX; // Move x coordinate of list item over to cover bullet as well michael@0: return NS_OK; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // HTMLLIAccessible: public michael@0: michael@0: void michael@0: HTMLLIAccessible::UpdateBullet(bool aHasBullet) michael@0: { michael@0: if (aHasBullet == !!mBullet) { michael@0: NS_NOTREACHED("Bullet and accessible are in sync already!"); michael@0: return; michael@0: } michael@0: michael@0: DocAccessible* document = Document(); michael@0: if (aHasBullet) { michael@0: mBullet = new HTMLListBulletAccessible(mContent, mDoc); michael@0: document->BindToDocument(mBullet, nullptr); michael@0: InsertChildAt(0, mBullet); michael@0: } else { michael@0: RemoveChild(mBullet); michael@0: document->UnbindFromDocument(mBullet); michael@0: mBullet = nullptr; michael@0: } michael@0: michael@0: // XXXtodo: fire show/hide and reorder events. That's hard to make it michael@0: // right now because coalescence happens by DOM node. michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // HTMLLIAccessible: Accessible protected michael@0: michael@0: void michael@0: HTMLLIAccessible::CacheChildren() michael@0: { michael@0: if (mBullet) michael@0: AppendChild(mBullet); michael@0: michael@0: // Cache children from subtree. michael@0: AccessibleWrap::CacheChildren(); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // HTMLListBulletAccessible michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: HTMLListBulletAccessible:: michael@0: HTMLListBulletAccessible(nsIContent* aContent, DocAccessible* aDoc) : michael@0: LeafAccessible(aContent, aDoc) michael@0: { michael@0: mStateFlags |= eSharedNode; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // HTMLListBulletAccessible: Accessible michael@0: michael@0: nsIFrame* michael@0: HTMLListBulletAccessible::GetFrame() const michael@0: { michael@0: nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame()); michael@0: return blockFrame ? blockFrame->GetBullet() : nullptr; michael@0: } michael@0: michael@0: ENameValueFlag michael@0: HTMLListBulletAccessible::Name(nsString &aName) michael@0: { michael@0: aName.Truncate(); michael@0: michael@0: // Native anonymous content, ARIA can't be used. Get list bullet text. michael@0: nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame()); michael@0: if (blockFrame) { michael@0: blockFrame->GetBulletText(aName); michael@0: michael@0: // Append space otherwise bullets are jammed up against list text. michael@0: aName.Append(' '); michael@0: } michael@0: michael@0: return eNameOK; michael@0: } michael@0: michael@0: role michael@0: HTMLListBulletAccessible::NativeRole() michael@0: { michael@0: return roles::STATICTEXT; michael@0: } michael@0: michael@0: uint64_t michael@0: HTMLListBulletAccessible::NativeState() michael@0: { michael@0: return LeafAccessible::NativeState() | states::READONLY; michael@0: } michael@0: michael@0: void michael@0: HTMLListBulletAccessible::AppendTextTo(nsAString& aText, uint32_t aStartOffset, michael@0: uint32_t aLength) michael@0: { michael@0: nsAutoString bulletText; michael@0: nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame()); michael@0: if (blockFrame) michael@0: blockFrame->GetBulletText(bulletText); michael@0: michael@0: aText.Append(Substring(bulletText, aStartOffset, aLength)); michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // HTMLListBulletAccessible: public michael@0: michael@0: bool michael@0: HTMLListBulletAccessible::IsInside() const michael@0: { michael@0: nsBlockFrame* blockFrame = do_QueryFrame(mContent->GetPrimaryFrame()); michael@0: return blockFrame ? blockFrame->HasInsideBullet() : false; michael@0: }