1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef mozilla_a11y_relation_h_
8 #define mozilla_a11y_relation_h_
9 
10 #include "AccIterator.h"
11 
12 #include <memory>
13 
14 namespace mozilla {
15 namespace a11y {
16 
17 /**
18  * A collection of relation targets of a certain type.  Targets are computed
19  * lazily while enumerating.
20  */
21 class Relation {
22  public:
Relation()23   Relation() : mFirstIter(nullptr), mLastIter(nullptr) {}
24 
Relation(AccIterable * aIter)25   explicit Relation(AccIterable* aIter) : mFirstIter(aIter), mLastIter(aIter) {}
26 
Relation(Accessible * aAcc)27   explicit Relation(Accessible* aAcc)
28       : mFirstIter(nullptr), mLastIter(nullptr) {
29     AppendTarget(aAcc);
30   }
31 
Relation(DocAccessible * aDocument,nsIContent * aContent)32   Relation(DocAccessible* aDocument, nsIContent* aContent)
33       : mFirstIter(nullptr), mLastIter(nullptr) {
34     AppendTarget(aDocument, aContent);
35   }
36 
Relation(Relation && aOther)37   Relation(Relation&& aOther)
38       : mFirstIter(Move(aOther.mFirstIter)), mLastIter(aOther.mLastIter) {
39     aOther.mLastIter = nullptr;
40   }
41 
42   Relation& operator=(Relation&& aRH) {
43     mFirstIter = Move(aRH.mFirstIter);
44     mLastIter = aRH.mLastIter;
45     aRH.mLastIter = nullptr;
46     return *this;
47   }
48 
AppendIter(AccIterable * aIter)49   inline void AppendIter(AccIterable* aIter) {
50     if (mLastIter)
51       mLastIter->mNextIter.reset(aIter);
52     else
53       mFirstIter.reset(aIter);
54 
55     mLastIter = aIter;
56   }
57 
58   /**
59    * Append the given accessible to the set of related accessibles.
60    */
AppendTarget(Accessible * aAcc)61   inline void AppendTarget(Accessible* aAcc) {
62     if (aAcc) AppendIter(new SingleAccIterator(aAcc));
63   }
64 
65   /**
66    * Append the one accessible for this content node to the set of related
67    * accessibles.
68    */
AppendTarget(DocAccessible * aDocument,nsIContent * aContent)69   void AppendTarget(DocAccessible* aDocument, nsIContent* aContent) {
70     if (aContent) AppendTarget(aDocument->GetAccessible(aContent));
71   }
72 
73   /**
74    * compute and return the next related accessible.
75    */
Next()76   inline Accessible* Next() {
77     Accessible* target = nullptr;
78 
79     while (mFirstIter && !(target = mFirstIter->Next()))
80       mFirstIter = std::move(mFirstIter->mNextIter);
81 
82     if (!mFirstIter) mLastIter = nullptr;
83 
84     return target;
85   }
86 
87  private:
88   Relation& operator=(const Relation&) = delete;
89   Relation(const Relation&) = delete;
90 
91   std::unique_ptr<AccIterable> mFirstIter;
92   AccIterable* mLastIter;
93 };
94 
95 }  // namespace a11y
96 }  // namespace mozilla
97 
98 #endif
99