summaryrefslogtreecommitdiffstats
path: root/accessible/base/TreeWalker.h
blob: 9093d8187f87370038af80f6efa0a886873f5875 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_a11y_TreeWalker_h_
#define mozilla_a11y_TreeWalker_h_

#include "mozilla/Attributes.h"
#include <stdint.h>
#include "mozilla/dom/ChildIterator.h"
#include "nsCOMPtr.h"

class nsIContent;

namespace mozilla {
namespace a11y {

class LocalAccessible;
class DocAccessible;

/**
 * This class is used to walk the DOM tree to create accessible tree.
 */
class TreeWalker final {
 public:
  enum {
    // used to walk the existing tree of the given node
    eWalkCache = 1,
    // used to walk the context tree starting from given node
    eWalkContextTree = 2 | eWalkCache,
    eScoped = 4
  };

  /**
   * Used to navigate and create if needed the accessible children.
   */
  explicit TreeWalker(LocalAccessible* aContext);

  /**
   * Used to navigate the accessible children relative to the anchor.
   *
   * @param aContext [in] container accessible for the given node, used to
   *                   define accessible context
   * @param aAnchorNode [in] the node the search will be prepared relative to
   * @param aFlags   [in] flags (see enum above)
   */
  TreeWalker(LocalAccessible* aContext, nsIContent* aAnchorNode,
             uint32_t aFlags = eWalkCache);

  /**
   * Navigates the accessible children within the anchor node subtree.
   */
  TreeWalker(DocAccessible* aDocument, nsIContent* aAnchorNode);

  ~TreeWalker();

  /**
   * Resets the walker state, and sets the given node as an anchor. Returns a
   * first accessible element within the node including the node itself.
   */
  LocalAccessible* Scope(nsIContent* aAnchorNode);

  /**
   * Resets the walker state.
   */
  void Reset() {
    mPhase = eAtStart;
    mStateStack.Clear();
    mARIAOwnsIdx = 0;
  }

  /**
   * Sets the walker state to the given child node if it's within the anchor.
   */
  bool Seek(nsIContent* aChildNode);

  /**
   * Return the next/prev accessible.
   *
   * @note Returned accessible is bound to the document, if the accessible is
   *       rejected during tree creation then the caller should be unbind it
   *       from the document.
   */
  LocalAccessible* Next();
  LocalAccessible* Prev();

  LocalAccessible* Context() const { return mContext; }
  DocAccessible* Document() const { return mDoc; }

 private:
  TreeWalker();
  TreeWalker(const TreeWalker&);
  TreeWalker& operator=(const TreeWalker&);

  /**
   * Return an accessible for the given node if any.
   */
  LocalAccessible* AccessibleFor(nsIContent* aNode, uint32_t aFlags,
                                 bool* aSkipSubtree);

  /**
   * Create new state for the given node and push it on top of stack / at bottom
   * of stack.
   *
   * @note State stack is used to navigate up/down the DOM subtree during
   *        accessible children search.
   */
  dom::AllChildrenIterator* PushState(nsIContent* aContent,
                                      bool aStartAtBeginning) {
    return mStateStack.AppendElement(
        dom::AllChildrenIterator(aContent, mChildFilter, aStartAtBeginning));
  }
  dom::AllChildrenIterator* PrependState(nsIContent* aContent,
                                         bool aStartAtBeginning) {
    return mStateStack.InsertElementAt(
        0, dom::AllChildrenIterator(aContent, mChildFilter, aStartAtBeginning));
  }

  /**
   * Pop state from stack.
   */
  dom::AllChildrenIterator* PopState();

  DocAccessible* mDoc;
  LocalAccessible* mContext;
  nsIContent* mAnchorNode;

  AutoTArray<dom::AllChildrenIterator, 20> mStateStack;
  uint32_t mARIAOwnsIdx;

  int32_t mChildFilter;
  uint32_t mFlags;

  enum Phase { eAtStart, eAtDOM, eAtARIAOwns, eAtEnd };
  Phase mPhase;
};

}  // namespace a11y
}  // namespace mozilla

#endif  // mozilla_a11y_TreeWalker_h_