LCOV - code coverage report
Current view: top level - accessible/base - AccGroupInfo.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 118 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : #include "AccGroupInfo.h"
       6             : #include "nsAccUtils.h"
       7             : 
       8             : #include "Role.h"
       9             : #include "States.h"
      10             : 
      11             : using namespace mozilla::a11y;
      12             : 
      13           0 : AccGroupInfo::AccGroupInfo(Accessible* aItem, role aRole) :
      14           0 :   mPosInSet(0), mSetSize(0), mParent(nullptr), mItem(aItem), mRole(aRole)
      15             : {
      16           0 :   MOZ_COUNT_CTOR(AccGroupInfo);
      17           0 :   Update();
      18           0 : }
      19             : 
      20             : void
      21           0 : AccGroupInfo::Update()
      22             : {
      23           0 :   Accessible* parent = mItem->Parent();
      24           0 :   if (!parent)
      25           0 :     return;
      26             : 
      27           0 :   int32_t indexInParent = mItem->IndexInParent();
      28           0 :   uint32_t siblingCount = parent->ChildCount();
      29           0 :   if (indexInParent == -1 ||
      30           0 :       indexInParent >= static_cast<int32_t>(siblingCount)) {
      31           0 :     NS_ERROR("Wrong index in parent! Tree invalidation problem.");
      32           0 :     return;
      33             :   }
      34             : 
      35           0 :   int32_t level = nsAccUtils::GetARIAOrDefaultLevel(mItem);
      36             : 
      37             :   // Compute position in set.
      38           0 :   mPosInSet = 1;
      39           0 :   for (int32_t idx = indexInParent - 1; idx >= 0 ; idx--) {
      40           0 :     Accessible* sibling = parent->GetChildAt(idx);
      41           0 :     roles::Role siblingRole = sibling->Role();
      42             : 
      43             :     // If the sibling is separator then the group is ended.
      44           0 :     if (siblingRole == roles::SEPARATOR)
      45           0 :       break;
      46             : 
      47             :     // If sibling is not visible and hasn't the same base role.
      48           0 :     if (BaseRole(siblingRole) != mRole || sibling->State() & states::INVISIBLE)
      49           0 :       continue;
      50             : 
      51             :     // Check if it's hierarchical flatten structure, i.e. if the sibling
      52             :     // level is lesser than this one then group is ended, if the sibling level
      53             :     // is greater than this one then the group is split by some child elements
      54             :     // (group will be continued).
      55           0 :     int32_t siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling);
      56           0 :     if (siblingLevel < level) {
      57           0 :       mParent = sibling;
      58           0 :       break;
      59             :     }
      60             : 
      61             :     // Skip subset.
      62           0 :     if (siblingLevel > level)
      63           0 :       continue;
      64             : 
      65             :     // If the previous item in the group has calculated group information then
      66             :     // build group information for this item based on found one.
      67           0 :     if (sibling->mBits.groupInfo) {
      68           0 :       mPosInSet += sibling->mBits.groupInfo->mPosInSet;
      69           0 :       mParent = sibling->mBits.groupInfo->mParent;
      70           0 :       mSetSize = sibling->mBits.groupInfo->mSetSize;
      71           0 :       return;
      72             :     }
      73             : 
      74           0 :     mPosInSet++;
      75             :   }
      76             : 
      77             :   // Compute set size.
      78           0 :   mSetSize = mPosInSet;
      79             : 
      80           0 :   for (uint32_t idx = indexInParent + 1; idx < siblingCount; idx++) {
      81           0 :     Accessible* sibling = parent->GetChildAt(idx);
      82             : 
      83           0 :     roles::Role siblingRole = sibling->Role();
      84             : 
      85             :     // If the sibling is separator then the group is ended.
      86           0 :     if (siblingRole == roles::SEPARATOR)
      87           0 :       break;
      88             : 
      89             :     // If sibling is visible and has the same base role
      90           0 :     if (BaseRole(siblingRole) != mRole || sibling->State() & states::INVISIBLE)
      91           0 :       continue;
      92             : 
      93             :     // and check if it's hierarchical flatten structure.
      94           0 :     int32_t siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling);
      95           0 :     if (siblingLevel < level)
      96           0 :       break;
      97             : 
      98             :     // Skip subset.
      99           0 :     if (siblingLevel > level)
     100           0 :       continue;
     101             : 
     102             :     // If the next item in the group has calculated group information then
     103             :     // build group information for this item based on found one.
     104           0 :     if (sibling->mBits.groupInfo) {
     105           0 :       mParent = sibling->mBits.groupInfo->mParent;
     106           0 :       mSetSize = sibling->mBits.groupInfo->mSetSize;
     107           0 :       return;
     108             :     }
     109             : 
     110           0 :     mSetSize++;
     111             :   }
     112             : 
     113           0 :   if (mParent)
     114           0 :     return;
     115             : 
     116           0 :   roles::Role parentRole = parent->Role();
     117           0 :   if (ShouldReportRelations(mRole, parentRole))
     118           0 :     mParent = parent;
     119             : 
     120             :   // ARIA tree and list can be arranged by using ARIA groups to organize levels.
     121           0 :   if (parentRole != roles::GROUPING)
     122           0 :     return;
     123             : 
     124             :   // Way #1 for ARIA tree (not ARIA treegrid): previous sibling of a group is a
     125             :   // parent. In other words the parent of the tree item will be a group and
     126             :   // the previous tree item of the group is a conceptual parent of the tree
     127             :   // item.
     128           0 :   if (mRole == roles::OUTLINEITEM) {
     129           0 :     Accessible* parentPrevSibling = parent->PrevSibling();
     130           0 :     if (parentPrevSibling && parentPrevSibling->Role() == mRole) {
     131           0 :       mParent = parentPrevSibling;
     132           0 :       return;
     133             :     }
     134             :   }
     135             : 
     136             :   // Way #2 for ARIA list and tree: group is a child of an item. In other words
     137             :   // the parent of the item will be a group and containing item of the group is
     138             :   // a conceptual parent of the item.
     139           0 :   if (mRole == roles::LISTITEM || mRole == roles::OUTLINEITEM) {
     140           0 :     Accessible* grandParent = parent->Parent();
     141           0 :     if (grandParent && grandParent->Role() == mRole)
     142           0 :       mParent = grandParent;
     143             :   }
     144             : }
     145             : 
     146             : Accessible*
     147           0 : AccGroupInfo::FirstItemOf(Accessible* aContainer)
     148             : {
     149             :   // ARIA tree can be arranged by ARIA groups case #1 (previous sibling of a
     150             :   // group is a parent) or by aria-level.
     151           0 :   a11y::role containerRole = aContainer->Role();
     152           0 :   Accessible* item = aContainer->NextSibling();
     153           0 :   if (item) {
     154           0 :     if (containerRole == roles::OUTLINEITEM && item->Role() == roles::GROUPING)
     155           0 :       item = item->FirstChild();
     156             : 
     157           0 :     if (item) {
     158           0 :       AccGroupInfo* itemGroupInfo = item->GetGroupInfo();
     159           0 :       if (itemGroupInfo && itemGroupInfo->ConceptualParent() == aContainer)
     160           0 :         return item;
     161             :     }
     162             :   }
     163             : 
     164             :   // ARIA list and tree can be arranged by ARIA groups case #2 (group is
     165             :   // a child of an item).
     166           0 :   item = aContainer->LastChild();
     167           0 :   if (!item)
     168           0 :     return nullptr;
     169             : 
     170           0 :   if (item->Role() == roles::GROUPING &&
     171           0 :       (containerRole == roles::LISTITEM || containerRole == roles::OUTLINEITEM)) {
     172           0 :     item = item->FirstChild();
     173           0 :     if (item) {
     174           0 :       AccGroupInfo* itemGroupInfo = item->GetGroupInfo();
     175           0 :       if (itemGroupInfo && itemGroupInfo->ConceptualParent() == aContainer)
     176           0 :         return item;
     177             :     }
     178             :   }
     179             : 
     180             :   // Otherwise, it can be a direct child if the container is a list or tree.
     181           0 :   item = aContainer->FirstChild();
     182           0 :   if (ShouldReportRelations(item->Role(), containerRole))
     183           0 :     return item;
     184             : 
     185           0 :   return nullptr;
     186             : }
     187             : 
     188             : Accessible*
     189           0 : AccGroupInfo::NextItemTo(Accessible* aItem)
     190             : {
     191           0 :   AccGroupInfo* groupInfo = aItem->GetGroupInfo();
     192           0 :   if (!groupInfo)
     193           0 :     return nullptr;
     194             : 
     195             :   // If the item in middle of the group then search next item in siblings.
     196           0 :   if (groupInfo->PosInSet() >= groupInfo->SetSize())
     197           0 :     return nullptr;
     198             : 
     199           0 :   Accessible* parent = aItem->Parent();
     200           0 :   uint32_t childCount = parent->ChildCount();
     201           0 :   for (uint32_t idx = aItem->IndexInParent() + 1; idx < childCount; idx++) {
     202           0 :     Accessible* nextItem = parent->GetChildAt(idx);
     203           0 :     AccGroupInfo* nextGroupInfo = nextItem->GetGroupInfo();
     204           0 :     if (nextGroupInfo &&
     205           0 :         nextGroupInfo->ConceptualParent() == groupInfo->ConceptualParent()) {
     206           0 :       return nextItem;
     207             :     }
     208             :   }
     209             : 
     210           0 :   NS_NOTREACHED("Item in the middle of the group but there's no next item!");
     211           0 :   return nullptr;
     212             : }
     213             : 
     214             : bool
     215           0 : AccGroupInfo::ShouldReportRelations(role aRole, role aParentRole)
     216             : {
     217             :   // We only want to report hierarchy-based node relations for items in tree or
     218             :   // list form.  ARIA level/owns relations are always reported.
     219           0 :   if (aParentRole == roles::OUTLINE && aRole == roles::OUTLINEITEM)
     220           0 :     return true;
     221           0 :   if (aParentRole == roles::TREE_TABLE && aRole == roles::ROW)
     222           0 :     return true;
     223           0 :   if (aParentRole == roles::LIST && aRole == roles::LISTITEM)
     224           0 :     return true;
     225             : 
     226           0 :   return false;
     227             : }

Generated by: LCOV version 1.13