Added support for XCUITests (with a subset of checks). Add check for dynamic text check. Fixed typos and some APIs have been renamed for clarity. APIs imporvements: more flexible scan APIs that return result info. Improved accessibility auto enable code. Extracted GTX core logic into a C++ library and used Protobuf for cross platform execution.
diff --git a/Classes/GTXAccessibilityTree.m b/Classes/GTXAccessibilityTree.m
index 483d1c9..0c6c504 100644
--- a/Classes/GTXAccessibilityTree.m
+++ b/Classes/GTXAccessibilityTree.m
@@ -25,6 +25,19 @@
  */
 static const NSInteger kAccessibilityChildrenUpperBound = 50000;
 
+/**
+ * The class name for @c UIPickerTableView elements. Must be accessed via @c NSClassFromString
+ * because it is a private class.
+ */
+static NSString *const kUIPickerTableViewClassName = @"UIPickerTableView";
+
+/**
+ * The class name for accessibility children of @c UIPickerTableView elements. Must be accessed via
+ * @c NSClassFromString because it is a private class.
+ */
+static NSString *const kUIPickerTableViewAccessibilityElementClassName =
+    @"UITableViewCellAccessibilityElement";
+
 @implementation GTXAccessibilityTree {
   // A queue of elements to be visited.
   NSMutableArray *_queue;
@@ -62,7 +75,6 @@
   if (!nextInQueue) {
     return nil;
   }
-
   [_visitedElements addObject:nextInQueue];
   if ([nextInQueue respondsToSelector:@selector(isAccessibilityElement)]) {
     if (![nextInQueue isAccessibilityElement]) {
@@ -199,7 +211,33 @@
     isHiddenDueToFrame = frame.size.width == 0 || frame.size.height == 0;
   }
   return (isHidden || isAccessibilityHidden ||
-          (isHiddenDueToFrame && isHiddenDueToAccessibilityFrame));
+          (isHiddenDueToFrame && isHiddenDueToAccessibilityFrame) ||
+          [self gtx_isElementOffscreenPickerViewElement:element]);
+}
+
+/**
+ * Determines if the element represents an accessibility element in a @c UIPickerTableView, and the
+ * element is offscreen.
+ *
+ * @param element The accessibility element to check.
+ * @return @c YES if the element is an offscreen accessibility element whose container is a
+ *  @c UIPickerTableView, @c NO otherwise.
+ */
+- (BOOL)gtx_isElementOffscreenPickerViewElement:(id)element {
+  if (![element respondsToSelector:@selector(accessibilityFrame)] ||
+      ![element respondsToSelector:@selector(accessibilityContainer)]) {
+    return NO;
+  }
+  id accessibilityContainer = [element accessibilityContainer];
+  if ([accessibilityContainer isKindOfClass:NSClassFromString(kUIPickerTableViewClassName)] &&
+      [element isKindOfClass:NSClassFromString(kUIPickerTableViewAccessibilityElementClassName)]) {
+    CGRect containerAccessibilityFrame = [accessibilityContainer accessibilityFrame];
+    CGRect childAccessibilityFrame = [element accessibilityFrame];
+    if (!CGRectIntersectsRect(childAccessibilityFrame, containerAccessibilityFrame)) {
+      return YES;
+    }
+  }
+  return NO;
 }
 
 @end
diff --git a/Classes/GTXArtifactCollector.h b/Classes/GTXArtifactCollector.h
deleted file mode 100644
index 307aab9..0000000
--- a/Classes/GTXArtifactCollector.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright 2019 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-
-#import "GTXChecking.h"
-#import "GTXSnapshotContainer.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- *  A class to streamline snapshot collection for a given set of checks.
- */
-@interface GTXArtifactCollector : NSObject
-
-/**
- *  Initializes an artifact collector to work with the given set of @c checks.
- */
-- (instancetype)initWithChecks:(NSArray<id<GTXChecking>> *)checks;
-
-/**
- *  @return a snapshot container with all the artifact snapshots needed by the checks. This method
- *          must only be invoked on the main thread to allow for UI related artifacts to be
- *          collected.
- */
-- (GTXSnapshotContainer *)snapshot;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXArtifactCollector.m b/Classes/GTXArtifactCollector.m
deleted file mode 100644
index fe347ae..0000000
--- a/Classes/GTXArtifactCollector.m
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// Copyright 2019 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-
-#import "GTXArtifactCollector.h"
-#import "GTXAssertions.h"
-
-@implementation GTXArtifactCollector {
-  NSArray<Class<GTXArtifactImplementing>> *_artifactClasses;
-}
-
-- (instancetype)initWithChecks:(NSArray<id<GTXChecking>> *)checks {
-  self = [super init];
-  if (self) {
-    // Get the set of all (unique) Artifact classes that the checks need.
-    NSMutableSet *classes = [[NSMutableSet alloc] init];
-    for (id<GTXChecking> check in checks) {
-      if ([check respondsToSelector:@selector(requiredArtifactClasses)]) {
-        [classes addObjectsFromArray:[check requiredArtifactClasses]];
-      }
-    }
-    _artifactClasses = [classes allObjects];
-  }
-  return self;
-}
-
-- (GTXSnapshotContainer *)snapshot {
-  GTX_ASSERT([NSThread isMainThread], @"Snapshots cannot be taken on non-main threads");
-  NSMutableArray<id<GTXArtifactImplementing>> *snapshots = [[NSMutableArray alloc] init];
-  for (Class<GTXArtifactImplementing> cls in _artifactClasses) {
-    id<GTXArtifactImplementing> snapshot = [cls createArtifactSnapshot];
-    GTX_ASSERT(snapshot, @"Could not fetch a snapshot");
-    [snapshots addObject:snapshot];
-  }
-  return snapshots.count > 0 ? [[GTXSnapshotContainer alloc] initWithSnapshots:snapshots] : nil;
-}
-
-@end
diff --git a/Classes/GTXArtifactProcessor.h b/Classes/GTXArtifactProcessor.h
deleted file mode 100644
index 093bd1a..0000000
--- a/Classes/GTXArtifactProcessor.h
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-// Copyright 2019 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-
-#import "GTXChecking.h"
-#import "GTXSnapshotContainer.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- *  A delegate protocol for listening to events occurring in the @c GTXArtifactProcessor.
- */
-@protocol GTXArtifactProcessorDelegate <NSObject>
-
-- (void)artifactProcessorDidProcessSnapshotContainer;
-- (void)artifactProcessorDidShutdown;
-
-@end
-
-typedef void (^GTXArtifactProcessorReportFetchBlock)(GTXReport *report);
-
-/**
- *  An artifact processor which can process artifacts on background threads.
- */
-@interface GTXArtifactProcessor : NSObject
-
-/**
- *  Use initWithChecks:delegate: instead.
- */
-- (instancetype)init NS_UNAVAILABLE;
-
-/**
- *  Initializes a new artifact processor to work with the given set of checks.
- *
- *  @param checks The checks to be performed on the snapshots.
- *  @param delegate An optional delegate to recieve callback of checks processing.
- *
- *  @return a new artifact processor.
- */
-- (instancetype)initWithChecks:(NSArray<id<GTXChecking>> *)checks
-                      delegate:(nullable id<GTXArtifactProcessorDelegate>)delegate;
-
-/**
- *  Starts a background thread to process the submitted snapshots.
- */
-- (void)startProcessing;
-
-/**
- *  Stops the backgorund processing of snapshots, any snapshots submitted after this call may not
- *  be processed.
- */
-- (void)stopProcessing;
-
-/**
- *  Fetches the latest report held by the processor and invokes the given callback with it.
- *
- *  @param fetchBlock A callback to invoke once the report is prepared.
- */
-- (void)fetchLatestReportAsync:(GTXArtifactProcessorReportFetchBlock)fetchBlock;
-
-/**
- *  Adds a snapshot container into the artifact processor's internal buffer for processing.
- *
- *  @param container The snapshot container to be processed.
- *
- *  @return @c YES if the container was successfully added, @c NO otherwise.
- */
-- (BOOL)addSnapshotContainerForProcessing:(GTXSnapshotContainer *)container;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXArtifactProcessor.m b/Classes/GTXArtifactProcessor.m
deleted file mode 100644
index 1db9ccd..0000000
--- a/Classes/GTXArtifactProcessor.m
+++ /dev/null
@@ -1,140 +0,0 @@
-//
-// Copyright 2019 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "GTXArtifactProcessor.h"
-
-#import <Foundation/Foundation.h>
-
-#import "GTXAssertions.h"
-#import "GTXSnapshotBuffer.h"
-
-@implementation GTXArtifactProcessor {
-  NSArray<id<GTXChecking>> *_checks;
-  id<GTXArtifactProcessorDelegate> _delegate;
-  volatile BOOL _isShuttingDown;
-  GTXSnapshotBuffer *_buffer;
-  GTXReport *_report;
-
-  // GTXArtifactProcessor uses a command buffer model to deal with multi-threading: all
-  // processing and its associated tasks enqueue as commands on a command queue and are executed
-  // from it. @c _queueKey and @c _queueContext are used to ensure that commands related code is
-  // only invoked from the command queue context.
-  dispatch_queue_t _commandQueue;
-  void *_queueKey, *_queueContext;
-}
-
-- (instancetype)initWithChecks:(NSArray<id<GTXChecking>> *)checks
-                      delegate:(id<GTXArtifactProcessorDelegate>)delegate {
-  self = [super init];
-  if (self) {
-    _checks = checks;
-    _delegate = delegate;
-    _buffer = [[GTXSnapshotBuffer alloc] init];
-  }
-  return self;
-}
-
-- (void)startProcessing {
-  GTX_ASSERT(!_commandQueue, @"GTXArtifactProcessor was already started");
-  _report = [[GTXReport alloc] init];
-  _commandQueue =
-      dispatch_queue_create("com.google.gtxilib.artifactprocessor", DISPATCH_QUEUE_SERIAL);
-  _queueKey = &_queueKey;
-  _queueContext = &_queueContext;
-  dispatch_queue_set_specific(_commandQueue, _queueKey, _queueContext, NULL);
-}
-
-- (void)stopProcessing {
-  __weak typeof(self) weakSelf = self;
-  dispatch_async(_commandQueue, ^{
-    [weakSelf gtx_commandForProcessorShutdown];
-  });
-}
-
-- (BOOL)addSnapshotContainerForProcessing:(GTXSnapshotContainer *)container {
-  if (_isShuttingDown) {
-    return NO;
-  }
-  [_buffer putSnapshotsContainer:container];
-  __weak typeof(self) wSelf = self;
-  dispatch_async(_commandQueue, ^{
-    [wSelf gtx_commandForProcessingNextSnapshot];
-  });
-  return YES;
-}
-
-- (void)fetchLatestReportAsync:(GTXArtifactProcessorReportFetchBlock)fetchBlock {
-  __weak typeof(self) weakSelf = self;
-  dispatch_async(_commandQueue, ^{
-    [weakSelf gtx_commandForReportFetch:fetchBlock];
-  });
-}
-
-#pragma mark - Artifact Processor Command Implementations
-
-- (void)gtx_assertCallerIsCommandQueue {
-  void *context = dispatch_queue_get_specific(_commandQueue, _queueKey);
-  (void)context;  // Marking context as used when below assert is removed due to compiler
-                  // optimizations.
-  GTX_ASSERT(context == _queueContext, @"This method can only be executed from command queue.");
-}
-
-- (void)gtx_commandForProcessingNextSnapshot {
-  [self gtx_assertCallerIsCommandQueue];
-  if (_isShuttingDown) {
-    return;
-  }
-  GTXSnapshotContainer *container = [_buffer getNextSnapshotsContainer];
-  if (container) {
-    // Process this container and add errors to the report.
-    for (id<GTXChecking> check in _checks) {
-      if ([check respondsToSelector:@selector(performCheckOnSnapshot:addingErrorsToReport:)]) {
-        [check performCheckOnSnapshot:container addingErrorsToReport:_report];
-        // @TODO: Consider adding all passing elements to the report as well, it might be useful to
-        // look at all the elements that were scanned.
-      }
-    }
-    __weak typeof(self) weakSelf = self;
-    dispatch_async(dispatch_get_main_queue(), ^{
-      typeof(self) strongSelf = weakSelf;
-      if (strongSelf) {
-        [strongSelf->_delegate artifactProcessorDidProcessSnapshotContainer];
-      }
-    });
-  }
-}
-
-- (void)gtx_commandForProcessorShutdown {
-  [self gtx_assertCallerIsCommandQueue];
-  _isShuttingDown = YES;
-  __weak typeof(self) weakSelf = self;
-  dispatch_async(dispatch_get_main_queue(), ^{
-    typeof(self) strongSelf = weakSelf;
-    if (strongSelf) {
-      [strongSelf->_delegate artifactProcessorDidShutdown];
-    }
-  });
-}
-
-- (void)gtx_commandForReportFetch:(GTXArtifactProcessorReportFetchBlock)fetchBlock {
-  [self gtx_assertCallerIsCommandQueue];
-  GTXReport *reportCopy = [_report copy];
-  dispatch_async(dispatch_get_main_queue(), ^{
-    fetchBlock(reportCopy);
-  });
-}
-
-@end
diff --git a/Classes/GTXBlacklistFactory.h b/Classes/GTXBlacklistFactory.h
deleted file mode 100644
index 0fe3a83..0000000
--- a/Classes/GTXBlacklistFactory.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// Copyright 2018 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <UIKit/UIKit.h>
-
-#import "GTXBlacklisting.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- *  Factory for GTXBlacklisting objects for blacklisting elements.
- */
-@interface GTXBlacklistFactory : NSObject
-
-- (instancetype)init NS_UNAVAILABLE;
-/**
- *  Returns a GTXBlacklisting object that ignores all elements that are instances of
- *  a given @c elementClassName.
- *
- *  @param elementClassName The name of the class that should be blacklisted.
- *  @return A GTXBlacklisting object that ignores all elements of the given class.
- */
-+ (id<GTXBlacklisting>)blacklistWithClassName:(NSString *)elementClassName;
-/**
- *  Returns a GTXBlacklisting object that ignores all elements that are instances of
- *  a given @c elementClassName, but only for GTXChecking objects with a given @c checkName.
- *
- *  @param elementClassName The name of the class that should be blacklisted.
- *  @param skipCheckName The name of the check that should ignore elements of the given class.
- *  @return A GTXBlacklisting object that ignores all elements of the given class when running the
- *  given check.
- */
-+ (id<GTXBlacklisting>)blacklistWithClassName:(NSString *)elementClassName
-                                    checkName:(NSString *)skipCheckName;
-/**
- *  Returns a GTXBlacklisting object that ignores all elements with a given accessibility
- *  identifier, but only for GTXChecking objects with a given @c checkName.
- *
- *  @param accessibilityId The accessibility identifier of the element that should be blacklisted.
- *  @param skipCheckName The name of the check that should ignore elements with the given
- *  accessibility identifier.
- */
-+ (id<GTXBlacklisting>)blacklistWithAccessibilityIdentifier:(NSString *)accessibilityId
-                                                  checkName:(NSString *)skipCheckName;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXCheckBlock.h b/Classes/GTXCheckBlock.h
index f635f55..b5959d6 100644
--- a/Classes/GTXCheckBlock.h
+++ b/Classes/GTXCheckBlock.h
@@ -22,37 +22,53 @@
 NS_ASSUME_NONNULL_BEGIN
 
 /**
- *  Block that performs a single accessibility check on the given element.
+ * Block that performs a single accessibility check on the given element.
  *
- *  @param      element    The target element on which GTX check is to be performed.
- *  @param[out] errorOrNil The error set on failure. The error returned can be @c nil, signifying
- *                         that the check succeeded.
+ * @param      element    The target element on which GTX check is to be performed.
+ * @param[out] errorOrNil The error set on failure. The error returned can be @c nil, signifying
+ *                        that the check succeeded.
  *
- *  @return @c YES if the check performed succeeded without any errors, else @c NO.
+ * @return @c YES if the check performed succeeded without any errors, else @c NO.
  */
 typedef BOOL (^GTXCheckHandlerBlock)(id element, GTXErrorRefType errorOrNil);
 
 /**
- *  A block based interface for creating accessiblity checks.
+ * A block based interface for creating accessiblity checks.
  */
 @interface GTXCheckBlock : NSObject<GTXChecking>
 
 /**
- *  GTXCheckBlock::init is disabled, instead use GTXCheckBlock::GTXCheckWithName:block: method
- *  to create GTXChecks.
+ * GTXCheckBlock::init is disabled, instead use GTXCheckBlock::GTXCheckWithName:block: method
+ * to create GTXChecks.
  */
 - (instancetype)init __attribute__((unavailable("Use GTXCheckWithName:block: instead.")));
 
 /**
- *  Creates an GTXCheck with the given @c name and @c block that performs the check.
+ * Creates an GTXCheck with the given @c name and @c block that performs the check. Note that this
+ * check is equivalent to check created using GTXCheckWithName:requiresWindow:block: where
+ * requiresWindow is @c YES.
  *
- *  @param name  The name of the check.
- *  @param block A block that performs the check.
+ * @param name  The name of the check.
+ * @param block A block that performs the check.
  *
- *  @return An GTXCheck object.
+ * @return An GTXCheck object.
  */
 + (id<GTXChecking>)GTXCheckWithName:(NSString *)name block:(GTXCheckHandlerBlock)block;
 
+/**
+ * Creates an GTXCheck with the given @c name and @c block that performs the check.
+ *
+ * @param name           The name of the check.
+ * @param requiresWindow A boolean that indicates if element must have a window before running the
+ * check.
+ * @param block          A block that performs the check.
+ *
+ * @return An GTXCheck object.
+ */
++ (id<GTXChecking>)GTXCheckWithName:(NSString *)name
+                     requiresWindow:(BOOL)requiresWindow
+                              block:(GTXCheckHandlerBlock)block;
+
 @end
 
 NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXCheckBlock.m b/Classes/GTXCheckBlock.m
index a6957bc..1dd74dc 100644
--- a/Classes/GTXCheckBlock.m
+++ b/Classes/GTXCheckBlock.m
@@ -21,14 +21,22 @@
 @implementation GTXCheckBlock {
   NSString *_name;
   GTXCheckHandlerBlock _block;
+  BOOL _requiresWindow;
 }
 
 + (id<GTXChecking>)GTXCheckWithName:(NSString *)name
+                     requiresWindow:(BOOL)requiresWindow
                               block:(GTXCheckHandlerBlock)block {
-  return [[GTXCheckBlock alloc] initWithName:name block:block];
+  return [[GTXCheckBlock alloc] initWithName:name requiresWindow:requiresWindow block:block];
+}
+
++ (id<GTXChecking>)GTXCheckWithName:(NSString *)name block:(GTXCheckHandlerBlock)block {
+  // NOTE: requiresWindow is YES to ensure backward compatibility.
+  return [self GTXCheckWithName:name requiresWindow:YES block:block];
 }
 
 - (instancetype)initWithName:(NSString *)name
+              requiresWindow:(BOOL)requiresWindow
                        block:(GTXCheckHandlerBlock)block {
   NSParameterAssert(name);
   NSParameterAssert(block);
@@ -37,6 +45,7 @@
   if (self) {
     _name = [name copy];
     _block = [block copy];
+    _requiresWindow = requiresWindow;
   }
   return self;
 }
@@ -55,4 +64,8 @@
   return _name;
 }
 
+- (BOOL)requiresWindowBeforeChecking {
+  return _requiresWindow;
+}
+
 @end
diff --git a/Classes/GTXCheckResult.h b/Classes/GTXCheckResult.h
new file mode 100644
index 0000000..4b1cd4a
--- /dev/null
+++ b/Classes/GTXCheckResult.h
@@ -0,0 +1,58 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Describes the result of an error produced by running a @c GTXChecking instance on a UI element.
+ */
+@interface GTXCheckResult : NSObject
+
+/**
+ * The check's name.
+ */
+@property(copy, nonatomic, readonly) NSString *checkName;
+
+/**
+ * A description of the error produced by the check.
+ */
+@property(copy, nonatomic, readonly) NSString *errorDescription;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/**
+ * Initializes a @c GTXCheckResult with the given parameters.
+ *
+ * @param checkName The name of the check producing this result.
+ * @param errorDescription A description of the error produced by the check.
+ */
+- (instancetype)initWithCheckName:(NSString *)checkName
+                 errorDescription:(NSString *)errorDescription NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Constructs a @c GTXCheckResult instance from an @c NSError object in the format returned by @c
+ * GTXChecking objects.
+ *
+ * @param error Describes the result of a @c GTXChecking object. @c error.userInfo must contain the
+ * keys @c kGTXErrorCheckNameKey and @c NSLocalizedDescriptionKey.
+ */
++ (instancetype)checkResultFromError:(NSError *)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXCheckResult.m b/Classes/GTXCheckResult.m
new file mode 100644
index 0000000..f5a6e72
--- /dev/null
+++ b/Classes/GTXCheckResult.m
@@ -0,0 +1,50 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXCheckResult.h"
+
+#import "GTXAssertions.h"
+#import "NSError+GTXAdditions.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation GTXCheckResult
+
+- (instancetype)initWithCheckName:(NSString *)checkName
+                 errorDescription:(NSString *)errorDescription {
+  self = [super init];
+  if (self) {
+    GTX_ASSERT(checkName, @"checkName must be nonnull.");
+    GTX_ASSERT(errorDescription, @"errorDescription must be nonnull.");
+    _checkName = [checkName copy];
+    _errorDescription = [errorDescription copy];
+  }
+  return self;
+}
+
++ (instancetype)checkResultFromError:(NSError *)error {
+  GTX_ASSERT(error, @"error must not be nil");
+  NSString *checkName = error.userInfo[kGTXErrorCheckNameKey];
+  NSString *errorDescription = error.userInfo[NSLocalizedDescriptionKey];
+  GTX_ASSERT(checkName, @"error.userInfo must contain an entry for kGTXErrorCheckNameKey");
+  GTX_ASSERT(errorDescription,
+             @"error.userInfo must contain an entry for NSLocalizedDescriptionKey");
+  return [[GTXCheckResult alloc] initWithCheckName:checkName errorDescription:errorDescription];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXChecking.h b/Classes/GTXChecking.h
index 61de4f3..46e2662 100644
--- a/Classes/GTXChecking.h
+++ b/Classes/GTXChecking.h
@@ -16,10 +16,8 @@
 
 #import <UIKit/UIKit.h>
 
-#import "GTXArtifactImplementing.h"
 #import "GTXCommon.h"
 #import "GTXReport.h"
-#import "GTXSnapshotContainer.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -48,22 +46,13 @@
 @optional
 
 /**
- *  @return An array of classes whose snapshots are required by this check for performing the check
- *          verification.
+ *  Indicates if the check requires that the element have a window before it can be checked. If this
+ * method is not implemented the check is assumed to be able to run without a window. Note that the
+ * restriction does not apply to UIAccessibilityElements as they do not have a window property.
+ *  @return @c YES if the check requires that elements to be checked be in hierarchy for the check
+ *  to be performed, @c NO otherwise.
  */
-- (NSArray<Class<GTXArtifactImplementing>> *)requiredArtifactClasses;
-
-/**
- *  Performs the check on the given snapshot.
- *
- *  @param      snapshots The target snapshot on which this check needs to be performed.
- *  @param[out] report    The report to be populated with issues detected by the check.
- *
- *  @return @c YES if the check succeeded (no issues were detected and report is unchanged), else @c
- *          NO.
- */
-- (BOOL)performCheckOnSnapshot:(GTXSnapshotContainer *)snapshots
-          addingErrorsToReport:(GTXReport *)report;
+- (BOOL)requiresWindowBeforeChecking;
 
 @end
 
diff --git a/Classes/GTXChecksCollection.h b/Classes/GTXChecksCollection.h
index 3a40141..db7d71b 100644
--- a/Classes/GTXChecksCollection.h
+++ b/Classes/GTXChecksCollection.h
@@ -51,7 +51,7 @@
 /**
  *  @return An array of all supported GTXChecks for the given @c version.
  */
-+ (NSArray<id<GTXChecking>> *)allChecksForVersion:(GTXVersion)version;
++ (NSArray<id<GTXChecking>> *)allGTXChecksForVersion:(GTXVersion)version;
 
 /**
  *  @return An array of all supported GTXChecks.
@@ -59,6 +59,19 @@
 + (NSArray<id<GTXChecking>> *)allGTXChecks;
 
 /**
+ * Returns an array of all supported GTXChecks for @c version except those with names in
+ * @c excludedCheckNames. Crashes with an assertion if an element in @c excludedCheckNames does not
+ * have a corresponding check.
+ *
+ * @param version The version of the GTX check suite to use.
+ * @param excludedCheckNames The names of the checks to exclude from the returned array.
+ * @return All GTXChecks for @c version, except checks whose names are found in
+ * @c excludedCheckNames.
+ */
++ (NSArray<id<GTXChecking>> *)allGTXChecksForVersion:(GTXVersion)version
+                            excludingChecksWithNames:(NSSet<NSString *> *)excludedCheckNames;
+
+/**
  *  @return a check that verifies that accessibility label is present on all accessibility elements.
  */
 + (id<GTXChecking>)checkForAXLabelPresent;
@@ -96,4 +109,11 @@
  */
 + (id<GTXChecking>)checkForSufficientTextViewContrastRatio;
 
+/**
+ *  @return a check that verifies that a text displaying element automatically scales font size with
+ *  Dynamic Type. Text displaying elements include UILabel, UITextView, and UITextField, and custom
+ *  views that implement @c adjustsFontForContentSizeCategory and @c font.
+ */
++ (id<GTXChecking>)checkForSupportsDynamicType;
+
 @end
diff --git a/Classes/GTXChecksCollection.m b/Classes/GTXChecksCollection.m
index 1fcedd8..0ea3c3e 100644
--- a/Classes/GTXChecksCollection.m
+++ b/Classes/GTXChecksCollection.m
@@ -16,6 +16,7 @@
 
 #import "GTXChecksCollection.h"
 
+#import "GTXAssertions.h"
 #import "GTXCheckBlock.h"
 #import "GTXChecking.h"
 #import "GTXImageAndColorUtils.h"
@@ -32,6 +33,13 @@
 NSString *const kGTXCheckNameMinimumTappableArea = @"Touch target size";
 NSString *const kGTXCheckNameLabelMinimumContrastRatio = @"Contrast ratio (Label)";
 NSString *const kGTXCheckNameTextViewMinimumContrastRatio = @"Contrast ratio (TextView)";
+NSString *const kGTXCheckNameSupportsDynamicType = @"Supports Dynamic Type";
+
+/**
+ * The text style attribute for fonts initialized by the system. Fonts with this text style do not
+ * scale with Dynamic Type.
+ */
+static NSString *const kGTXDefaultFontDescriptorTextStyle = @"CTFontRegularUsage";
 
 #pragma mark - Globals
 
@@ -48,335 +56,503 @@
  */
 static const float kGTXMinContrastRatioForAccessibleText = 3.0;
 
+#pragma mark - Exposed Interfaces
+
+/**
+ * Declares private selectors so they can be used with @c respondsToSelector and have the correct
+ * type information.
+ */
+@interface UIFont (GTXExposePrivateAPIs)
+
+/**
+ * @return The text style associated with this font.
+ */
+- (NSString *)textStyleForScaling;
+
+@end
+
 #pragma mark - Implementations
 
 @implementation GTXChecksCollection
 
-+ (NSArray<id<GTXChecking>> *)allChecksForVersion:(GTXVersion)version {
++ (NSArray<id<GTXChecking>> *)allGTXChecksForVersion:(GTXVersion)version {
+  NSArray<id<GTXChecking>> *originalChecks = @[
+    [self checkForAXLabelPresent], [self checkForAXLabelNotPunctuated],
+    [self checkForAXLabelNotRedundantWithTraits], [self checkForAXTraitDontConflict],
+    [self checkForMinimumTappableArea], [self checkForSufficientContrastRatio],
+    [self checkForSupportsDynamicType]
+  ];
   switch (version) {
-    case GTXVersionLatest: return [self allGTXChecks];
-    case GTXVersionPreRelease: return [self allGTXChecks];
-    case GTXVersion_0: return [self allGTXChecks];
+    case GTXVersionLatest:
+      return originalChecks;
+    case GTXVersionPreRelease:
+      return originalChecks;
+    case GTXVersion_0:
+      return originalChecks;
   }
 }
 
 + (NSArray<id<GTXChecking>> *)allGTXChecks {
-  return @[[self checkForAXLabelPresent],
-           [self checkForAXLabelNotPunctuated],
-           [self checkForAXLabelNotRedundantWithTraits],
-           [self checkForAXTraitDontConflict],
-           [self checkForMinimumTappableArea],
-           [self checkForSufficientContrastRatio]];
+  return [GTXChecksCollection allGTXChecksForVersion:GTXVersionLatest];
+}
+
++ (NSArray<id<GTXChecking>> *)allGTXChecksForVersion:(GTXVersion)version
+                            excludingChecksWithNames:(NSSet<NSString *> *)excludedCheckNames {
+  NSArray<id<GTXChecking>> *originalChecks = [GTXChecksCollection allGTXChecksForVersion:version];
+  [GTXChecksCollection gtx_assertChecks:originalChecks containChecksForNames:excludedCheckNames];
+  NSMutableArray<id<GTXChecking>> *checks = [[NSMutableArray alloc] init];
+  for (id<GTXChecking> check in originalChecks) {
+    if (![excludedCheckNames containsObject:[check name]]) {
+      [checks addObject:check];
+    }
+  }
+  return checks;
 }
 
 #pragma mark - GTXChecks
 
 + (id<GTXChecking>)checkForAXLabelPresent {
-  id<GTXChecking> check = [GTXCheckBlock GTXCheckWithName:kGTXCheckNameAccessibilityLabelPresent
-                                   block:^BOOL(id element, GTXErrorRefType errorOrNil) {
-    if ([self gtx_isTextDisplayingElement:element]) {
-      // Elements that display text can use its text as an accessibility value making the
-      // accessibility label optional.
-      return YES;
-    }
-    NSError *error;
-    NSString *label = [self stringValueOfAccessibilityLabelForElement:element
-                                                                error:&error];
-    if (error) {
-      if (errorOrNil) {
-        *errorOrNil = error;
-      }
-      return NO;
-    }
-    label = [self gtx_trimmedStringFromString:label];
-    if ([label length] > 0) {
-      // Check passed.
-      return YES;
-    }
-    [NSError
-        gtx_logOrSetGTXCheckFailedError:errorOrNil
-                                element:element
-                                   name:kGTXCheckNameAccessibilityLabelPresent
-                            description:@"This element doesn’t have an accessibility label. All "
-                                        @"accessibility elements must have accessibility labels."];
-    return NO;
-  }];
+  id<GTXChecking> check = [GTXCheckBlock
+      GTXCheckWithName:kGTXCheckNameAccessibilityLabelPresent
+        requiresWindow:NO
+                 block:^BOOL(id element, GTXErrorRefType errorOrNil) {
+                   if ([self gtx_isTextDisplayingElement:element]) {
+                     // Elements that display text can use its text as an accessibility value making
+                     // the accessibility label optional.
+                     return YES;
+                   }
+                   NSError *error;
+                   NSString *label = [self stringValueOfAccessibilityLabelForElement:element
+                                                                               error:&error];
+                   if (error) {
+                     if (errorOrNil) {
+                       *errorOrNil = error;
+                     }
+                     return NO;
+                   }
+                   label = [self gtx_trimmedStringFromString:label];
+                   if ([label length] > 0) {
+                     // Check passed.
+                     return YES;
+                   }
+                   [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                                    element:element
+                                                       name:kGTXCheckNameAccessibilityLabelPresent
+                                                description:@"This element doesn’t have an "
+                                                            @"accessibility label. All "
+                                                            @"accessibility elements must have "
+                                                            @"accessibility labels."];
+                   return NO;
+                 }];
   return check;
 }
 
 + (id<GTXChecking>)checkForAXLabelNotPunctuated {
-  id<GTXChecking> check =
-      [GTXCheckBlock GTXCheckWithName:kGTXCheckNameAccessibilityLabelNotPunctuated
-                                block:^BOOL(id element, GTXErrorRefType errorOrNil) {
-    if ([self gtx_isTextDisplayingElement:element]) {
-      // This check is not applicable to text elements as accessibility labels can hold static text
-      // that can be punctuated and formatted like a string.
-      return YES;
-    }
-    NSError *error;
-    NSString *stringValue = [self stringValueOfAccessibilityLabelForElement:element
-                                                                      error:&error];
-    if (error) {
-      if (errorOrNil) {
-        *errorOrNil = error;
-      }
-      return NO;
-    }
-    NSString *label = [self gtx_trimmedStringFromString:stringValue];
-    // This check is not applicable for container elements that combine individual labels joined
-    // with commas.
-    if ([label rangeOfString:@","].location != NSNotFound) {
-      return YES;
-    }
-    if ([label length] > 0 && [label hasSuffix:@"."]) {
-      // Check failed.
-      NSString *errorDescription = [NSString
-          stringWithFormat:
-              @"This element has an accessibility label that ends in a period but doesn’t have a "
-              @"text trait. Accessibility labels aren’t sentences and don’t need periods. If the "
-              @"element visually displays text it should have the UIAccessibilityTraitStaticText "
-              @"trait similar to UITextView or UILabel.\n\nLabel found: %@.",
-              label];
-      [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
-                                       element:element
-                                          name:kGTXCheckNameAccessibilityLabelNotPunctuated
-                                   description:errorDescription];
-      return NO;
-    }
-    return YES;
-  }];
+  id<GTXChecking> check = [GTXCheckBlock
+      GTXCheckWithName:kGTXCheckNameAccessibilityLabelNotPunctuated
+        requiresWindow:NO
+                 block:^BOOL(id element, GTXErrorRefType errorOrNil) {
+                   if ([self gtx_isTextDisplayingElement:element]) {
+                     // This check is not applicable to text elements as accessibility labels can
+                     // hold static text that can be punctuated and formatted like a string.
+                     return YES;
+                   }
+                   NSError *error;
+                   NSString *stringValue = [self stringValueOfAccessibilityLabelForElement:element
+                                                                                     error:&error];
+                   if (error) {
+                     if (errorOrNil) {
+                       *errorOrNil = error;
+                     }
+                     return NO;
+                   }
+                   NSString *label = [self gtx_trimmedStringFromString:stringValue];
+                   // This check is not applicable for container elements that combine individual
+                   // labels joined with commas.
+                   if ([label rangeOfString:@","].location != NSNotFound) {
+                     return YES;
+                   }
+                   if ([label length] > 0 && [label hasSuffix:@"."]) {
+                     // Check failed.
+                     NSString *errorDescription = [NSString
+                         stringWithFormat:
+                             @"This element has an accessibility label that ends in a period but "
+                             @"doesn’t have a "
+                             @"text trait. Accessibility labels aren’t sentences and don’t need "
+                             @"periods. If the "
+                             @"element visually displays text it should have the "
+                             @"UIAccessibilityTraitStaticText "
+                             @"trait similar to UITextView or UILabel.\n\nLabel found: %@.",
+                             label];
+                     [NSError
+                         gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                                 element:element
+                                                    name:
+                                                        kGTXCheckNameAccessibilityLabelNotPunctuated
+                                             description:errorDescription];
+                     return NO;
+                   }
+                   return YES;
+                 }];
   return check;
 }
 
-// @todo Include all UIAccessibilityTraits that announce themselves (image, search
+// @TODO Include all UIAccessibilityTraits that announce themselves (image, search
 // field, etc.), and find a more robust way to determine if the label is redundant. Currently, the
 // suffix is compared to a single string, which causes false positives when that string occurs
 // elsewhere in the label or synonyms are used. Additionally, the hardcoded string only works in
 // English. This method also needs to be updated for i18n.
 + (id<GTXChecking>)checkForAXLabelNotRedundantWithTraits {
-  id<GTXChecking> check =
-    [GTXCheckBlock GTXCheckWithName:kGTXCheckNameAccessibilityLabelIsNotRedundantWithTraits
-                              block:^BOOL(id element, GTXErrorRefType errorOrNil) {
-    UIAccessibilityTraits elementAXTraits = [element accessibilityTraits];
-    NSString *elementAXLabel = [element accessibilityLabel];
-    NSDictionary<NSNumber *, NSString *> const *redundantLabelsDictionary =
-        [self gtx_traitsToRedundantLabelsDictionary];
-    NSMutableArray<NSString *> *redundantTextList = [[NSMutableArray alloc] init];
-    NSMutableArray<NSString *> *redundantTraitNameList = [[NSMutableArray alloc] init];
-    for (NSNumber *testTrait in redundantLabelsDictionary) {
-      NSString* redundantText = [redundantLabelsDictionary objectForKey:testTrait];
-      UIAccessibilityTraits testUITrait = [testTrait unsignedLongLongValue];
-      if ((BOOL)(elementAXTraits & testUITrait)) {
-        if ([GTXChecksCollection gtx_caseInsensitive:elementAXLabel hasSuffix:redundantText]) {
-          if ([element isKindOfClass:[UIButton class]] &&
-              [GTXChecksCollection gtx_caseInsensitive:((UIButton *)element).titleLabel.text
-                                             hasSuffix:redundantText]) {
-            // This is a button whose title itself has the word "button", we must ignore this
-            // kind of elements.
-            continue;
-          }
-          NSError *error;
-          NSString *stringValue = [self stringValueOfUIAccessibilityTraits:testUITrait
-                                                                     error:&error];
-          if (error) {
-            if (errorOrNil) {
-              *errorOrNil = error;
-            }
-            return NO;
-          }
+  id<GTXChecking> check = [GTXCheckBlock
+      GTXCheckWithName:kGTXCheckNameAccessibilityLabelIsNotRedundantWithTraits
+        requiresWindow:NO
+                 block:^BOOL(id element, GTXErrorRefType errorOrNil) {
+                   UIAccessibilityTraits elementAXTraits = [element accessibilityTraits];
+                   NSString *elementAXLabel = [element accessibilityLabel];
+                   NSDictionary<NSNumber *, NSString *> const *redundantLabelsDictionary =
+                       [self gtx_traitsToRedundantLabelsDictionary];
+                   NSMutableArray<NSString *> *redundantTextList = [[NSMutableArray alloc] init];
+                   NSMutableArray<NSString *> *redundantTraitNameList =
+                       [[NSMutableArray alloc] init];
+                   for (NSNumber *testTrait in redundantLabelsDictionary) {
+                     NSString *redundantText = [redundantLabelsDictionary objectForKey:testTrait];
+                     UIAccessibilityTraits testUITrait = [testTrait unsignedLongLongValue];
+                     if ((BOOL)(elementAXTraits & testUITrait)) {
+                       if ([GTXChecksCollection gtx_caseInsensitive:elementAXLabel
+                                                          hasSuffix:redundantText]) {
+                         if ([element isKindOfClass:[UIButton class]] &&
+                             [GTXChecksCollection
+                                 gtx_caseInsensitive:((UIButton *)element).titleLabel.text
+                                           hasSuffix:redundantText]) {
+                           // This is a button whose title itself has the word "button", we must
+                           // ignore this kind of elements.
+                           continue;
+                         }
+                         NSError *error;
+                         NSString *stringValue =
+                             [self stringValueOfUIAccessibilityTraits:testUITrait error:&error];
+                         if (error) {
+                           if (errorOrNil) {
+                             *errorOrNil = error;
+                           }
+                           return NO;
+                         }
 
-          [redundantTextList addObject:redundantText];
-          [redundantTraitNameList addObject:stringValue];
-        }
-      }
-    }
-    if ([redundantTraitNameList count] > 0) {
-      NSString* stringOfRedundantTextList = [redundantTextList componentsJoinedByString:@", "];
-      NSString* stringOfRedundantTraitNameList =
-          [redundantTraitNameList componentsJoinedByString:@", "];
-      NSString *errorDescription = [NSString
-          stringWithFormat:
-              @"This element has an accessibility label that isn't needed because the element "
-              @"already includes a trait.Traits such as the UIAccessibilityTraitButton cause "
-              @"VoiceOver to speak \"button\" along with the label, so you don't need to include "
-              @"the word \"button\".\n\nLabel found: %@\nRedundant label text found: %@\nRedundant "
-              @"Trait(s) found: %@",
-              elementAXLabel, stringOfRedundantTextList, stringOfRedundantTraitNameList];
-      [NSError
-          gtx_logOrSetGTXCheckFailedError:errorOrNil
-                                  element:element
-                                     name:kGTXCheckNameAccessibilityLabelIsNotRedundantWithTraits
-                              description:errorDescription];
-      return NO;
-    }
-    return YES;
-  }];
+                         [redundantTextList addObject:redundantText];
+                         [redundantTraitNameList addObject:stringValue];
+                       }
+                     }
+                   }
+                   if ([redundantTraitNameList count] > 0) {
+                     NSString *stringOfRedundantTextList =
+                         [redundantTextList componentsJoinedByString:@", "];
+                     NSString *stringOfRedundantTraitNameList =
+                         [redundantTraitNameList componentsJoinedByString:@", "];
+                     NSString *errorDescription = [NSString
+                         stringWithFormat:@"This element has an accessibility label that isn't "
+                                          @"needed because the element "
+                                          @"already includes a trait. Traits such as the "
+                                          @"UIAccessibilityTraitButton cause "
+                                          @"VoiceOver to speak \"button\" along with the label, so "
+                                          @"you don't need to include "
+                                          @"the word \"button\".\n\nLabel found: %@\nRedundant "
+                                          @"label text found: %@\nRedundant "
+                                          @"Trait(s) found: %@",
+                                          elementAXLabel, stringOfRedundantTextList,
+                                          stringOfRedundantTraitNameList];
+                     [NSError
+                         gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                                 element:element
+                                                    name:
+                                                        kGTXCheckNameAccessibilityLabelIsNotRedundantWithTraits
+                                             description:errorDescription];
+                     return NO;
+                   }
+                   return YES;
+                 }];
   return check;
 }
 
 + (id<GTXChecking>)checkForAXTraitDontConflict {
-  id<GTXChecking> check =
-      [GTXCheckBlock GTXCheckWithName:kGTXCheckNameAccessibilityTraitsDontConflict
-                                block:^BOOL(id element, GTXErrorRefType errorOrNil) {
-    if ([NSStringFromClass([element class]) isEqualToString:@"UIAccessibilityElementKBKey"]) {
-      // iOS keyboard keys are known to have conflicting traits skip them.
-      return YES;
-    }
-    UIAccessibilityTraits elementAXTraits = [element accessibilityTraits];
-    // Even though we can check for valid accessibility traits, we are not doing that because some
-    // undocumented UIKit controls, e.g., UINavigationItemButtonView, are known to have unknown
-    // values. Check b/29226386 for more details.
-    // Check mutually exclusive conflicts for the element's accessibility traits.
-    for (NSArray<NSNumber *> *traitsConflictRule in [self gtx_traitsMutuallyExclusiveRules]) {
-      NSMutableArray<NSString *> *conflictTraitsNameList = [[NSMutableArray alloc] init];
-      for (NSNumber *testTrait in traitsConflictRule) {
-        UIAccessibilityTraits testUITrait = [testTrait unsignedLongLongValue];
-        if ((BOOL)(elementAXTraits & testUITrait)) {
-          NSError *error;
-          NSString *stringValue = [self stringValueOfUIAccessibilityTraits:testUITrait
-                                                                     error:&error];
-          if (error) {
-            if (errorOrNil) {
-              *errorOrNil = error;
-            }
-            return NO;
-          }
-          [conflictTraitsNameList addObject:stringValue];
-        }
-      }
-      if ([conflictTraitsNameList count] > 1) {
-        NSString *stringOfConflictTraitsNameList =
-            [conflictTraitsNameList componentsJoinedByString:@", "];
-        NSString *errorDescription =
-            [NSString stringWithFormat:@"This element has traits that are conflicting. These "
-                                       @"traits can’t occur at the same time: %@",
-                                       stringOfConflictTraitsNameList];
-        [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
-                                         element:element
-                                            name:kGTXCheckNameAccessibilityTraitsDontConflict
-                                     description:errorDescription];
-        return NO;
-      }
-    }
-    return YES;
-  }];
+  id<GTXChecking> check = [GTXCheckBlock
+      GTXCheckWithName:kGTXCheckNameAccessibilityTraitsDontConflict
+        requiresWindow:NO
+                 block:^BOOL(id element, GTXErrorRefType errorOrNil) {
+                   if ([NSStringFromClass([element class])
+                           isEqualToString:@"UIAccessibilityElementKBKey"]) {
+                     // iOS keyboard keys are known to have conflicting traits skip them.
+                     return YES;
+                   }
+                   UIAccessibilityTraits elementAXTraits = [element accessibilityTraits];
+                   // Even though we can check for valid accessibility traits, we are not doing that
+                   // because some undocumented UIKit controls, e.g., UINavigationItemButtonView,
+                   // are known to have unknown values. Check b/29226386 for more details. Check
+                   // mutually exclusive conflicts for the element's accessibility traits.
+                   for (NSArray<NSNumber *> *traitsConflictRule in
+                        [self gtx_traitsMutuallyExclusiveRules]) {
+                     NSMutableArray<NSString *> *conflictTraitsNameList =
+                         [[NSMutableArray alloc] init];
+                     for (NSNumber *testTrait in traitsConflictRule) {
+                       UIAccessibilityTraits testUITrait = [testTrait unsignedLongLongValue];
+                       if ((BOOL)(elementAXTraits & testUITrait)) {
+                         NSError *error;
+                         NSString *stringValue =
+                             [self stringValueOfUIAccessibilityTraits:testUITrait error:&error];
+                         if (error) {
+                           if (errorOrNil) {
+                             *errorOrNil = error;
+                           }
+                           return NO;
+                         }
+                         [conflictTraitsNameList addObject:stringValue];
+                       }
+                     }
+                     if ([conflictTraitsNameList count] > 1) {
+                       NSString *stringOfConflictTraitsNameList =
+                           [conflictTraitsNameList componentsJoinedByString:@", "];
+                       NSString *errorDescription = [NSString
+                           stringWithFormat:@"This element has traits that are conflicting. These "
+                                            @"traits can’t occur at the same time: %@",
+                                            stringOfConflictTraitsNameList];
+                       [NSError
+                           gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                                   element:element
+                                                      name:
+                                                          kGTXCheckNameAccessibilityTraitsDontConflict
+                                               description:errorDescription];
+                       return NO;
+                     }
+                   }
+                   return YES;
+                 }];
   return check;
 }
 
 + (id<GTXChecking>)checkForMinimumTappableArea {
-  id<GTXChecking> check =
-      [GTXCheckBlock GTXCheckWithName:kGTXCheckNameMinimumTappableArea
-                                block:^BOOL(id element, GTXErrorRefType errorOrNil) {
-    if (![self gtx_isTappableNonLinkElement:element]) {
-      // Element is not tappable or is a link, links follow the font size of the text on page and
-      // are exempt from this check.
-      return YES;
-    }
-    NSMutableArray<NSString *> *errorDescriptions = [[NSMutableArray alloc] init];
-    if ([element respondsToSelector:@selector(accessibilityFrame)]) {
-      [GTXChecksCollection gtx_errorDescriptionForMinimumTappableArea:[element accessibilityFrame]
-                                                         propertyName:@"accessibilityFrame"
-                                                           addToArray:errorDescriptions];
-    }
-    // In iOS 13, UIAccessibilityElement responds to the frame selector but always returns
-    // CGRectZero. This causes all UIAccessibilityElement instances to fail touch target guidelines.
-    // Since UIAccessibilityElement instances don't really have a frame independent of their
-    // accessibility frame, ignoring elements with frames that are not UIView subclasses solves
-    // this.
-    if ([element respondsToSelector:@selector(frame)] && [element isKindOfClass:[UIView class]]) {
-      [GTXChecksCollection gtx_errorDescriptionForMinimumTappableArea:[element frame]
-                                                         propertyName:@"frame"
-                                                           addToArray:errorDescriptions];
-    }
-    if ([errorDescriptions count] > 0) {
-      NSString *joiner = @"\n\n";
-      NSString *propertyErrorDescription = [errorDescriptions componentsJoinedByString:joiner];
-      NSString *errorDescription = [NSString
-          stringWithFormat:
-              @"This element has a small touch target. All tappable elements must have a minimum "
-              @"touch target size of %dX%d points.%@%@",
-              (int)kGTXMinSizeForAccessibleElements, (int)kGTXMinSizeForAccessibleElements, joiner,
-              propertyErrorDescription];
-      [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
-                                       element:element
-                                          name:kGTXCheckNameMinimumTappableArea
-                                   description:errorDescription];
-      return NO;
-    }
-    return YES;
-  }];
+  id<GTXChecking> check = [GTXCheckBlock
+      GTXCheckWithName:kGTXCheckNameMinimumTappableArea
+        requiresWindow:NO
+                 block:^BOOL(id element, GTXErrorRefType errorOrNil) {
+                   if (![self gtx_isTappableNonLinkElement:element]) {
+                     // Element is not tappable or is a link, links follow the font size of the text
+                     // on page and are exempt from this check.
+                     return YES;
+                   }
+                   NSString *errorDescriptionTemplate =
+                       [NSString stringWithFormat:@"This element has a small touch target. All "
+                                                  @"tappable elements must have a minimum "
+                                                  @"touch target size of %d by %d points.",
+                                                  (int)kGTXMinSizeForAccessibleElements,
+                                                  (int)kGTXMinSizeForAccessibleElements];
+                   // If an element responds to the selectors needed to dynamically check for touch
+                   // events, that should be the source of truth for touch target size.
+                   // Accessibility services dispatch touch events using the same APIs, so
+                   // responding to touch events in a wide enough area satisfies touch target
+                   // guidelines. If they do not respond to those selectors, the only way to
+                   // estimate touch target size is via frame or accessibilityFrame. Checking
+                   // touchInside:withEvent must occur first, or else elements with too small frames
+                   // that respond to touches in a larger area, or vice versa, will be fail the
+                   // check when they should pass.
+                   if ([GTXChecksCollection gtx_canElementRespondToTouches:element]) {
+                     if (![GTXChecksCollection
+                             gtx_elementRespondsToTouchesInSufficientArea:element]) {
+                       NSString *errorDescription = [errorDescriptionTemplate
+                           stringByAppendingString:
+                               @"%@ The element does not respond to touches in the given range "
+                               @"using pointInside:withEvent:."];
+                       [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                                        element:element
+                                                           name:kGTXCheckNameMinimumTappableArea
+                                                    description:errorDescription];
+                       return NO;
+                     }
+                     return YES;
+                   }
+                   NSMutableArray<NSString *> *errorDescriptions = [[NSMutableArray alloc] init];
+                   if ([element respondsToSelector:@selector(accessibilityFrame)]) {
+                     [GTXChecksCollection
+                         gtx_errorDescriptionForMinimumTappableArea:[element accessibilityFrame]
+                                                       propertyName:@"accessibilityFrame"
+                                                         addToArray:errorDescriptions];
+                   }
+                   // In iOS 13, UIAccessibilityElement responds to the frame selector but always
+                   // returns CGRectZero. This causes all UIAccessibilityElement instances to fail
+                   // touch target guidelines. Since UIAccessibilityElement instances don't really
+                   // have a frame independent of their accessibility frame, ignoring elements with
+                   // frames that are not UIView subclasses solves this.
+                   if ([element respondsToSelector:@selector(frame)] &&
+                       [element isKindOfClass:[UIView class]]) {
+                     [GTXChecksCollection
+                         gtx_errorDescriptionForMinimumTappableArea:[element frame]
+                                                       propertyName:@"frame"
+                                                         addToArray:errorDescriptions];
+                   }
+                   if ([errorDescriptions count] > 0) {
+                     NSString *joiner = @"\n\n";
+                     NSString *propertyErrorDescription =
+                         [errorDescriptions componentsJoinedByString:joiner];
+                     NSString *errorDescription =
+                         [NSString stringWithFormat:@"%@%@%@", errorDescriptionTemplate, joiner,
+                                                    propertyErrorDescription];
+                     [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                                      element:element
+                                                         name:kGTXCheckNameMinimumTappableArea
+                                                  description:errorDescription];
+                     return NO;
+                   }
+                   return YES;
+                 }];
   return check;
 }
 
 + (id<GTXChecking>)checkForSufficientContrastRatio {
-  id<GTXChecking> check =
-  [GTXCheckBlock GTXCheckWithName:kGTXCheckNameLabelMinimumContrastRatio
-                                block:^BOOL(id element, GTXErrorRefType errorOrNil) {
-    if (![element isKindOfClass:[UILabel class]]) {
-      return YES;
-    } else if ([[(UILabel *)element text] length] == 0) {
-      return  YES;
-    }
-    UIColor *textColor, *backgroundColor;
-    CGFloat ratio = [GTXImageAndColorUtils contrastRatioOfUILabel:element
-                                                  outAvgTextColor:&textColor
-                                            outAvgBackgroundColor:&backgroundColor];
-    BOOL hasSufficientContrast =
-        (ratio >= kGTXMinContrastRatioForAccessibleText - kGTXContrastRatioAccuracy);
-    if (!hasSufficientContrast) {
-      // @TODO include actual color values found in the error description as well.
-      NSString *errorDescription = [NSString
-          stringWithFormat:@"This element has a low contrast ratio. All text and icons must have a "
-                           @"minimum contrast ratio of %.5f.\n\nContrast ratio: %.5f\nText color: "
-                           @"%@\nBackground color: %@",
-                           (float)kGTXMinContrastRatioForAccessibleText, (float)ratio,
-                           [textColor gtx_description], [backgroundColor gtx_description]];
-      [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
-                                       element:element
-                                          name:kGTXCheckNameLabelMinimumContrastRatio
-                                   description:errorDescription];
-    }
-    return hasSufficientContrast;
-  }];
+  id<GTXChecking> check = [GTXCheckBlock
+      GTXCheckWithName:kGTXCheckNameLabelMinimumContrastRatio
+        requiresWindow:YES
+                 block:^BOOL(id element, GTXErrorRefType errorOrNil) {
+                   if (![element isKindOfClass:[UILabel class]]) {
+                     return YES;
+                   } else if ([[(UILabel *)element text] length] == 0) {
+                     return YES;
+                   }
+                   UIColor *textColor, *backgroundColor;
+                   CGFloat ratio = [GTXImageAndColorUtils contrastRatioOfUILabel:element
+                                                                 outAvgTextColor:&textColor
+                                                           outAvgBackgroundColor:&backgroundColor];
+                   BOOL hasSufficientContrast =
+                       (ratio >= kGTXMinContrastRatioForAccessibleText - kGTXContrastRatioAccuracy);
+                   if (!hasSufficientContrast) {
+                     // @TODO include actual color values found in the error
+                     // description as well.
+                     NSString *errorDescription =
+                         [NSString stringWithFormat:@"This element has a low contrast ratio. All "
+                                                    @"text and icons must have a "
+                                                    @"minimum contrast ratio of %.5f.\n\nContrast "
+                                                    @"ratio: %.5f\nText color: "
+                                                    @"%@\nBackground color: %@",
+                                                    (float)kGTXMinContrastRatioForAccessibleText,
+                                                    (float)ratio, [textColor gtx_description],
+                                                    [backgroundColor gtx_description]];
+                     [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                                      element:element
+                                                         name:kGTXCheckNameLabelMinimumContrastRatio
+                                                  description:errorDescription];
+                   }
+                   return hasSufficientContrast;
+                 }];
   return check;
 }
 
 + (id<GTXChecking>)checkForSufficientTextViewContrastRatio {
-  id<GTXChecking> check =
-  [GTXCheckBlock GTXCheckWithName:kGTXCheckNameTextViewMinimumContrastRatio
-                            block:^BOOL(id element, GTXErrorRefType errorOrNil) {
-    if (![element isKindOfClass:[UITextView class]]) {
-      return YES;
-    } else if ([[(UITextView *)element text] length] == 0) {
-      return  YES;
-    }
-    UIColor *textColor, *backgroundColor;
-    CGFloat ratio = [GTXImageAndColorUtils contrastRatioOfUITextView:element
-                                                     outAvgTextColor:&textColor
-                                               outAvgBackgroundColor:&backgroundColor];
+  id<GTXChecking> check = [GTXCheckBlock
+      GTXCheckWithName:kGTXCheckNameTextViewMinimumContrastRatio
+        requiresWindow:YES
+                 block:^BOOL(id element, GTXErrorRefType errorOrNil) {
+                   if (![element isKindOfClass:[UITextView class]]) {
+                     return YES;
+                   } else if ([[(UITextView *)element text] length] == 0) {
+                     return YES;
+                   }
+                   UIColor *textColor, *backgroundColor;
+                   CGFloat ratio =
+                       [GTXImageAndColorUtils contrastRatioOfUITextView:element
+                                                        outAvgTextColor:&textColor
+                                                  outAvgBackgroundColor:&backgroundColor];
 
-    BOOL hasSufficientContrast =
-      (ratio >= kGTXMinContrastRatioForAccessibleText - kGTXContrastRatioAccuracy);
-    if (!hasSufficientContrast) {
-      NSString *errorDescription = [NSString
-          stringWithFormat:@"This element has a low contrast ratio. All text and icons must have a "
-                           @"minimum contrast ratio of %.5f.\n\nContrast ratio: %.5f\nText color: "
-                           @"%@\nBackground color: %@",
-                           (float)kGTXMinContrastRatioForAccessibleText, (float)ratio,
-                           [textColor gtx_description], [backgroundColor gtx_description]];
-      [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
-                                       element:element
-                                          name:kGTXCheckNameTextViewMinimumContrastRatio
-                                   description:errorDescription];
-    }
-    return hasSufficientContrast;
-  }];
+                   BOOL hasSufficientContrast =
+                       (ratio >= kGTXMinContrastRatioForAccessibleText - kGTXContrastRatioAccuracy);
+                   if (!hasSufficientContrast) {
+                     NSString *errorDescription =
+                         [NSString stringWithFormat:@"This element has a low contrast ratio. All "
+                                                    @"text and icons must have a "
+                                                    @"minimum contrast ratio of %.5f.\n\nContrast "
+                                                    @"ratio: %.5f\nText color: "
+                                                    @"%@\nBackground color: %@",
+                                                    (float)kGTXMinContrastRatioForAccessibleText,
+                                                    (float)ratio, [textColor gtx_description],
+                                                    [backgroundColor gtx_description]];
+                     [NSError
+                         gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                                 element:element
+                                                    name:kGTXCheckNameTextViewMinimumContrastRatio
+                                             description:errorDescription];
+                   }
+                   return hasSufficientContrast;
+                 }];
+  return check;
+}
+
++ (id<GTXChecking>)checkForSupportsDynamicType {
+  id<GTXChecking> check = [GTXCheckBlock
+      GTXCheckWithName:kGTXCheckNameSupportsDynamicType
+        requiresWindow:NO
+                 block:^BOOL(id element, GTXErrorRefType errorOrNil) {
+                   BOOL respondsToAdjustsFont =
+                       [element respondsToSelector:@selector(adjustsFontForContentSizeCategory)];
+                   BOOL respondsToFont = [element respondsToSelector:@selector(font)];
+                   if (!respondsToAdjustsFont || !respondsToFont) {
+                     // Assume this element doesn't display text. This accounts for the standard
+                     // text displaying views: UILabel, UITextView, and UITextField. Custom elements
+                     // that implement these methods can be checked. Custom elements that don't
+                     // implement these methods or name them differently are ignored.
+                     return YES;
+                   }
+                   if (![element adjustsFontForContentSizeCategory]) {
+                     // TODO: Localize all the strings in this method.
+                     NSString *errorDescription = @"This element is a text displaying element, but "
+                                                  @"adjustsFontForContentSizeCategory is NO. Set "
+                                                  @"adjustsFontForContentSizeCategory to YES to "
+                                                  @"automatically scale with Dynamic Type.";
+                     [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                                      element:element
+                                                         name:kGTXCheckNameSupportsDynamicType
+                                                  description:errorDescription];
+                     return NO;
+                   }
+                   UIFont *font = (UIFont *)[element font];
+                   BOOL textStyleForScalingExists =
+                       [font respondsToSelector:@selector(textStyleForScaling)] &&
+                       ([font textStyleForScaling] != nil);
+                   BOOL isTextStyleAttributeScalable =
+                       [GTXChecksCollection gtx_isFontTextStyleAttributeScalable:font];
+                   if (textStyleForScalingExists || isTextStyleAttributeScalable) {
+                     return YES;
+                   }
+                   NSString *errorDescription =
+                       @"This element is a text displaying element, but its font does not scale "
+                       @"automatically with Dynamic Type. Its font must be constructed using "
+                       @"preferredFontForTextStyle or UIFontMetrics.";
+                   [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                                    element:element
+                                                       name:kGTXCheckNameSupportsDynamicType
+                                                description:errorDescription];
+                   return NO;
+                 }];
   return check;
 }
 
 #pragma mark - Private
 
 /**
+ * Asserts that @c checks contains a check with a name for every name in @c names. Crashes with an
+ * assertion if there is an element in @c names without a corresponding check in @c checks.
+ *
+ * @param checks An array of checks.
+ * @param names A set of names which must be present in @c checks.
+ */
++ (void)gtx_assertChecks:(NSArray<id<GTXChecking>> *)checks
+    containChecksForNames:(NSSet<NSString *> *)names {
+  NSSet<NSString *> *originalNames =
+      [[NSSet alloc] initWithArray:[checks valueForKey:NSStringFromSelector(@selector(name))]];
+  BOOL isSubset = [names isSubsetOfSet:originalNames];
+  GTX_ASSERT(isSubset, @"Cannot exclude nonexistent check. Excluded names: %@. Valid names: %@",
+             names, checks);
+  // Reassign to isSubset because GTX_ASSERT is stripped in production builds, causing an unused
+  // variable warning.
+  isSubset = NO;
+}
+
+/**
  *  @return The NSArray contains the mutually exclusive rules for accessibility traits.
  *          For details, check go/gtx-ios.
  */
@@ -385,16 +561,11 @@
   return @[
     // Conflicting Rule No. 1
     @[
-      @(UIAccessibilityTraitButton),
-      @(UIAccessibilityTraitLink),
-      @(UIAccessibilityTraitSearchField),
-      @(UIAccessibilityTraitKeyboardKey)
+      @(UIAccessibilityTraitButton), @(UIAccessibilityTraitLink),
+      @(UIAccessibilityTraitSearchField), @(UIAccessibilityTraitKeyboardKey)
     ],
     // Conflicting Rule No. 2
-    @[
-      @(UIAccessibilityTraitButton),
-      @(UIAccessibilityTraitAdjustable)
-    ]
+    @[ @(UIAccessibilityTraitButton), @(UIAccessibilityTraitAdjustable) ]
   ];
 }
 
@@ -405,40 +576,23 @@
 + (NSDictionary<NSNumber *, NSString *> const *)gtx_traitsToStringDictionary {
   // Each element below is an valid accessibility traits entity.
   return @{
-    @(UIAccessibilityTraitNone):
-      @"UIAccessibilityTraitNone",
-    @(UIAccessibilityTraitButton):
-      @"UIAccessibilityTraitButton",
-    @(UIAccessibilityTraitLink):
-      @"UIAccessibilityTraitLink",
-    @(UIAccessibilityTraitSearchField):
-      @"UIAccessibilityTraitSearchField",
-    @(UIAccessibilityTraitImage):
-      @"UIAccessibilityTraitImage",
-    @(UIAccessibilityTraitSelected):
-      @"UIAccessibilityTraitSelected",
-    @(UIAccessibilityTraitPlaysSound):
-      @"UIAccessibilityTraitPlaysSound",
-    @(UIAccessibilityTraitKeyboardKey):
-      @"UIAccessibilityTraitKeyboardKey",
-    @(UIAccessibilityTraitStaticText):
-      @"UIAccessibilityTraitStaticText",
-    @(UIAccessibilityTraitSummaryElement):
-      @"UIAccessibilityTraitSummaryElement",
-    @(UIAccessibilityTraitNotEnabled):
-      @"UIAccessibilityTraitNotEnabled",
-    @(UIAccessibilityTraitUpdatesFrequently):
-      @"UIAccessibilityTraitUpdatesFrequently",
-    @(UIAccessibilityTraitStartsMediaSession):
-      @"UIAccessibilityTraitStartsMediaSession",
-    @(UIAccessibilityTraitAdjustable):
-      @"UIAccessibilityTraitAdjustable",
-    @(UIAccessibilityTraitAllowsDirectInteraction):
-      @"UIAccessibilityTraitAllowsDirectInteraction",
-    @(UIAccessibilityTraitCausesPageTurn):
-      @"UIAccessibilityTraitCausesPageTurn",
-    @(UIAccessibilityTraitHeader):
-      @"UIAccessibilityTraitHeader"
+    @(UIAccessibilityTraitNone) : @"UIAccessibilityTraitNone",
+    @(UIAccessibilityTraitButton) : @"UIAccessibilityTraitButton",
+    @(UIAccessibilityTraitLink) : @"UIAccessibilityTraitLink",
+    @(UIAccessibilityTraitSearchField) : @"UIAccessibilityTraitSearchField",
+    @(UIAccessibilityTraitImage) : @"UIAccessibilityTraitImage",
+    @(UIAccessibilityTraitSelected) : @"UIAccessibilityTraitSelected",
+    @(UIAccessibilityTraitPlaysSound) : @"UIAccessibilityTraitPlaysSound",
+    @(UIAccessibilityTraitKeyboardKey) : @"UIAccessibilityTraitKeyboardKey",
+    @(UIAccessibilityTraitStaticText) : @"UIAccessibilityTraitStaticText",
+    @(UIAccessibilityTraitSummaryElement) : @"UIAccessibilityTraitSummaryElement",
+    @(UIAccessibilityTraitNotEnabled) : @"UIAccessibilityTraitNotEnabled",
+    @(UIAccessibilityTraitUpdatesFrequently) : @"UIAccessibilityTraitUpdatesFrequently",
+    @(UIAccessibilityTraitStartsMediaSession) : @"UIAccessibilityTraitStartsMediaSession",
+    @(UIAccessibilityTraitAdjustable) : @"UIAccessibilityTraitAdjustable",
+    @(UIAccessibilityTraitAllowsDirectInteraction) : @"UIAccessibilityTraitAllowsDirectInteraction",
+    @(UIAccessibilityTraitCausesPageTurn) : @"UIAccessibilityTraitCausesPageTurn",
+    @(UIAccessibilityTraitHeader) : @"UIAccessibilityTraitHeader"
   };
 }
 
@@ -452,7 +606,8 @@
   if (nil == stringValue) {
     NSString *errorMessage =
         [NSString stringWithFormat:@"This element defines accessibility traits 0x%016llx which may "
-                                   @"be invalid.", traits];
+                                   @"be invalid.",
+                                   traits];
     [NSError gtx_logOrSetError:errorOrNil
                    description:errorMessage
                           code:GTXCheckErrorCodeGenericError
@@ -479,8 +634,7 @@
         [NSString stringWithFormat:@"String value of accessibility label %@ of class"
                                    @" %@ could not be extracted from element %@",
                                    accessibilityLabel,
-                                   NSStringFromClass([accessibilityLabel class]),
-                                   element];
+                                   NSStringFromClass([accessibilityLabel class]), element];
     [NSError gtx_logOrSetError:errorOrNil
                    description:errorMessage
                           code:GTXCheckErrorCodeGenericError
@@ -504,8 +658,7 @@
  */
 + (NSDictionary<NSNumber *, NSString *> const *)gtx_traitsToRedundantLabelsDictionary {
   return @{
-    @(UIAccessibilityTraitButton):
-      @"button",
+    @(UIAccessibilityTraitButton) : @"button",
   };
 }
 
@@ -516,11 +669,10 @@
   BOOL hasTappableTrait = NO;
   if ([element respondsToSelector:@selector(accessibilityTraits)]) {
     UIAccessibilityTraits traits = [element accessibilityTraits];
-    hasTappableTrait = ((traits & UIAccessibilityTraitButton) ||
-                        (traits & UIAccessibilityTraitLink) ||
-                        (traits & UIAccessibilityTraitSearchField) ||
-                        (traits & UIAccessibilityTraitPlaysSound) ||
-                        (traits & UIAccessibilityTraitKeyboardKey));
+    hasTappableTrait =
+        ((traits & UIAccessibilityTraitButton) || (traits & UIAccessibilityTraitLink) ||
+         (traits & UIAccessibilityTraitSearchField) || (traits & UIAccessibilityTraitPlaysSound) ||
+         (traits & UIAccessibilityTraitKeyboardKey));
   }
   return hasTappableTrait;
 }
@@ -532,21 +684,17 @@
   BOOL hasTextTrait = NO;
   if ([element respondsToSelector:@selector(accessibilityTraits)]) {
     UIAccessibilityTraits traits = [element accessibilityTraits];
-    hasTextTrait = ((traits & UIAccessibilityTraitStaticText) ||
-                    (traits & UIAccessibilityTraitLink) ||
-                    (traits & UIAccessibilityTraitSearchField) ||
-                    (traits & UIAccessibilityTraitKeyboardKey));
+    hasTextTrait =
+        ((traits & UIAccessibilityTraitStaticText) || (traits & UIAccessibilityTraitLink) ||
+         (traits & UIAccessibilityTraitSearchField) || (traits & UIAccessibilityTraitKeyboardKey));
   }
   BOOL isContainedInTextField = NO;
   if ([element respondsToSelector:@selector(accessibilityContainer)]) {
     UIAccessibilityElement *container = [element accessibilityContainer];
     isContainedInTextField = [container isKindOfClass:[UITextField class]];
   }
-  return ([element isKindOfClass:[UILabel class]] ||
-          [element isKindOfClass:[UITextView class]] ||
-          [element isKindOfClass:[UITextField class]] ||
-          hasTextTrait ||
-          isContainedInTextField);
+  return ([element isKindOfClass:[UILabel class]] || [element isKindOfClass:[UITextView class]] ||
+          [element isKindOfClass:[UITextField class]] || hasTextTrait || isContainedInTextField);
 }
 
 /**
@@ -571,6 +719,57 @@
 }
 
 /**
+ * Determines if an element responds to the selectors required to handle touch events.
+ *
+ * @param element The element to check if it responds to selectors.
+ * @return @c YES if @c element responds to @c accessibilityFrame, @c window,
+ *  @c convertPoint:fromView:, and @c pointInside:withEvent:, and if window is non nil, @c NO
+ * otherwise.
+ */
++ (BOOL)gtx_canElementRespondToTouches:(id)element {
+  return [element respondsToSelector:@selector(accessibilityFrame)] &&
+         [element respondsToSelector:@selector(window)] &&
+         [element respondsToSelector:@selector(convertPoint:fromView:)] &&
+         [element respondsToSelector:@selector(pointInside:withEvent:)] && [element window] != nil;
+}
+
+/**
+ * Determines if an element responds to touches in a sufficient area. If so, it is considered
+ * to have a sufficient touch target size. This method dynamically checks which coordinates an
+ * element considers "inside" to determine if its touch target size is sufficient. @c element must
+ * respond to @c accessibilityFrame, @c window,
+ * @c convertPoint:fromView:, and @c pointInside:withEvent:, and window must be non nil. If not, the
+ * element is ignored and @c YES is returned.
+ *
+ * @param element The element of which to check which points are inside.
+ * @return @c YES if @c element responds to points far enough apart to have a sufficient touch
+ *  target size. @c YES if @c element does not respond to the above selectors. @c NO otherwise.
+ */
++ (BOOL)gtx_elementRespondsToTouchesInSufficientArea:(id)element {
+  if (![GTXChecksCollection gtx_canElementRespondToTouches:element]) {
+    return YES;
+  }
+  CGRect center = CGRectMake(CGRectGetMidX([element accessibilityFrame]),
+                             CGRectGetMidY([element accessibilityFrame]), 0, 0);
+  CGRect minimumFrame = CGRectInset(center, -kGTXMinSizeForAccessibleElements / 2.0,
+                                    -kGTXMinSizeForAccessibleElements / 2.0);
+  const NSInteger cornerCount = 4;
+  CGPoint corners[] = {
+      CGPointMake(CGRectGetMinX(minimumFrame), CGRectGetMinY(minimumFrame)),
+      CGPointMake(CGRectGetMaxX(minimumFrame), CGRectGetMinY(minimumFrame)),
+      CGPointMake(CGRectGetMinX(minimumFrame), CGRectGetMaxY(minimumFrame)),
+      CGPointMake(CGRectGetMaxX(minimumFrame), CGRectGetMaxY(minimumFrame))};
+  UIWindow *window = [element window];
+  for (NSInteger i = 0; i < cornerCount; i++) {
+    CGPoint pointInElementCoordinates = [element convertPoint:corners[i] fromView:window];
+    if (![element pointInside:pointInElementCoordinates withEvent:nil]) {
+      return NO;
+    }
+  }
+  return YES;
+}
+
+/**
  *  Determines if @c frame satisfies minimum touch target guidelines, and if it doesn't, adds an
  *  error description to @c array.
  *
@@ -599,4 +798,22 @@
   return [[string lowercaseString] hasSuffix:suffix];
 }
 
+/**
+ *  Determines if @c font has a text style attribute that scales with Dynamic Type.
+ *
+ *  @param font The font to check the attributes of.
+ *  @return @c YES if the font's text style attribute scales with Dynamic Type, @c NO if it does
+ *  not, or if the attribute doesn't exist.
+ */
++ (BOOL)gtx_isFontTextStyleAttributeScalable:(UIFont *)font {
+  if ([font.fontDescriptor objectForKey:UIFontDescriptorTextStyleAttribute] != nil) {
+    NSString *textStyleAttribute =
+        [font.fontDescriptor objectForKey:UIFontDescriptorTextStyleAttribute];
+    if ([textStyleAttribute isKindOfClass:[NSString class]]) {
+      return ![textStyleAttribute isEqualToString:kGTXDefaultFontDescriptorTextStyle];
+    }
+  }
+  return NO;
+}
+
 @end
diff --git a/Classes/GTXCommon.h b/Classes/GTXCommon.h
index c957dba..f8c5ce3 100644
--- a/Classes/GTXCommon.h
+++ b/Classes/GTXCommon.h
@@ -19,6 +19,6 @@
 /**
  *  Defines a double pointer to NSError with nullability attributes to allow both the pointer and
  *  the NSError object being pointed to be @c nil.
- *  @todo Update __nullable to _Nullable when FoM moves to Xcode 7.0+.
+ *  @TODO Update __nullable to _Nullable when FoM moves to Xcode 7.0+.
  */
 typedef NSError *__nullable __strong *__nullable GTXErrorRefType;
diff --git a/Classes/GTXElementBlacklist.h b/Classes/GTXElementBlacklist.h
deleted file mode 100644
index 7519465..0000000
--- a/Classes/GTXElementBlacklist.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copyright 2018 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <UIKit/UIKit.h>
-
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- *  Describes a blacklist of a elements of a given class and optionally for a given GTXCheck.
- */
-@interface GTXElementBlacklist : NSObject
-
-- (instancetype)init NS_UNAVAILABLE;
-- (instancetype)initWithElementClassName:(NSString *)elementClassName
-                               checkName:(nullable NSString *)checkName;
-
-@property (nonatomic, copy) NSString *elementClassName;
-@property (nonatomic, nullable, copy) NSString *checkName;
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXElementBlacklist.m b/Classes/GTXElementBlacklist.m
deleted file mode 100644
index 154ad02..0000000
--- a/Classes/GTXElementBlacklist.m
+++ /dev/null
@@ -1,32 +0,0 @@
-//
-// Copyright 2018 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "GTXElementBlacklist.h"
-
-@implementation GTXElementBlacklist
-
-- (instancetype)initWithElementClassName:(NSString *)elementClassName
-                               checkName:(NSString *)checkName {
-  NSParameterAssert(elementClassName);
-  self = [super init];
-  if (self) {
-    _elementClassName = [elementClassName copy];
-    _checkName = [checkName copy];
-  }
-  return self;
-}
-
-@end
diff --git a/Classes/GTXElementReference.h b/Classes/GTXElementReference.h
new file mode 100644
index 0000000..868b836
--- /dev/null
+++ b/Classes/GTXElementReference.h
@@ -0,0 +1,99 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Describes a @c UIView or @c UIAccessibilityElement without referencing the original object. The
+ * entry point for comparing if two elements refer to the same conceptual element (which may not be
+ * literally the same element. For example, table views might use different reusable cells for the
+ * same cell at different times, but both refer to the same element).
+ */
+@interface GTXElementReference : NSObject
+
+/**
+ * The address of the object. Not an actual reference to avoid retain cycles are automatically being
+ * set to nil.
+ */
+@property(assign, nonatomic, readonly) NSUInteger elementAddress;
+
+/**
+ * The class of the element.
+ */
+@property(strong, nonatomic, readonly) Class elementClass;
+
+/**
+ * The accessibility label of the element, if exists.
+ */
+@property(copy, nonatomic, nullable, readonly) NSString *accessibilityLabel;
+
+/**
+ * The accessibility identifier of the element, if exists.
+ */
+@property(copy, nonatomic, nullable, readonly) NSString *accessibilityIdentifier;
+
+/**
+ * The accessibility frame of the element.
+ */
+@property(assign, nonatomic, readonly) CGRect accessibilityFrame;
+
+/**
+ * A human readable description of the element.
+ */
+@property(copy, nonatomic, readonly) NSString *elementDescription;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/**
+ * Initializes this instance with the given properties describing a @c UIView or
+ * @c UIAccessibilityElement.
+ *
+ * @param elementAddress The original element's memory address as an integer.
+ * @param elementClass The original element's class.
+ * @param accessibilityLabel Optional. The original element's accessibility label.
+ * @param accessibilityIdentifier Optional. The original element's accessibility identifier.
+ * @param accessibilityFrame The original element's accessibility frame.
+ * @param elementDescription A concise, human readable description of the element.
+ * @return An initialized @c GTXElementReference instance.
+ */
+- (instancetype)initWithElementAddress:(NSUInteger)elementAddress
+                          elementClass:(Class)elementClass
+                    accessibilityLabel:(nullable NSString *)accessibilityLabel
+               accessibilityIdentifier:(nullable NSString *)accessibilityIdentifier
+                    accessibilityFrame:(CGRect)accessibilityFrame
+                    elementDescription:(NSString *)elementDescription NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes this element with the properties in @c element.
+ *
+ * @param element The element this instance should reference, based on its accessibility properties.
+ * @return An initialized @c GTXElementReference instance.
+ */
+- (instancetype)initWithElement:(id)element;
+
+/**
+ * Constructs a @c GTXElementReference object from an error produced by a @c GTXChecking instance.
+ *
+ * @param error An error produced by a @c GTXChecking instance. Fails with an assertion if
+ * @c error.userInfo does not contain the key @c kGTXErrorFailingElementKey.
+ */
+- (instancetype)initWithError:(NSError *)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXElementReference.m b/Classes/GTXElementReference.m
new file mode 100644
index 0000000..f5d715b
--- /dev/null
+++ b/Classes/GTXElementReference.m
@@ -0,0 +1,78 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXElementReference.h"
+
+#import "GTXAssertions.h"
+#import "NSError+GTXAdditions.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation GTXElementReference
+
+- (instancetype)initWithElementAddress:(NSUInteger)elementAddress
+                          elementClass:(Class)elementClass
+                    accessibilityLabel:(nullable NSString *)accessibilityLabel
+               accessibilityIdentifier:(nullable NSString *)accessibilityIdentifier
+                    accessibilityFrame:(CGRect)accessibilityFrame
+                    elementDescription:(NSString *)description {
+  self = [super init];
+  if (self) {
+    GTX_ASSERT(elementClass, @"elementClass must be nonnull.");
+    GTX_ASSERT(description, @"description must be nonnull.");
+    _elementAddress = elementAddress;
+    _elementClass = elementClass;
+    _accessibilityLabel = [accessibilityLabel copy];
+    _accessibilityIdentifier = [accessibilityIdentifier copy];
+    _accessibilityFrame = accessibilityFrame;
+    _elementDescription = [description copy];
+  }
+  return self;
+}
+
+- (instancetype)initWithElement:(id)element {
+  GTX_ASSERT(element, @"element must be nonnull.");
+  NSString *accessibilityLabel = nil;
+  NSString *accessibilityIdentifier = nil;
+  CGRect accessibilityFrame = CGRectZero;
+  NSString *elementDescription = [NSString stringWithFormat:@"%@ %p", [element class], element];
+  if ([element respondsToSelector:@selector(accessibilityLabel)]) {
+    accessibilityLabel = [element accessibilityLabel];
+  }
+  if ([element respondsToSelector:@selector(accessibilityIdentifier)]) {
+    accessibilityIdentifier = [element accessibilityIdentifier];
+  }
+  if ([element respondsToSelector:@selector(accessibilityFrame)]) {
+    accessibilityFrame = [element accessibilityFrame];
+  }
+  return [self initWithElementAddress:(NSUInteger)element
+                         elementClass:[element class]
+                   accessibilityLabel:accessibilityLabel
+              accessibilityIdentifier:accessibilityIdentifier
+                   accessibilityFrame:accessibilityFrame
+                   elementDescription:elementDescription];
+}
+
+- (instancetype)initWithError:(NSError *)error {
+  GTX_ASSERT(error, @"error must be nonnull.");
+  id element = error.userInfo[kGTXErrorFailingElementKey];
+  GTX_ASSERT(element, @"userInfo must have value for key kGTXErrorFailingElementKey");
+  return [self initWithElement:element];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXElementResultCollection.h b/Classes/GTXElementResultCollection.h
new file mode 100644
index 0000000..686e301
--- /dev/null
+++ b/Classes/GTXElementResultCollection.h
@@ -0,0 +1,66 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <Foundation/Foundation.h>
+
+#import "GTXCheckResult.h"
+#import "GTXElementReference.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * Represents all the accessibility issues found on a single UI element.
+ */
+@interface GTXElementResultCollection : NSObject
+
+/**
+ * Refers to the UI element without maintaining a reference to the original instance (which would
+ * either retain it or be set to nil).
+ */
+@property(strong, nonatomic, readonly) GTXElementReference *elementReference;
+
+/**
+ * All accessibility issues found on @c elementReference. Each result should be produced by a
+ * different @c GTXChecking instance.
+ */
+@property(copy, nonatomic, readonly) NSArray<GTXCheckResult *> *checkResults;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/**
+ * Initializes a @c GTXElementResultCollection with the given parameters.
+ *
+ * @param element Represents the UI element with accessibility issues this instance refers to.
+ * @param checkResults The accessibility issues associated with @c element. Each element in
+ * @c checkResults must be produced by a different @c GTXChecking instance.
+ * @return An initialized @c GTXElementResultCollection instance.
+ */
+- (instancetype)initWithElement:(GTXElementReference *)element
+                   checkResults:(NSArray<GTXCheckResult *> *)checkResults NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes a @c GTXElementResultCollection with an error representing the element and check
+ * results.
+ *
+ * @param error An error aggregating all errors produced by running @c GTXChecking instances on a
+ * given element.
+ * @return An initialized @c GTXElementResultCollection instance.
+ */
+- (instancetype)initWithError:(NSError *)error;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXElementResultCollection.m b/Classes/GTXElementResultCollection.m
new file mode 100644
index 0000000..e17124f
--- /dev/null
+++ b/Classes/GTXElementResultCollection.m
@@ -0,0 +1,51 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXElementResultCollection.h"
+
+#import "GTXAssertions.h"
+#import "NSError+GTXAdditions.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation GTXElementResultCollection
+
+- (instancetype)initWithElement:(GTXElementReference *)element
+                   checkResults:(NSArray<GTXCheckResult *> *)checkResults {
+  self = [super init];
+  if (self) {
+    _elementReference = element;
+    _checkResults = [checkResults copy];
+  }
+  return self;
+}
+
+- (instancetype)initWithError:(NSError *)error {
+  GTX_ASSERT(error, @"error cannot be nil.");
+  NSArray<NSError *> *underlyingErrors = error.userInfo[kGTXErrorUnderlyingErrorsKey];
+  GTX_ASSERT(underlyingErrors.count != 0,
+             @"error.userInfo must have a nonempty value for key kGTXErrorUnderlyingErrorsKey.");
+  GTXElementReference *elementReference = [[GTXElementReference alloc] initWithError:error];
+  NSMutableArray<GTXCheckResult *> *checkResults = [[NSMutableArray alloc] init];
+  for (NSError *underlyingError in underlyingErrors) {
+    [checkResults addObject:[GTXCheckResult checkResultFromError:underlyingError]];
+  }
+  return [self initWithElement:elementReference checkResults:checkResults];
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXErrorReporter.m b/Classes/GTXErrorReporter.m
index 475566b..af46b56 100644
--- a/Classes/GTXErrorReporter.m
+++ b/Classes/GTXErrorReporter.m
@@ -63,7 +63,7 @@
 }
 
 + (NSString *)hierarchyDescriptionOfRootElements:(NSArray *)rootElements {
-  NSMutableArray *descriptions = [NSMutableArray new];
+  NSMutableArray *descriptions = [[NSMutableArray alloc] init];
   for (id rootElement in rootElements) {
     [self gtx_getRecursiveHierarchyDescriptionOfRootElement:rootElement
                                                      indent:nil
@@ -86,9 +86,9 @@
                                                    indent:(NSString *)indent
                                            outDescription:(NSMutableArray *)description {
   indent = indent ? indent : @"";
-  NSMutableSet *axChildren = [NSMutableSet new];
-  NSMutableSet *subviews = [NSMutableSet new];
-  NSMutableSet *both = [NSMutableSet new];
+  NSMutableSet<id> *axChildren = [[NSMutableSet alloc] init];
+  NSMutableSet<id> *subviews = [[NSMutableSet alloc] init];
+  NSMutableSet<id> *both = [[NSMutableSet alloc] init];
   // Get all a11y children.
   NSArray *elements = [element accessibilityElements];
   NSInteger count = [element accessibilityElementCount];
@@ -155,7 +155,7 @@
  *  @return The description of the given element prepended with the indent.
  */
 + (NSString *)gtx_hierarchyDescriptionOfSingleElement:(id)element indent:(NSString *)indent {
-  NSMutableArray *descriptions = [NSMutableArray new];
+  NSMutableArray<NSString *> *descriptions = [[NSMutableArray alloc] init];
   [descriptions addObject:[NSString stringWithFormat:@"%@<%@:%p",
                                                      indent,
                                                      NSStringFromClass([element class]),
@@ -217,7 +217,7 @@
     return @"None";
   }
 
-  NSMutableArray *traitsStrings = [NSMutableArray new];
+  NSMutableArray<NSString *> *traitsStrings = [[NSMutableArray alloc] init];
   const NSDictionary<NSNumber *, NSString *> *traitsToString = [self gtx_traitsToStringDictionary];
   for (NSNumber *trait in traitsToString.allKeys) {
     if (traits & [trait unsignedLongLongValue]) {
diff --git a/Classes/GTXBlacklistBlock.h b/Classes/GTXExcludeListBlock.h
similarity index 64%
rename from Classes/GTXBlacklistBlock.h
rename to Classes/GTXExcludeListBlock.h
index 1e073cd..4b649af 100644
--- a/Classes/GTXBlacklistBlock.h
+++ b/Classes/GTXExcludeListBlock.h
@@ -16,7 +16,7 @@
 
 #import <UIKit/UIKit.h>
 
-#import "GTXBlacklisting.h"
+#import "GTXExcludeListing.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -27,24 +27,25 @@
  @param checkName Name of the check for which element must be looked up.
  @return @c YES if element needs to be ignored for the given check @c NO other wise.
  */
-typedef BOOL(^GTXIgnoreElementMatcher)(id element, NSString *checkName);
+typedef BOOL (^GTXIgnoreElementMatcher)(id element, NSString *checkName);
 
-@interface GTXBlacklistBlock: NSObject<GTXBlacklisting>
+@interface GTXExcludeListBlock : NSObject <GTXExcludeListing>
 
 /**
- *  GTXBlacklistBlock::init is disabled, instead use GTXBlacklistBlock::blacklistWithBlock:
- *  method to create GTXBlacklists.
+ *  GTXExcludeListBlock::init is disabled, instead use GTXExcludeListBlock::excludeListWithBlock:
+ *  method to create GTXExcludeLists.
  */
-- (instancetype)init __attribute__((unavailable("Use blacklistWithBlock: instead.")));
+- (instancetype)init __attribute__((unavailable("Use excludeListWithBlock: instead.")));
 
 /**
- *  Creates an GTXBlacklist with the given @c block that determines if an element should be ignored.
+ *  Creates an GTXExcludeList with the given @c block that determines if an element should be
+ * ignored.
  *
  *  @param block A block that determines if an element should be ignored.
  *
- *  @return A GTXBlacklist object.
+ *  @return A GTXExcludeList object.
  */
-+ (id<GTXBlacklisting>)blacklistWithBlock:(GTXIgnoreElementMatcher)block;
++ (id<GTXExcludeListing>)excludeListWithBlock:(GTXIgnoreElementMatcher)block;
 
 @end
 
diff --git a/Classes/GTXBlacklistBlock.m b/Classes/GTXExcludeListBlock.m
similarity index 79%
rename from Classes/GTXBlacklistBlock.m
rename to Classes/GTXExcludeListBlock.m
index 3c16499..364a155 100644
--- a/Classes/GTXBlacklistBlock.m
+++ b/Classes/GTXExcludeListBlock.m
@@ -14,16 +14,16 @@
 // limitations under the License.
 //
 
-#import "GTXBlacklistBlock.h"
+#import "GTXExcludeListBlock.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
-@implementation GTXBlacklistBlock {
+@implementation GTXExcludeListBlock {
   GTXIgnoreElementMatcher _block;
 }
 
-+ (id<GTXBlacklisting>)blacklistWithBlock:(GTXIgnoreElementMatcher)block {
-  return [[GTXBlacklistBlock alloc] initWithBlock:block];
++ (id<GTXExcludeListing>)excludeListWithBlock:(GTXIgnoreElementMatcher)block {
+  return [[GTXExcludeListBlock alloc] initWithBlock:block];
 }
 
 - (instancetype)initWithBlock:(GTXIgnoreElementMatcher)block {
@@ -36,7 +36,7 @@
   return self;
 }
 
-#pragma mark - GTXBlacklisting
+#pragma mark - GTXExcludeListing
 
 - (BOOL)shouldIgnoreElement:(id)element forCheckNamed:(NSString *)check {
   return _block(element, check);
diff --git a/Classes/GTXExcludeListFactory.h b/Classes/GTXExcludeListFactory.h
new file mode 100644
index 0000000..6fb3550
--- /dev/null
+++ b/Classes/GTXExcludeListFactory.h
@@ -0,0 +1,61 @@
+//
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "GTXExcludeListing.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ *  Factory for GTXExcludeListing objects for excluding elements from checks.
+ */
+@interface GTXExcludeListFactory : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
+/**
+ *  Returns a GTXExcludeListing object that ignores all elements that are instances of
+ *  a given @c elementClassName.
+ *
+ *  @param elementClassName The name of the class that should be excluded.
+ *  @return A GTXExcludeListing object that ignores all elements of the given class.
+ */
++ (id<GTXExcludeListing>)excludeListWithClassName:(NSString *)elementClassName;
+/**
+ *  Returns a GTXExcludeListing object that ignores all elements that are instances of
+ *  a given @c elementClassName, but only for GTXChecking objects with a given @c checkName.
+ *
+ *  @param elementClassName The name of the class that should be excluded.
+ *  @param skipCheckName The name of the check that should ignore elements of the given class.
+ *  @return A GTXExcludeListing object that ignores all elements of the given class when running the
+ *  given check.
+ */
++ (id<GTXExcludeListing>)excludeListWithClassName:(NSString *)elementClassName
+                                        checkName:(NSString *)skipCheckName;
+/**
+ *  Returns a GTXExcludeListing object that ignores all elements with a given accessibility
+ *  identifier, but only for GTXChecking objects with a given @c checkName.
+ *
+ *  @param accessibilityId The accessibility identifier of the element that should be excluded.
+ *  @param skipCheckName The name of the check that should ignore elements with the given
+ *  accessibility identifier.
+ */
++ (id<GTXExcludeListing>)excludeListWithAccessibilityIdentifier:(NSString *)accessibilityId
+                                                      checkName:(NSString *)skipCheckName;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXBlacklistFactory.m b/Classes/GTXExcludeListFactory.m
similarity index 66%
rename from Classes/GTXBlacklistFactory.m
rename to Classes/GTXExcludeListFactory.m
index 5c4d2d8..059558d 100644
--- a/Classes/GTXBlacklistFactory.m
+++ b/Classes/GTXExcludeListFactory.m
@@ -14,43 +14,43 @@
 // limitations under the License.
 //
 
-#import "GTXBlacklistFactory.h"
+#import "GTXExcludeListFactory.h"
 
-#import "GTXBlacklistBlock.h"
+#import "GTXExcludeListBlock.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
-@implementation GTXBlacklistFactory
+@implementation GTXExcludeListFactory
 
-+ (id<GTXBlacklisting>)blacklistWithClassName:(NSString *)elementClassName {
++ (id<GTXExcludeListing>)excludeListWithClassName:(NSString *)elementClassName {
   Class classObject = NSClassFromString(elementClassName);
   NSAssert(classObject, @"Class named %@ does not exist!", elementClassName);
   GTXIgnoreElementMatcher matcher = ^BOOL(id element, NSString *checkName) {
     return [element isKindOfClass:classObject];
   };
-  return [GTXBlacklistBlock blacklistWithBlock:matcher];
+  return [GTXExcludeListBlock excludeListWithBlock:matcher];
 }
 
-+ (id<GTXBlacklisting>)blacklistWithClassName:(NSString *)elementClassName
-                                    checkName:(NSString *)skipCheckName {
++ (id<GTXExcludeListing>)excludeListWithClassName:(NSString *)elementClassName
+                                        checkName:(NSString *)skipCheckName {
   NSParameterAssert(elementClassName);
   Class classObject = NSClassFromString(elementClassName);
   NSAssert(classObject, @"Class named %@ does not exist!", elementClassName);
   GTXIgnoreElementMatcher matcher = ^BOOL(id element, NSString *checkName) {
     return [element isKindOfClass:classObject] && [checkName isEqualToString:skipCheckName];
   };
-  return [GTXBlacklistBlock blacklistWithBlock:matcher];
+  return [GTXExcludeListBlock excludeListWithBlock:matcher];
 }
 
-+ (id<GTXBlacklisting>)blacklistWithAccessibilityIdentifier:(NSString *)accessibilityId
-                                                  checkName:(NSString *)skipCheckName {
++ (id<GTXExcludeListing>)excludeListWithAccessibilityIdentifier:(NSString *)accessibilityId
+                                                      checkName:(NSString *)skipCheckName {
   NSParameterAssert(accessibilityId);
   NSParameterAssert(skipCheckName);
   GTXIgnoreElementMatcher matcher = ^BOOL(id element, NSString *checkName) {
     return [[element accessibilityIdentifier] isEqualToString:accessibilityId] &&
-        [checkName isEqualToString:skipCheckName];
+           [checkName isEqualToString:skipCheckName];
   };
-  return [GTXBlacklistBlock blacklistWithBlock:matcher];
+  return [GTXExcludeListBlock excludeListWithBlock:matcher];
 }
 
 @end
diff --git a/Classes/GTXBlacklisting.h b/Classes/GTXExcludeListing.h
similarity index 89%
rename from Classes/GTXBlacklisting.h
rename to Classes/GTXExcludeListing.h
index 401d86f..f6bf6d5 100644
--- a/Classes/GTXBlacklisting.h
+++ b/Classes/GTXExcludeListing.h
@@ -19,9 +19,9 @@
 NS_ASSUME_NONNULL_BEGIN
 
 /**
- *  Protocol for blacklisting certain types of UI elements in accessibility checks.
+ *  Protocol for excluding certain types of UI elements in accessibility checks.
  */
-@protocol GTXBlacklisting<NSObject>
+@protocol GTXExcludeListing <NSObject>
 
 /**
  *  Determines if the given @c check should not be run on the given @c element.
diff --git a/Classes/GTXHierarchyResultCollection.h b/Classes/GTXHierarchyResultCollection.h
new file mode 100644
index 0000000..78eb895
--- /dev/null
+++ b/Classes/GTXHierarchyResultCollection.h
@@ -0,0 +1,73 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "GTXElementResultCollection.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ * All the accessibility issues found in a view hierarchy, defined by an array of root elements.
+ */
+@interface GTXHierarchyResultCollection : NSObject
+
+/**
+ * All accessibility issues found in the hierarchy. Each entry represents an element with an
+ * accessibility issue.
+ */
+@property(copy, nonatomic, readonly) NSArray<GTXElementResultCollection *> *elementResults;
+
+/**
+ * A screenshot of the view hierarchy as it appeared when the results were collected, or @c nil if
+ * none exists.
+ */
+@property(strong, nonatomic, readonly) UIImage *screenshot;
+
+- (instancetype)init NS_UNAVAILABLE;
+
+/**
+ * Initializes a @c GTXHierarchyResultCollection instance with the given parameters.
+ *
+ * @param elementResults The elements in the hierarchy with accessibility issues.
+ * @param screenshot A screenshot of the view hierarchy as it appeared when the results were
+ *  collected.
+ * @return An initialized @c GTXHierarchyResultCollection instance.
+ */
+- (instancetype)initWithElementResults:(NSArray<GTXElementResultCollection *> *)elementResults
+                            screenshot:(UIImage *)screenshot NS_DESIGNATED_INITIALIZER;
+
+/**
+ * Initializes a @c GTXHierarchyResultCollection instance by parsing @c errors representing
+ * aggregate errors produced by @c GTXToolKit.
+ *
+ * @param errors An array of errors. Each error must be produced by a @c GTXToolKit instance. @c nil
+ *  is treated as an empty array.
+ * @param rootViews The root views scanned to produce @c errors. Fails with an assertion if
+ *  @c rootViews is empty. It is assumed all elements in @c rootViews have the same origin.
+ * @return An initialized @c GTXHierarchyResultCollection instance.
+ */
+- (instancetype)initWithErrors:(nullable NSArray<NSError *> *)errors
+                     rootViews:(NSArray<UIView *> *)rootViews;
+
+/**
+ * @return The number of check results across all elements in this scan.
+ */
+- (NSUInteger)checkResultCount;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXHierarchyResultCollection.m b/Classes/GTXHierarchyResultCollection.m
new file mode 100644
index 0000000..c30d729
--- /dev/null
+++ b/Classes/GTXHierarchyResultCollection.m
@@ -0,0 +1,59 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXHierarchyResultCollection.h"
+
+#import "GTXAssertions.h"
+#import "GTXImageAndColorUtils.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation GTXHierarchyResultCollection
+
+- (instancetype)initWithElementResults:(NSArray<GTXElementResultCollection *> *)elementResults
+                            screenshot:(UIImage *)screenshot {
+  self = [super init];
+  if (self) {
+    GTX_ASSERT(elementResults, @"elementResults must be nonnil.");
+    GTX_ASSERT(screenshot, @"screenshot must be nonnil.");
+    _elementResults = [elementResults copy];
+    _screenshot = screenshot;
+  }
+  return self;
+}
+
+- (instancetype)initWithErrors:(nullable NSArray<NSError *> *)errors
+                     rootViews:(NSArray<UIView *> *)rootViews {
+  GTX_ASSERT(rootViews.count > 0, @"rootViews must be nonnil and nonempty.");
+  NSMutableArray<GTXElementResultCollection *> *elementResults = [[NSMutableArray alloc] init];
+  for (NSError *error in errors) {
+    [elementResults addObject:[[GTXElementResultCollection alloc] initWithError:error]];
+  }
+  UIImage *screenshot = [GTXImageAndColorUtils imageByCompositingViews:rootViews];
+  return [self initWithElementResults:elementResults screenshot:screenshot];
+}
+
+- (NSUInteger)checkResultCount {
+  NSUInteger count = 0;
+  for (GTXElementResultCollection *result in self.elementResults) {
+    count += result.checkResults.count;
+  }
+  return count;
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXImageAndColorUtils.h b/Classes/GTXImageAndColorUtils.h
index 44a58e5..00a6fa4 100644
--- a/Classes/GTXImageAndColorUtils.h
+++ b/Classes/GTXImageAndColorUtils.h
@@ -81,4 +81,28 @@
                      outAvgTextColor:(UIColor **)outAvgTextColor
                outAvgBackgroundColor:(UIColor **)outAvgBackgroundColor;
 
+/**
+ *  Renders the view hierarchy of @c view to @c context, appropriately translating subviews to
+ *  render in the correct position. The view hierarchy must be rendered manually because
+ *  @c drawViewHierarchy:afterScreenUpdates: with @c YES for @c afterScreenUpdates causes VoiceOver
+ *  to reset focus to the first element of the view hierarchy. However, passing @c NO causes the
+ *  screenshot to not use any recent changes, such as changing the text color to identify foreground
+ *  color. Manually rendering the view hierarchy avoids both of these problems.
+ *
+ *  @param view The root of the view hierarchy to render.
+ *  @param context The graphics context to which to render.
+ */
++ (void)renderViewHierarchy:(UIView *)view inContext:(CGContextRef)context;
+
+/**
+ * Renders the views in @c views to a single image, with the first element in back and the last
+ * element in front. The size of the image is equal to the greatest width and greatest height of the
+ * bounds in @c views. May not be the bounds of the largest view. For example, one view may have a
+ * larger width and another has a larger height.
+ *
+ * @param views The views to render. Fails with an assertion if @c views is empty.
+ * @return An image of all the views in @c views.
+ */
++ (UIImage *)imageByCompositingViews:(NSArray<UIView *> *)views;
+
 @end
diff --git a/Classes/GTXImageAndColorUtils.m b/Classes/GTXImageAndColorUtils.mm
similarity index 82%
rename from Classes/GTXImageAndColorUtils.m
rename to Classes/GTXImageAndColorUtils.mm
index 8c6be73..c565eea 100644
--- a/Classes/GTXImageAndColorUtils.m
+++ b/Classes/GTXImageAndColorUtils.mm
@@ -16,7 +16,9 @@
 
 #import "GTXImageAndColorUtils.h"
 
+#import "GTXAssertions.h"
 #import "GTXImageRGBAData.h"
+#include "image_color_utils.h"
 
 /**
  *  Accuracy of the contrast ratios provided by the APIs in this class.
@@ -26,16 +28,7 @@
 @implementation GTXImageAndColorUtils
 
 + (CGFloat)luminanceWithRed:(CGFloat)red blue:(CGFloat)blue green:(CGFloat)green {
-  // Based on https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
-  CGFloat (^adjustedComponent)(CGFloat) = ^CGFloat(CGFloat component) {
-    if (component < 0.03928f) {
-      return component / 12.92f;
-    } else {
-      return (CGFloat)pow((component + 0.055f) / 1.055f, 2.4f);
-    }
-  };
-  return (0.2126f * adjustedComponent(red) + 0.0722f * adjustedComponent(blue) +
-          0.7152f * adjustedComponent(green));
+  return gtx::image_color_utils::Luminance(red, blue, green);
 }
 
 + (CGFloat)luminanceWithColor:(UIColor *)color {
@@ -46,12 +39,7 @@
 
 + (CGFloat)contrastRatioWithLuminaceOfFirstColor:(CGFloat)color1Luminance
                        andLuminanceOfSecondColor:(CGFloat)color2Luminance {
-  NSParameterAssert(color2Luminance >= 0);
-  NSParameterAssert(color1Luminance >= 0);
-  CGFloat brighterColorLuminance = MAX(color1Luminance, color2Luminance);
-  CGFloat darkerColorLuminance = MIN(color1Luminance, color2Luminance);
-  // Based on https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
-  return (brighterColorLuminance + 0.05f) / (darkerColorLuminance + 0.05f);
+  return gtx::image_color_utils::ContrastRatio(color1Luminance, color2Luminance);
 }
 
 + (CGFloat)contrastRatioOfUILabel:(UILabel *)label
@@ -100,6 +88,31 @@
                                outAvgBackgroundColor:outAvgBackgroundColor];
 }
 
++ (void)renderViewHierarchy:(UIView *)view inContext:(CGContextRef)context {
+  CGFloat xOffset = CGRectGetMinX(view.frame) - CGRectGetMinX(view.bounds);
+  CGFloat yOffset = CGRectGetMinY(view.frame) - CGRectGetMinY(view.bounds);
+  CGContextSaveGState(context);
+  CGContextTranslateCTM(context, xOffset, yOffset);
+  [view.layer renderInContext:context];
+  for (UIView *subview in view.subviews) {
+    [GTXImageAndColorUtils renderViewHierarchy:subview inContext:context];
+  }
+  CGContextRestoreGState(context);
+}
+
++ (UIImage *)imageByCompositingViews:(NSArray<UIView *> *)views {
+  GTX_ASSERT(views.count > 0, @"views cannot be empty.");
+  CGSize size = [[self class] gtx_maximumSizeInViews:views];
+  UIGraphicsBeginImageContextWithOptions(size, NO, 0.0);
+  for (UIView *view in views) {
+    // Pass NO to prevent VoiceOver from resetting focus.
+    [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];
+  }
+  UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
+  UIGraphicsEndImageContext();
+  return image;
+}
+
 #pragma mark - Utils
 
 + (UIImage *)gtx_takeSnapshot:(UIView *)element {
@@ -112,36 +125,13 @@
   }
   CGContextRef context = UIGraphicsGetCurrentContext();
   CGContextTranslateCTM(context, -labelBounds.origin.x, -labelBounds.origin.y);
-  [GTXImageAndColorUtils gtx_renderViewHierarchy:window inContext:context];
+  [GTXImageAndColorUtils renderViewHierarchy:window inContext:context];
   UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();
   return image;
 }
 
 /**
- *  Renders the view hierarchy of @c view to @c context, appropriately translating subviews to
- *  render in the correct position. The view hierarchy must be rendered manually because
- *  @c drawViewHierarchy:afterScreenUpdates: with @c YES for @c afterScreenUpdates causes VoiceOver
- *  to reset focus to the first element of the view hierarchy. However, passing @c NO causes the
- *  screenshot to not use any recent changes, such as changing the text color to identify foreground
- *  color. Manually rendering the view hierarchy avoids both of these problems.
- *
- *  @param view The root of the view hierarchy to render.
- *  @param context The graphics context to which to render.
- */
-+ (void)gtx_renderViewHierarchy:(UIView *)view inContext:(CGContextRef)context {
-  CGFloat xOffset = CGRectGetMinX(view.frame) - CGRectGetMinX(view.bounds);
-  CGFloat yOffset = CGRectGetMinY(view.frame) - CGRectGetMinY(view.bounds);
-  CGContextSaveGState(context);
-  CGContextTranslateCTM(context, xOffset, yOffset);
-  [view.layer renderInContext:context];
-  for (UIView *subview in view.subviews) {
-    [GTXImageAndColorUtils gtx_renderViewHierarchy:subview inContext:context];
-  }
-  CGContextRestoreGState(context);
-}
-
-/**
  *  Computes the contrast ratio for the text in the given image. This method also requires image of
  *  the text element with the text color changed, by comparing both the image pixels its possible to
  *  determine which pixels belong to text (will change between images) and which ones belong to the
@@ -163,12 +153,13 @@
   NSInteger textPixelCount = 0;
   CGFloat backgroundLogAverage = 0;
   NSInteger backgroundPixelCount = 0;
+  const NSInteger bytesPerPixel = 4;
   GTXImageRGBAData *beforeData = [[GTXImageRGBAData alloc] initWithUIImage:original];
   GTXImageRGBAData *afterData = [[GTXImageRGBAData alloc] initWithUIImage:colorShifted];
   struct {
     CGFloat totalRed, totalBlue, totalGreen;
     NSInteger count;
-  } textColor = {0}, backgroundColor = {0};
+  } textColor = {}, backgroundColor = {};
 
   // Geometric mean of n numbers is the nth root of the product of the numbers however to avoid
   // issues with floating point accuracies we first compute the average of the logarithms and then
@@ -182,9 +173,9 @@
   for (NSUInteger column = 0; column < beforeData.width; column++) {
     for (NSUInteger row = 0; row < beforeData.height; row++) {
       unsigned char *beforeOffset =
-          beforeData.rgba + column * beforeData.bytesPerPixel + row * beforeData.bytesPerRow;
+          beforeData.rgba + column * bytesPerPixel + row * beforeData.bytesPerRow;
       unsigned char *afterOffset =
-          afterData.rgba + column * afterData.bytesPerPixel + row * afterData.bytesPerRow;
+          afterData.rgba + column * bytesPerPixel + row * afterData.bytesPerRow;
       CGFloat red = beforeOffset[0] / 255.0f;
       CGFloat green = beforeOffset[1] / 255.0f;
       CGFloat blue = beforeOffset[2] / 255.0f;
@@ -265,4 +256,27 @@
   return [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
 }
 
+/**
+ * Calculates the maximum size enclosing all bounds in @c views.
+ *
+ * @param views The views to calculate the maximum size of. Fails with an assertion if @c views is
+ *  empty.
+ * @return A size enclosing all bounds in @c views. May not be the bounds of the largest view. For
+ *  example, one view may have a larger width and another has a larger height.
+ */
++ (CGSize)gtx_maximumSizeInViews:(NSArray<UIView *> *)views {
+  GTX_ASSERT(views.count > 0, @"views cannot be empty.");
+  CGFloat width = views[0].bounds.size.width;
+  CGFloat height = views[0].bounds.size.height;
+  for (UIView *view in views) {
+    if (view.bounds.size.width > width) {
+      width = view.bounds.size.width;
+    }
+    if (view.bounds.size.height > height) {
+      height = view.bounds.size.height;
+    }
+  }
+  return CGSizeMake(width, height);
+}
+
 @end
diff --git a/Classes/GTXArtifactImplementing.h b/Classes/GTXImageRGBAData+GTXOOPAdditions.h
similarity index 61%
copy from Classes/GTXArtifactImplementing.h
copy to Classes/GTXImageRGBAData+GTXOOPAdditions.h
index 24d9344..6d96332 100644
--- a/Classes/GTXArtifactImplementing.h
+++ b/Classes/GTXImageRGBAData+GTXOOPAdditions.h
@@ -1,5 +1,5 @@
 //
-// Copyright 2019 Google Inc.
+// Copyright 2020 Google Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -16,18 +16,21 @@
 
 #import <UIKit/UIKit.h>
 
+#import "GTXImageRGBAData.h"
+#include "check.h"
+
 NS_ASSUME_NONNULL_BEGIN
 
 /**
- *  A protocol that all artifacts must implement to ensure that snapshots can be taken.
+ APIs for converting Image data into Out-of-Process compatible formats.
  */
-@protocol GTXArtifactImplementing <NSObject>
+@interface GTXImageRGBAData (GTXOOPAdditions)
 
 /**
- *  @return a new snapshot object with data captured at the time of invocation. This method is only
- *          invoked on the main thread.
- */
-+ (instancetype)createArtifactSnapshot;
+@return a a shallow copy of this instrance as std::unique_ptr to gtx::Image. @note that
+gtx::Image valid only until this instance is in scope.
+*/
+- (std::unique_ptr<gtx::Image>)gtxImage NS_RETURNS_INNER_POINTER;
 
 @end
 
diff --git a/Classes/GTXImageRGBAData+GTXOOPAdditions.mm b/Classes/GTXImageRGBAData+GTXOOPAdditions.mm
new file mode 100644
index 0000000..cf3b39f
--- /dev/null
+++ b/Classes/GTXImageRGBAData+GTXOOPAdditions.mm
@@ -0,0 +1,35 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXImageRGBAData+GTXOOPAdditions.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@implementation GTXImageRGBAData (GTXOOPAdditions)
+
+- (std::unique_ptr<gtx::Image>)gtxImage {
+  NSAssert(self.bytesPerPixel == 4, @"gtx::Image assumes 4 bytes per pixel, actual %d",
+           static_cast<int>(self.bytesPerPixel));
+  std::unique_ptr<gtx::Image> gtxImage = std::make_unique<gtx::Image>();
+  gtxImage->pixels = (gtx::Pixel *)self.rgba;
+  gtxImage->width = static_cast<int>(self.width);
+  gtxImage->height = static_cast<int>(self.height);
+  return gtxImage;
+}
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXImageRGBAData.h b/Classes/GTXImageRGBAData.h
index 7e8c193..e2fba3d 100644
--- a/Classes/GTXImageRGBAData.h
+++ b/Classes/GTXImageRGBAData.h
@@ -29,7 +29,7 @@
 /**
  *  Pointer to rgba data (in that order) of the provided image in row major order.
  */
-@property(nonatomic, readonly) unsigned char *rgba;
+@property(nonatomic, readonly) unsigned char *rgba NS_RETURNS_INNER_POINTER;
 
 /**
  *  Width of the image as available in the rgba data.
diff --git a/Classes/GTXImageRGBAData.m b/Classes/GTXImageRGBAData.m
index c7f65b3..e6a0585 100644
--- a/Classes/GTXImageRGBAData.m
+++ b/Classes/GTXImageRGBAData.m
@@ -24,19 +24,21 @@
     _rgba = [GTXImageRGBAData RGBADataFromImage:image
                                        outWidth:&_width
                                       outheight:&_height
-                               outbytesPerPixel:&_bytesPerPixel
                                  outbytesPerRow:&_bytesPerRow];
   }
   return self;
 }
 
+- (NSUInteger)bytesPerPixel {
+  return 4;
+}
+
 /**
  *  Provides RGBA pixel data for the given UIImage.
  *
  *  @param image The image whose RGBA data is to be extracted.
  *  @param[out] outWidth Populated with the image width, if provided.
  *  @param[out] outHeight Populated with the image height, if provided.
- *  @param[out] outBytesPerPixel Populated with the byte count per pixel, if provided.
  *  @param[out] outBytesPerRow Populated with the byte count per row, if provided.
  *
  *  @return pointer to RGBA data for the given image.
@@ -44,7 +46,6 @@
 + (unsigned char *)RGBADataFromImage:(UIImage *)image
                             outWidth:(NSUInteger *)outWidth
                            outheight:(NSUInteger *)outHeight
-                    outbytesPerPixel:(NSUInteger *)outBytesPerPixel
                       outbytesPerRow:(NSUInteger *)outBytesPerRow {
   // Extract the image dimentions.
   CGImageRef imageRef = [image CGImage];
@@ -74,9 +75,6 @@
   if (outHeight) {
     *outHeight = height;
   }
-  if (outBytesPerPixel) {
-    *outBytesPerPixel = bytesPerPixel;
-  }
   if (outBytesPerRow) {
     *outBytesPerRow = bytesPerRow;
   }
diff --git a/Classes/GTXPluginXCTestCase.m b/Classes/GTXPluginXCTestCase.m
index 4f52fd8..90ab919 100644
--- a/Classes/GTXPluginXCTestCase.m
+++ b/Classes/GTXPluginXCTestCase.m
@@ -17,8 +17,9 @@
 #import "GTXPluginXCTestCase.h"
 
 #import "GTXAssertions.h"
-#import "GTXiLibCore.h"
+#import "GTXSwizzler.h"
 #import "GTXTestEnvironment.h"
+#import "GTXiLibCore.h"
 
 #import <objc/runtime.h>
 
@@ -26,7 +27,7 @@
  Reference to XCTestCase class which will be dynamically set when needed, this allows for tests as
  well as apps (which dont link to XCTest) use GTX.
  */
-Class gXCTestCaseClass;
+static Class gXCTestCaseClass;
 
 @implementation GTXPluginXCTestCase
 
@@ -36,15 +37,13 @@
     gXCTestCaseClass = NSClassFromString(@"XCTestCase");
     NSAssert(gXCTestCaseClass, @"XCTestCase class was not found, either XCTest framework is not "
                                @"being linked or not loaded yet.");
-    [self gtx_addInstanceMethod:@selector(gtx_tearDown)
-                      fromClass:self
-                        toClass:gXCTestCaseClass];
-    [self gtx_addInstanceMethod:@selector(gtx_invokeTest)
-                      fromClass:self
-                        toClass:gXCTestCaseClass];
-    [self gtx_swizzleInstanceMethod:@selector(invokeTest)
-                         withMethod:@selector(gtx_invokeTest)
-                            inClass:gXCTestCaseClass];
+    [GTXSwizzler addInstanceMethod:@selector(gtx_tearDown) fromClass:self toClass:gXCTestCaseClass];
+    [GTXSwizzler addInstanceMethod:@selector(gtx_invokeTest)
+                         fromClass:self
+                           toClass:gXCTestCaseClass];
+    [GTXSwizzler swizzleInstanceMethod:@selector(invokeTest)
+                            withMethod:@selector(gtx_invokeTest)
+                               inClass:gXCTestCaseClass];
     [GTXTestEnvironment setupEnvironment];
   });
 }
@@ -64,56 +63,6 @@
 #pragma mark - Private
 
 /**
- Adds the given method from the given source to the given destination class.
-
- @param methodSelector selector of the method to be added.
- @param srcClass Source class from where to get the method implementation
- @param destClass destination class where the method implementation is to be added.
- */
-+ (void)gtx_addInstanceMethod:(SEL)methodSelector
-                    fromClass:(Class)srcClass
-                      toClass:(Class)destClass {
-  Method instanceMethod = class_getInstanceMethod(srcClass, methodSelector);
-  const char *typeEncoding = method_getTypeEncoding(instanceMethod);
-  NSAssert(typeEncoding, @"Failed to get method type encoding.");
-
-  BOOL success = class_addMethod(destClass,
-                                 methodSelector,
-                                 method_getImplementation(instanceMethod),
-                                 typeEncoding);
-  NSAssert(success, @"Failed to add %@ from %@ to %@",
-                    NSStringFromSelector(methodSelector), srcClass, destClass);
-  (void)success; // Ensures 'success' is marked as used even if NSAssert is removed.
-}
-
-/**
- Swizzles the given methods in the given class.
-
- @param methodSelector1 Selector for the original method.
- @param methodSelector2 Selector for the method to be swizzled with.
- @param clazz Target class to be swizzled in.
- */
-+ (void)gtx_swizzleInstanceMethod:(SEL)methodSelector1
-                       withMethod:(SEL)methodSelector2
-                          inClass:(Class)clazz {
-  Method method1 = class_getInstanceMethod(clazz, methodSelector1);
-  Method method2 = class_getInstanceMethod(clazz, methodSelector2);
-  // Only swizzle if both methods are found
-  if (method1 && method2) {
-    IMP imp1 = method_getImplementation(method1);
-    IMP imp2 = method_getImplementation(method2);
-
-    if (class_addMethod(clazz, methodSelector1, imp2, method_getTypeEncoding(method2))) {
-      class_replaceMethod(clazz, methodSelector2, imp1, method_getTypeEncoding(method1));
-    } else {
-      method_exchangeImplementations(method1, method2);
-    }
-  } else {
-    GTX_ASSERT(NO, @"Cannot swizzle %@", NSStringFromSelector(methodSelector1));
-  }
-}
-
-/**
  @return Closest superclass to @c clazz that has -tearDown method.
  */
 + (Class)gtx_classWithInstanceTearDown:(Class)clazz {
@@ -139,9 +88,9 @@
     IMP gtxTearDownIMP = [baseClass instanceMethodForSelector:@selector(gtx_tearDown)];
     class_addMethod(clazz, @selector(gtx_tearDown), gtxTearDownIMP, desc->types);
   }
-  [self gtx_swizzleInstanceMethod:@selector(tearDown)
-                       withMethod:@selector(gtx_tearDown)
-                          inClass:clazz];
+  [GTXSwizzler swizzleInstanceMethod:@selector(tearDown)
+                          withMethod:@selector(gtx_tearDown)
+                             inClass:clazz];
 }
 
 /**
@@ -149,9 +98,9 @@
  */
 + (void)gtx_unWireTeardownInClass:(Class)clazz {
   // Swizzle again to restore tearDown/gtx_tearDown to their original IMPs.
-  [self gtx_swizzleInstanceMethod:@selector(tearDown)
-                       withMethod:@selector(gtx_tearDown)
-                          inClass:clazz];
+  [GTXSwizzler swizzleInstanceMethod:@selector(tearDown)
+                          withMethod:@selector(gtx_tearDown)
+                             inClass:clazz];
 }
 
 #pragma mark - Swizzled methods
diff --git a/Classes/GTXSnapshotBuffer.h b/Classes/GTXSnapshotBuffer.h
deleted file mode 100644
index d72da89..0000000
--- a/Classes/GTXSnapshotBuffer.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//
-// Copyright 2019 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-
-#import "GTXSnapshotContainer.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-/**
- *  @c GTXSnapshotBuffer instances are thread safe FIFO buffers for @c GTXSnapshotContainer objects.
- */
-@interface GTXSnapshotBuffer : NSObject
-
-/**
- *  Puts the given @c newSnapshots object into the buffer.
- */
-- (void)putSnapshotsContainer:(GTXSnapshotContainer *)newSnapshots;
-
-/**
- *  Gets the next snapshot container object from the buffer or @c nil if the buffer is empty.
- */
-- (nullable GTXSnapshotContainer *)getNextSnapshotsContainer;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXSnapshotBuffer.m b/Classes/GTXSnapshotBuffer.m
deleted file mode 100644
index f01ac66..0000000
--- a/Classes/GTXSnapshotBuffer.m
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// Copyright 2019 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "GTXSnapshotBuffer.h"
-
-@implementation GTXSnapshotBuffer {
-  NSMutableArray *snapshotsBuffer;
-}
-
-- (instancetype)init {
-  self = [super init];
-  if (self) {
-    snapshotsBuffer = [[NSMutableArray alloc] init];
-  }
-  return self;
-}
-
-- (void)putSnapshotsContainer:(GTXSnapshotContainer *)newSnapshot {
-  NSParameterAssert(newSnapshot);
-  @synchronized (self) {
-    [snapshotsBuffer addObject:newSnapshot];
-  }
-}
-
-- (GTXSnapshotContainer *)getNextSnapshotsContainer {
-  GTXSnapshotContainer *snapshot;
-  @synchronized (self) {
-    if (snapshotsBuffer.count) {
-      snapshot = [snapshotsBuffer firstObject];
-      [snapshotsBuffer removeObjectAtIndex:0];
-    }
-  }
-  return snapshot;
-}
-
-@end
diff --git a/Classes/GTXSnapshotContainer.h b/Classes/GTXSnapshotContainer.h
deleted file mode 100644
index 9332523..0000000
--- a/Classes/GTXSnapshotContainer.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright 2019 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import <Foundation/Foundation.h>
-
-#import "GTXArtifactImplementing.h"
-
-/**
- *  @c GTXSnapshotContainer is container for all the snapshots for ease of processing.
- */
-@interface GTXSnapshotContainer : NSObject
-
-/**
- *  Use initWithSnapshots: instead.
- */
-- (instancetype)init NS_UNAVAILABLE;
-
-/**
- *  Initialize a new container object with the given snapshots.
- *
- *  @param uniqueSnapshots Array of all unique snapshots to be part of this container.
- */
-- (instancetype)initWithSnapshots:(NSArray<id<GTXArtifactImplementing>> *)uniqueSnapshots;
-
-/**
- *  @return snapshot object of the given class @c cls that is in this container.
- */
-- (id<GTXArtifactImplementing>)snapshotFromArtifactClass:(Class<GTXArtifactImplementing>)cls;
-
-@end
diff --git a/Classes/GTXSnapshotContainer.m b/Classes/GTXSnapshotContainer.m
deleted file mode 100644
index 16b7334..0000000
--- a/Classes/GTXSnapshotContainer.m
+++ /dev/null
@@ -1,47 +0,0 @@
-//
-// Copyright 2019 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#import "GTXSnapshotContainer.h"
-
-#import "GTXAssertions.h"
-
-@implementation GTXSnapshotContainer {
-  NSDictionary *snapshotFromClass;
-}
-
-- (instancetype)initWithSnapshots:(NSArray<id<GTXArtifactImplementing>> *)uniqueSnapshots {
-  GTX_ASSERT(uniqueSnapshots.count > 0, @"Attempting to create empty container");
-  self = [super init];
-  if (self) {
-    NSMutableDictionary *map = [[NSMutableDictionary alloc] init];
-    for (id<GTXArtifactImplementing> snapshot in uniqueSnapshots) {
-      Class<GTXArtifactImplementing> cls = [snapshot class];
-      GTX_ASSERT(![map.allKeys containsObject:cls],
-                 @"Duplicate snapshots for %@ class in %@", cls, uniqueSnapshots);
-      map[(id<NSCopying>)cls] = snapshot;
-    }
-    snapshotFromClass = map;
-  }
-  return self;
-}
-
-- (id<GTXArtifactImplementing>)snapshotFromArtifactClass:(Class<GTXArtifactImplementing>)cls {
-  id<GTXArtifactImplementing> snapshot = snapshotFromClass[cls];
-  GTX_ASSERT(snapshot, @"Snapshot was not present for %@", cls);
-  return snapshot;
-}
-
-@end
diff --git a/Classes/GTXSwizzler.h b/Classes/GTXSwizzler.h
new file mode 100644
index 0000000..46f6b16
--- /dev/null
+++ b/Classes/GTXSwizzler.h
@@ -0,0 +1,44 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <Foundation/Foundation.h>
+
+/**
+ Class for performing Objective-C swizzle operations.
+ */
+@interface GTXSwizzler : NSObject
+
+/**
+ Adds the given method from the given source to the given destination class.
+
+ @param methodSelector selector of the method to be added.
+ @param srcClass Source class from where to get the method implementation
+ @param destClass destination class where the method implementation is to be added.
+ */
++ (void)addInstanceMethod:(SEL)methodSelector fromClass:(Class)srcClass toClass:(Class)destClass;
+
+/**
+ Swizzles the given methods in the given class.
+
+ @param methodSelector1 Selector for the original method.
+ @param methodSelector2 Selector for the method to be swizzled with.
+ @param clazz Target class to be swizzled in.
+ */
++ (void)swizzleInstanceMethod:(SEL)methodSelector1
+                   withMethod:(SEL)methodSelector2
+                      inClass:(Class)clazz;
+
+@end
diff --git a/Classes/GTXSwizzler.m b/Classes/GTXSwizzler.m
new file mode 100644
index 0000000..d755397
--- /dev/null
+++ b/Classes/GTXSwizzler.m
@@ -0,0 +1,57 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXSwizzler.h"
+
+#import "GTXAssertions.h"
+
+#import <objc/runtime.h>
+
+@implementation GTXSwizzler
+
++ (void)addInstanceMethod:(SEL)methodSelector fromClass:(Class)srcClass toClass:(Class)destClass {
+  Method instanceMethod = class_getInstanceMethod(srcClass, methodSelector);
+  const char *typeEncoding = method_getTypeEncoding(instanceMethod);
+  NSAssert(typeEncoding, @"Failed to get method type encoding.");
+
+  BOOL success = class_addMethod(destClass, methodSelector,
+                                 method_getImplementation(instanceMethod), typeEncoding);
+  NSAssert(success, @"Failed to add %@ from %@ to %@", NSStringFromSelector(methodSelector),
+           srcClass, destClass);
+  (void)success;  // Ensures 'success' is marked as used even if NSAssert is removed.
+}
+
++ (void)swizzleInstanceMethod:(SEL)methodSelector1
+                   withMethod:(SEL)methodSelector2
+                      inClass:(Class)clazz {
+  Method method1 = class_getInstanceMethod(clazz, methodSelector1);
+  Method method2 = class_getInstanceMethod(clazz, methodSelector2);
+  // Only swizzle if both methods are found
+  if (method1 && method2) {
+    IMP imp1 = method_getImplementation(method1);
+    IMP imp2 = method_getImplementation(method2);
+
+    if (class_addMethod(clazz, methodSelector1, imp2, method_getTypeEncoding(method2))) {
+      class_replaceMethod(clazz, methodSelector2, imp1, method_getTypeEncoding(method1));
+    } else {
+      method_exchangeImplementations(method1, method2);
+    }
+  } else {
+    GTX_ASSERT(NO, @"Cannot swizzle %@", NSStringFromSelector(methodSelector1));
+  }
+}
+
+@end
diff --git a/Classes/GTXTestEnvironment.h b/Classes/GTXTestEnvironment.h
index bde20a5..d9a3592 100644
--- a/Classes/GTXTestEnvironment.h
+++ b/Classes/GTXTestEnvironment.h
@@ -19,12 +19,12 @@
 #import "GTXCommon.h"
 
 /**
- *  A class for setting up enviornment (devices, simulators) etc that GTX runs on.
+ *  A class for setting up environment (devices, simulators) etc that GTX runs on.
  */
 @interface GTXTestEnvironment : NSObject
 
 /**
- *  Sets up the enviornment for use by GTX.
+ *  Sets up the environment for use by GTX.
  *
  *  @param[out] errorOrNil A pointer to an NSError object to populate if there is an error, or nil
  *                         if errors are not being handled.
@@ -33,7 +33,7 @@
  */
 + (BOOL)setupEnvironmentWithError:(GTXErrorRefType)errorOrNil;
 /**
- *  Sets up the enviornment for use by GTX. If the environment cannot be setup, then an exception
+ *  Sets up the environment for use by GTX. If the environment cannot be setup, then an exception
  *  is raised.
  */
 + (void)setupEnvironment;
diff --git a/Classes/GTXToolKit+GTXOOPAdditions.h b/Classes/GTXToolKit+GTXOOPAdditions.h
new file mode 100644
index 0000000..64e2382
--- /dev/null
+++ b/Classes/GTXToolKit+GTXOOPAdditions.h
@@ -0,0 +1,40 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "GTXToolKit.h"
+#include "check.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ APIs for using GTX from out of the iOS App process.
+ TODO: Merge this with GTXToolKit.h eventually.
+ */
+@interface GTXToolKit (GTXOOPAdditions)
+
+/**
+Registers the given "out-of-process" check to be executed on all elements this instance is used on.
+Note that if a check with the same name is already registered assertion will be thrown.
+
+@param check The OOP check to be registered.
+*/
+- (void)registerOOPCheck:(std::unique_ptr<gtx::Check> &)check;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/Classes/GTXToolKit.h b/Classes/GTXToolKit.h
index f486d54..2ae7309 100644
--- a/Classes/GTXToolKit.h
+++ b/Classes/GTXToolKit.h
@@ -16,10 +16,10 @@
 
 #import <UIKit/UIKit.h>
 
-#import "GTXBlacklistBlock.h"
-#import "GTXBlacklisting.h"
 #import "GTXCheckBlock.h"
 #import "GTXChecking.h"
+#import "GTXExcludeListBlock.h"
+#import "GTXExcludeListing.h"
 #import "GTXResult.h"
 
 NS_ASSUME_NONNULL_BEGIN
@@ -51,15 +51,33 @@
 + (instancetype)toolkitWithAllDefaultChecks;
 
 /**
- Creates a check.
+ Creates an accessibility check, note that this check can only be executed on elements that have a
+ window (or are UIAccessibilityElements).
 
  @param name Name of the check.
  @param block Block that performs the check, returns NO on failure.
+
  @return A newly created check.
  */
 + (id<GTXChecking>)checkWithName:(NSString *)name block:(GTXCheckHandlerBlock)block;
 
 /**
+ Creates an element check. @note that this check will be executed on any element even if it is not
+ in the view hierarchy and/or does not have a window if @c requiresWindow is @c NO.
+
+ @param name           Name of the check.
+ @param requiresWindow A boolean that indicates if element must have a window before running the
+ check. For example to create checks that can be executed in unit testing environment set this value
+ to NO.
+ @param block          Block that performs the check, returns NO on failure.
+
+ @return A newly created check.
+ */
++ (id<GTXChecking>)checkWithName:(NSString *)name
+                  requiresWindow:(BOOL)requiresWindow
+                           block:(GTXCheckHandlerBlock)block;
+
+/**
  Registers the given check to be executed on all elements this instance is used on.
 
  @param check The check to be registered.
@@ -67,15 +85,15 @@
 - (void)registerCheck:(id<GTXChecking>)check;
 
 /**
- Registers the given blacklist to be executed on all elements this instance is used on. Registered
- checks are not performed on blacklisted elements.
+ Registers the given excludeList to be executed on all elements this instance is used on. Registered
+ checks are not performed on excluded elements.
 
- @param blacklist The blacklist to be registered.
+ @param excludeList The excludeList to be registered.
  */
-- (void)registerBlacklist:(id<GTXBlacklisting>)blacklist;
+- (void)registerExcludeList:(id<GTXExcludeListing>)excludeList;
 
 /**
- Applies the registered checks on the given element while respecting blacklisted elements.
+ Applies the registered checks on the given element while respecting excluded elements.
 
  @param element element to be checked.
  @param errorOrNil Error object to be filled with error info on check failures.
@@ -87,7 +105,7 @@
  @deprecated Use -resultFromCheckingAllElementsFromRootElements: instead.
 
  Applies the registered checks on all elements in the accessibility tree under the given root
- elements while respecting blacklisted elements.
+ elements while respecting excluded elements.
 
  @param rootElements An array of root elements whose accessibility trees are to be checked.
  @param errorOrNil Error object to be filled with error info on check failures.
@@ -97,7 +115,7 @@
 
 /**
  Applies the registered checks on all elements in the accessibility tree under the given root
- elements while respecting blacklisted elements.
+ elements while respecting excluded elements.
 
  @param rootElements An array of root elements whose accessibility trees are to be checked.
  @return A @c GTXResult object encpsulating the results.
diff --git a/Classes/GTXToolKit.m b/Classes/GTXToolKit.mm
similarity index 68%
rename from Classes/GTXToolKit.m
rename to Classes/GTXToolKit.mm
index 55ad3a8..9dc61ce 100644
--- a/Classes/GTXToolKit.m
+++ b/Classes/GTXToolKit.mm
@@ -18,11 +18,18 @@
 
 #import "GTXAccessibilityTree.h"
 #import "GTXAnalytics.h"
-#import "GTXBlacklistBlock.h"
-#import "GTXBlacklistFactory.h"
 #import "GTXChecksCollection.h"
+#import "GTXExcludeListBlock.h"
+#import "GTXExcludeListFactory.h"
 #import "GTXLogging.h"
 #import "NSError+GTXAdditions.h"
+#import "NSObject+GTXAdditions.h"
+#import "NSString+GTXAdditions.h"
+#include "check.h"
+#include "error_message.h"
+#include "localized_strings_manager.h"
+#include "toolkit.h"
+#include "ui_element.h"
 
 #pragma mark - Extension
 
@@ -36,7 +43,10 @@
 
 @implementation GTXToolKit {
   NSMutableArray<id<GTXChecking>> *_checks;
-  NSMutableArray<id<GTXBlacklisting>> *_blacklists;
+  NSMutableArray<id<GTXExcludeListing>> *_excludeLists;
+  std::unique_ptr<gtx::LocalizedStringsManager> _stringManager;
+  std::unique_ptr<gtx::Toolkit> _outOfProcessToolkit;
+  gtx::Parameters _parameters;
 }
 
 + (instancetype)defaultToolkit {
@@ -52,7 +62,7 @@
 
 + (instancetype)toolkitWithAllDefaultChecks {
   GTXToolKit *toolkit = [[GTXToolKit alloc] initDefault];
-  for (id<GTXChecking> check in GTXChecksCollection.allGTXChecks) {
+  for (id<GTXChecking> check in [GTXChecksCollection allGTXChecksForVersion:GTXVersionLatest]) {
     [toolkit registerCheck:check];
   }
   return toolkit;
@@ -62,7 +72,9 @@
   self = [super init];
   if (self) {
     _checks = [[NSMutableArray alloc] init];
-    _blacklists = [[NSMutableArray alloc] init];
+    _excludeLists = [[NSMutableArray alloc] init];
+    _stringManager = std::make_unique<gtx::LocalizedStringsManager>();
+    _outOfProcessToolkit = std::make_unique<gtx::Toolkit>();
   }
   return self;
 }
@@ -71,6 +83,12 @@
   return [GTXCheckBlock GTXCheckWithName:name block:block];
 }
 
++ (id<GTXChecking>)checkWithName:(NSString *)name
+                  requiresWindow:(BOOL)requiresWindow
+                           block:(GTXCheckHandlerBlock)block {
+  return [GTXCheckBlock GTXCheckWithName:name requiresWindow:requiresWindow block:block];
+}
+
 - (void)registerCheck:(id<GTXChecking>)check {
   // Verify the newly added check is unique.
   for (id<GTXChecking> existingCheck in _checks) {
@@ -81,8 +99,24 @@
   [_checks addObject:check];
 }
 
-- (void)registerBlacklist:(id<GTXBlacklisting>)blacklist {
-  [_blacklists addObject:blacklist];
+- (void)registerOOPCheck:(std::unique_ptr<gtx::Check> &)check {
+  NSString *name = [NSString gtx_stringFromSTDString:check->name()];
+  _outOfProcessToolkit->RegisterCheck(check);
+  __weak typeof(self) weakSelf = self;
+  id<GTXChecking> wrappedCheck = [GTXToolKit
+      checkWithName:name
+              block:^BOOL(id _Nonnull element, GTXErrorRefType errorOrNil) {
+                return [weakSelf
+                    gtx_invokeRegisteredOOPCheckNamed:std::string([name
+                                                       cStringUsingEncoding:NSASCIIStringEncoding])
+                                            onElement:element
+                                                error:errorOrNil];
+              }];
+  [self registerCheck:wrappedCheck];
+}
+
+- (void)registerExcludeList:(id<GTXExcludeListing>)excludeList {
+  [_excludeLists addObject:excludeList];
 }
 
 - (BOOL)checkElement:(id)element error:(GTXErrorRefType)errorOrNil {
@@ -146,7 +180,33 @@
 #pragma mark - Private
 
 /**
- Applies the registered checks on the given element while respecting blacklisted elements.
+Invokes the check registered on the given name.
+
+@param name       Name of the check to be invoked.
+@param element    element to be checked.
+@param errorOrNil Error object to be filled with error info on check failures.
+@return @c YES if all check passed @c NO otherwise.
+*/
+- (BOOL)gtx_invokeRegisteredOOPCheckNamed:(const std::string &)name
+                                onElement:(id)element
+                                    error:(GTXErrorRefType)errorOrNil {
+  std::unique_ptr<gtx::UIElement> elementInfo = [element gtx_UIElement];
+  gtx::ErrorMessage checkError;
+  const gtx::Check &check = _outOfProcessToolkit->GetRegisteredCheckNamed(name);
+  BOOL success = (BOOL)check.CheckElement(*elementInfo, _parameters, &checkError);
+  if (!success) {
+    NSString *errorDescription = [NSString
+        gtx_stringFromSTDString:_stringManager->LocalizedString(checkError.description_id())];
+    [NSError gtx_logOrSetGTXCheckFailedError:errorOrNil
+                                     element:element
+                                        name:[NSString gtx_stringFromSTDString:name]
+                                 description:errorDescription];
+  }
+  return success;
+}
+
+/**
+ Applies the registered checks on the given element while respecting excluded elements.
 
  @param element element to be checked.
  @param checkAnalyticsEnabled Boolean that indicates if analytics events are to be invoked.
@@ -168,17 +228,12 @@
     // Currently all checks are only applicable to accessibility elements.
     return YES;
   }
-  if ([element respondsToSelector:@selector(window)] && [element window] == nil) {
-    // Elements without a window are not actually part of the view hierarchy and should not be
-    // checked.
-    return YES;
-  }
 
   NSMutableArray *failedCheckErrors;
   for (id<GTXChecking> checker in _checks) {
     BOOL shouldSkipThisCheck = NO;
-    for (id<GTXBlacklisting> blacklist in _blacklists) {
-      if ([blacklist shouldIgnoreElement:element forCheckNamed:[checker name]]) {
+    for (id<GTXExcludeListing> excludeList in _excludeLists) {
+      if ([excludeList shouldIgnoreElement:element forCheckNamed:[checker name]]) {
         shouldSkipThisCheck = YES;
         break;
       }
@@ -188,6 +243,13 @@
     }
 
     NSError *error = nil;
+    if ([checker respondsToSelector:@selector(requiresWindowBeforeChecking)] &&
+        [checker requiresWindowBeforeChecking] &&
+        [element respondsToSelector:@selector(window)] && [element window] == nil) {
+      // Elements without a window are not actually part of the view hierarchy and should not be
+      // checked if [checker requiresWindowBeforeChecking] is @c YES.
+      continue;
+    }
     if (![checker check:element error:&error]) {
       if (!error) {
         // Check failed but an error description was not provided, generate a generic description.
@@ -248,10 +310,10 @@
 - (NSString *)gtx_errorDescriptionForElement:(id)element gtxCheckErrors:(NSArray *)errors {
   NSMutableString *localizedDescription =
       [NSMutableString stringWithFormat:@"%d accessibility error(s) were found in %@:\n",
-                                        (int)[errors count], element];
+                                        static_cast<int>([errors count]), element];
   for (NSUInteger index = 0; index < [errors count]; index++) {
     [localizedDescription
-        appendString:[NSString stringWithFormat:@"%d. %@\n", (int)(index + 1),
+        appendString:[NSString stringWithFormat:@"%d. %@\n", static_cast<int>(index + 1),
                                                 [errors[index] localizedDescription]]];
   }
   return localizedDescription;
diff --git a/Classes/GTXXCUIApplicationProxy.h b/Classes/GTXXCUIApplicationProxy.h
new file mode 100644
index 0000000..b53d461
--- /dev/null
+++ b/Classes/GTXXCUIApplicationProxy.h
@@ -0,0 +1,40 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "GTXXCUIElementQueryProxy.h"
+
+/**
+ A proxy class for XCUIApplication class. This is needed since XCTest framework that contains
+ XCUIApplication class is only linked when tests are run.
+ */
+@interface GTXXCUIApplicationProxy : NSObject
+
+/**
+ @return Last known instance of XCUIApplication object created by the tests, generally this is the
+ app being tested.
+ */
++ (GTXXCUIApplicationProxy *)lastKnownApplicationProxy;
+
+/**
+ @return Array of all onscreen accessibility elements (of the app referenced by the last known
+ XCUIApplication instance). NOTE: we need gtx_ prefix here to avoid name collision with actual
+ XCUIApplication methods.
+ */
+- (NSArray<UIAccessibilityElement *> *)gtx_onScreenAccessibilityElements;
+
+@end
diff --git a/Classes/GTXXCUIApplicationProxy.m b/Classes/GTXXCUIApplicationProxy.m
new file mode 100644
index 0000000..2a7a1cb
--- /dev/null
+++ b/Classes/GTXXCUIApplicationProxy.m
@@ -0,0 +1,90 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXXCUIApplicationProxy.h"
+
+#import "GTXAssertions.h"
+#import "GTXSwizzler.h"
+#import "GTXXCUIElementProxy.h"
+
+/**
+ Reference to XCUIApplication class which will be dynamically set when needed, this allows for tests
+ as well as apps (which dont link to XCTest) use GTX.
+ */
+static Class gXCUIApplicationClass;
+
+/**
+ Reference to last known XCUIApplication instance.
+ */
+static __weak GTXXCUIApplicationProxy *gLastKnownApplication;
+
+/**
+ Category to expose the methods on XCUIApplication that this class uses.
+ */
+@interface GTXXCUIApplicationProxy (XCUIApplication)
+
+/**
+ @return Query object that fetches all the child elements of this application.
+ */
+- (GTXXCUIElementQueryProxy *)childrenMatchingType:(NSInteger)unused;
+
+@end
+
+@implementation GTXXCUIApplicationProxy
+
++ (void)load {
+  gXCUIApplicationClass = NSClassFromString(@"XCUIApplication");
+  if (gXCUIApplicationClass) {
+    [GTXSwizzler addInstanceMethod:@selector(initGTXXCUIApplication)
+                         fromClass:self
+                           toClass:gXCUIApplicationClass];
+    [GTXSwizzler swizzleInstanceMethod:@selector(init)
+                            withMethod:@selector(initGTXXCUIApplication)
+                               inClass:gXCUIApplicationClass];
+    [GTXSwizzler addInstanceMethod:@selector(gtx_onScreenAccessibilityElements)
+                         fromClass:self
+                           toClass:gXCUIApplicationClass];
+  }
+}
+
++ (GTXXCUIApplicationProxy *)lastKnownApplicationProxy {
+  return gLastKnownApplication;
+}
+
+- (id)initGTXXCUIApplication {
+  NSAssert(gXCUIApplicationClass,
+           @"XCUIApplication class was not found, either XCTest framework is "
+           @"not being linked or not loaded yet.");
+  self = [self initGTXXCUIApplication];
+  gLastKnownApplication = self;
+  NSAssert([gLastKnownApplication isKindOfClass:gXCUIApplicationClass], @"%@ was not of class %@",
+           gLastKnownApplication, gXCUIApplicationClass);
+  // TODO: Invoking this in +load is failing since Objective-C runtime is not loading
+  // XCUIElement class by that time, fix that issue andd move this code into +load.
+  [GTXXCUIElementProxy installPlugin];
+  return self;
+}
+
+- (NSArray<UIAccessibilityElement *> *)gtx_onScreenAccessibilityElements {
+  NSArray<GTXXCUIElementProxy *> *proxies = [[self childrenMatchingType:0] allElementsBoundByIndex];
+  NSMutableArray<UIAccessibilityElement *> *elements = [[NSMutableArray alloc] init];
+  for (GTXXCUIElementProxy *proxy in proxies) {
+    [elements addObject:[proxy gtx_accessibilityElementWithContainer:self]];
+  }
+  return elements;
+}
+
+@end
diff --git a/Classes/GTXXCUIElementProxy.h b/Classes/GTXXCUIElementProxy.h
new file mode 100644
index 0000000..0b879c0
--- /dev/null
+++ b/Classes/GTXXCUIElementProxy.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+/**
+ A proxy class for XCUIElement class. This is needed since XCTest framework that contains
+ XCUIElement class is only linked when tests are run.
+ */
+@interface GTXXCUIElementProxy : NSObject
+
+/**
+ Installs GTXXCUIElementProxy plugin by swizzling some XCUIElement methods.
+ */
++ (void)installPlugin;
+
+/**
+ @return UIAccessibilityElement representation of this element. NOTE: we need gtx_ prefix here to
+ avoid name collision with actual XCUIElement methods.
+ */
+- (UIAccessibilityElement *)gtx_accessibilityElementWithContainer:(id)container;
+
+@end
diff --git a/Classes/GTXXCUIElementProxy.m b/Classes/GTXXCUIElementProxy.m
new file mode 100644
index 0000000..ec2f866
--- /dev/null
+++ b/Classes/GTXXCUIElementProxy.m
@@ -0,0 +1,98 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXXCUIElementProxy.h"
+
+#import "GTXSwizzler.h"
+#import "GTXXCUIElementQueryProxy.h"
+
+/**
+ Proxy for XCUIElementType enum, since XCUIElementType is only available in XCTest framework.
+ */
+// TODO: Figure out a better way to keep these values in sync with XCUIElementType enum.
+typedef NS_ENUM(NSUInteger, XCUIProxyElementType) {
+  XCUIProxyElementTypeButton = 9,
+  XCUIProxyElementTypeStaticText = 48,
+};
+
+/**
+ Category to expose the methods on XCUIElement that this class uses.
+ */
+@interface GTXXCUIElementProxy (XCUIElement)
+
+- (CGRect)frame;
+- (NSString *)label;
+- (NSString *)identifier;
+- (GTXXCUIElementQueryProxy *)childrenMatchingType:(NSInteger)unused;
+- (XCUIProxyElementType)elementType;
+
+@end
+
+#pragma mark - Implementation
+
+@implementation GTXXCUIElementProxy
+
++ (void)installPlugin {
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    Class XCUIElementClass = NSClassFromString(@"XCUIElement");
+    if (XCUIElementClass) {
+      [GTXSwizzler addInstanceMethod:@selector(gtx_accessibilityElementWithContainer:)
+                           fromClass:self
+                             toClass:XCUIElementClass];
+      [GTXSwizzler addInstanceMethod:@selector(gtx_accessibilityTraits)
+                           fromClass:self
+                             toClass:XCUIElementClass];
+    }
+  });
+}
+
+// TODO: Update this code to accurately capture the hierarchy, sometimes we seem to be
+// getting duplicate entries.
+- (UIAccessibilityElement *)gtx_accessibilityElementWithContainer:(id)container {
+  UIAccessibilityElement *element =
+      [[UIAccessibilityElement alloc] initWithAccessibilityContainer:container];
+  element.accessibilityLabel = [self label];
+  element.accessibilityFrame = [self frame];
+  element.accessibilityIdentifier = [self identifier];
+  element.accessibilityTraits = [self gtx_accessibilityTraits];
+  NSMutableArray<UIAccessibilityElement *> *children;
+  NSArray<GTXXCUIElementProxy *> *decendents =
+      [[self childrenMatchingType:0] allElementsBoundByIndex];
+  for (GTXXCUIElementProxy *element in decendents) {
+    if (!children) {
+      children = [[NSMutableArray alloc] init];
+    }
+    UIAccessibilityElement *child = [element gtx_accessibilityElementWithContainer:element];
+    [children addObject:child];
+  }
+  element.accessibilityElements = children;
+  element.isAccessibilityElement = children.count ? NO : YES;
+  return element;
+}
+
+- (UIAccessibilityTraits)gtx_accessibilityTraits {
+  UIAccessibilityTraits traits = 0;
+  if (self.elementType == XCUIProxyElementTypeStaticText) {
+    traits |= UIAccessibilityTraitStaticText;
+  }
+  if (self.elementType == XCUIProxyElementTypeButton) {
+    traits |= UIAccessibilityTraitButton;
+  }
+  return traits;
+}
+
+@end
diff --git a/Classes/GTXXCUIElementQueryProxy.h b/Classes/GTXXCUIElementQueryProxy.h
new file mode 100644
index 0000000..788bead
--- /dev/null
+++ b/Classes/GTXXCUIElementQueryProxy.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+@class GTXXCUIElementProxy;
+
+/**
+ A proxy class for XCUIElementQuery class. This is needed since XCTest framework that contains
+ XCUIElementQuery class is only linked when tests are run.
+ */
+@interface GTXXCUIElementQueryProxy : NSObject
+@end
+
+/**
+ Category to expose the methods on XCUIElementQuery that this class uses.
+ */
+@interface GTXXCUIElementQueryProxy (XCUIElementQuery)
+
+/**
+ @return Array of GTXXCUIElementProxy instances of all elements matched by this query. Proxy for
+ XCUIElementQuery's -allElementsBoundByIndex method.
+ */
+- (NSArray<GTXXCUIElementProxy *> *)allElementsBoundByIndex;
+
+@end
diff --git a/Tests/UnitTests/GTXBaseTestCase.h b/Classes/GTXXCUIElementQueryProxy.m
similarity index 62%
copy from Tests/UnitTests/GTXBaseTestCase.h
copy to Classes/GTXXCUIElementQueryProxy.m
index 0b4feb3..c33f0d6 100644
--- a/Tests/UnitTests/GTXBaseTestCase.h
+++ b/Classes/GTXXCUIElementQueryProxy.m
@@ -1,5 +1,5 @@
 //
-// Copyright 2018 Google Inc.
+// Copyright 2020 Google Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,17 +14,10 @@
 // limitations under the License.
 //
 
-#import <UIKit/UIKit.h>
-#import <XCTest/XCTest.h>
+#import "GTXXCUIElementQueryProxy.h"
 
-#import "GTXCheckBlock.h"
+#import "GTXAssertions.h"
+#import "GTXXCUIElementProxy.h"
 
-extern GTXCheckHandlerBlock noOpCheckBlock;
-
-@interface GTXBaseTestCase : XCTestCase
-
-- (NSObject *)newAccessibleElement;
-- (NSObject *)newInaccessibleElement;
-- (void)createTreeFromPreOrderTraversal:(NSArray *)preOrderTraversal;
-
+@implementation GTXXCUIElementQueryProxy
 @end
diff --git a/Classes/GTXiLib.h b/Classes/GTXiLib.h
index b6b7743..158f87e 100644
--- a/Classes/GTXiLib.h
+++ b/Classes/GTXiLib.h
@@ -20,7 +20,7 @@
 #import <UIKit/UIKit.h>
 
 //! Project version number for GTXiLib.
-FOUNDATION_EXPORT double GTXiLibVersionNumber;
+FOUNDATION_EXPORT double gGTXiLibVersionNumber;
 
 //! Project version string for GTXiLib.
 FOUNDATION_EXPORT const unsigned char GTXiLibVersionString[];
@@ -29,18 +29,18 @@
 #import <GTXiLib/GTXAnalytics.h>
 #import <GTXiLib/GTXAnalyticsUtils.h>
 #import <GTXiLib/GTXAssertions.h>
-#import <GTXiLib/GTXiLibCore.h>
 #import <GTXiLib/GTXCheckBlock.h>
 #import <GTXiLib/GTXChecksCollection.h>
 #import <GTXiLib/GTXCommon.h>
-#import <GTXiLib/GTXBlacklistFactory.h>
 #import <GTXiLib/GTXErrorReporter.h>
-#import <GTXiLib/GTXImageRGBAData.h>
+#import <GTXiLib/GTXExcludeListFactory.h>
 #import <GTXiLib/GTXImageAndColorUtils.h>
+#import <GTXiLib/GTXImageRGBAData.h>
 #import <GTXiLib/GTXLogging.h>
 #import <GTXiLib/GTXPluginXCTestCase.h>
 #import <GTXiLib/GTXTestEnvironment.h>
-#import <GTXiLib/GTXToolKit.h>
 #import <GTXiLib/GTXTestSuite.h>
+#import <GTXiLib/GTXToolKit.h>
+#import <GTXiLib/GTXiLibCore.h>
 #import <GTXiLib/NSError+GTXAdditions.h>
 #import <GTXiLib/UIColor+GTXAdditions.h>
diff --git a/Classes/GTXiLibCore.h b/Classes/GTXiLibCore.h
index a601a22..d94391b 100644
--- a/Classes/GTXiLibCore.h
+++ b/Classes/GTXiLibCore.h
@@ -14,13 +14,13 @@
 // limitations under the License.
 //
 
-#import "GTXAnalytics.h"
 #import "GTXAccessibilityTree.h"
-#import "GTXBlacklisting.h"
+#import "GTXAnalytics.h"
 #import "GTXCheckBlock.h"
 #import "GTXChecksCollection.h"
 #import "GTXCommon.h"
 #import "GTXErrorReporter.h"
+#import "GTXExcludeListing.h"
 #import "GTXTestSuite.h"
 #import "NSError+GTXAdditions.h"
 
@@ -65,7 +65,7 @@
 typedef void(^GTXiLibFailureHandler)(NSError *error);
 
 /**
- *  Primary class that allows for installing checks, creating checks and blacklists etc.
+ *  Primary class that allows for installing checks, creating checks and excludeLists etc.
  */
 @interface GTXiLib : NSObject
 
@@ -74,11 +74,11 @@
 
  @param suite Suite of all test cases where checks are to be installed.
  @param checks Array of checks to be installed.
- @param blacklists Array of element blacklists to be skipped from checks.
+ @param excludeLists Array of element excludeLists to be skipped from checks.
  */
 + (void)installOnTestSuite:(GTXTestSuite *)suite
                     checks:(NSArray<id<GTXChecking>> *)checks
-         elementBlacklists:(NSArray<id<GTXBlacklisting>> *)blacklists;
+       elementExcludeLists:(NSArray<id<GTXExcludeListing>> *)excludeLists;
 
 /**
  Creates a check with the given name and block.
diff --git a/Classes/GTXiLibCore.m b/Classes/GTXiLibCore.m
index 76eea82..1188de3 100644
--- a/Classes/GTXiLibCore.m
+++ b/Classes/GTXiLibCore.m
@@ -22,10 +22,14 @@
 #import "GTXLogging.h"
 #import "GTXPluginXCTestCase.h"
 #import "GTXToolKit.h"
+#import "GTXXCUIApplicationProxy.h"
 #import "NSError+GTXAdditions.h"
 
 #pragma mark - Global definitions.
 
+double gGTXiLibVersionNumber = 4.0;
+const unsigned char GTXiLibVersionString[] = "4.0";
+
 NSString *const gtxTestCaseDidBeginNotification = @"gtxTestCaseDidBeginNotification";
 NSString *const gtxTestCaseDidEndNotification = @"gtxTestCaseDidEndNotification";
 NSString *const gtxTestClassUserInfoKey = @"gtxTestClassUserInfoKey";
@@ -36,7 +40,7 @@
 @interface GTXInstallOptions : NSObject
 
 @property(nonatomic, strong) NSArray *checks;
-@property(nonatomic, strong) NSArray *elementBlacklist;
+@property(nonatomic, strong) NSArray *elementExcludeList;
 @property(nonatomic, strong) GTXTestSuite *suite;
 
 @end
@@ -80,7 +84,7 @@
 
 + (void)installOnTestSuite:(GTXTestSuite *)suite
                     checks:(NSArray<id<GTXChecking>> *)checks
-         elementBlacklists:(NSArray<id<GTXBlacklisting>> *)blacklists {
+       elementExcludeLists:(NSArray<id<GTXExcludeListing>> *)excludeLists {
   [GTXPluginXCTestCase installPlugin];
   if (!gIntsallOptions) {
     gIntsallOptions = [[NSMutableArray alloc] init];
@@ -88,7 +92,7 @@
 
   GTXInstallOptions *options = [[GTXInstallOptions alloc] init];
   options.checks = checks;
-  options.elementBlacklist = blacklists;
+  options.elementExcludeList = excludeLists;
   options.suite = suite;
 
   // Assert that this suite has no test cases also specified in other install calls.
@@ -145,6 +149,22 @@
 #pragma mark - Private
 
 /**
+ @return Array of root elements on the screen or @c nil if no application/window was found.
+ */
++ (NSArray<NSObject *> *)gtx_onScreenRootElements {
+  if (GTXXCUIApplicationProxy.lastKnownApplicationProxy) {
+    // GTX is running from Out-of-process.
+    return [GTXXCUIApplicationProxy.lastKnownApplicationProxy gtx_onScreenAccessibilityElements];
+  } else {
+    UIWindow *window = UIApplication.sharedApplication.keyWindow;
+    if (window) {
+      return @[ window ];
+    }
+  }
+  return nil;
+}
+
+/**
  Executes the currently installed checks on the given element. In case of failures, the failure
  handler is invoked.
 
@@ -205,8 +225,8 @@
       } else {
         gToolkit = [GTXToolKit defaultToolkit];
       }
-      for (id<GTXBlacklisting> blacklist in gCurrentOptions.elementBlacklist) {
-        [gToolkit registerBlacklist:blacklist];
+      for (id<GTXExcludeListing> excludeList in gCurrentOptions.elementExcludeList) {
+        [gToolkit registerExcludeList:excludeList];
       }
     }
   }
@@ -225,9 +245,9 @@
 
   if (gCurrentOptions) {
     // Run all the checks.
-    UIWindow *window = [UIApplication sharedApplication].keyWindow;
-    if (window) {
-      [self gtx_checkAllElementsFromRootElements:@[ window ]];
+    NSArray<id> *rootElements = [self gtx_onScreenRootElements];
+    if (rootElements) {
+      [self gtx_checkAllElementsFromRootElements:rootElements];
     }
   }
 }
@@ -239,9 +259,10 @@
  */
 + (void)gtx_testInteractionDidBegin:(NSNotification *)notification {
   if (!gIsInInteraction) {
-    [self gtx_checkAllElementsFromRootElements:@[
-      [UIApplication sharedApplication].keyWindow.window
-    ]];
+    NSArray<id> *rootElements = [self gtx_onScreenRootElements];
+    if (rootElements) {
+      [self gtx_checkAllElementsFromRootElements:rootElements];
+    }
   }
   gIsInInteraction = YES;
 }
diff --git a/Classes/GTXArtifactImplementing.h b/Classes/NSObject+GTXAdditions.h
similarity index 61%
rename from Classes/GTXArtifactImplementing.h
rename to Classes/NSObject+GTXAdditions.h
index 24d9344..a4eadc4 100644
--- a/Classes/GTXArtifactImplementing.h
+++ b/Classes/NSObject+GTXAdditions.h
@@ -1,5 +1,5 @@
 //
-// Copyright 2019 Google Inc.
+// Copyright 2020 Google Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -16,19 +16,18 @@
 
 #import <UIKit/UIKit.h>
 
-NS_ASSUME_NONNULL_BEGIN
+#include "ui_element.h"
 
 /**
- *  A protocol that all artifacts must implement to ensure that snapshots can be taken.
+ *  Additions to NSObject to make it easy to create gtx::UIElements from UIViews and
+ *  UIAccessibilityElements.
  */
-@protocol GTXArtifactImplementing <NSObject>
+@interface NSObject (GTXAdditions)
 
 /**
- *  @return a new snapshot object with data captured at the time of invocation. This method is only
- *          invoked on the main thread.
+ *  @returns a unique_ptr to @c gtx::UIElement representing this element (UIView or
+ *  UIAccessibilityElement).
  */
-+ (instancetype)createArtifactSnapshot;
+- (std::unique_ptr<gtx::UIElement>)gtx_UIElement;
 
 @end
-
-NS_ASSUME_NONNULL_END
diff --git a/Classes/NSObject+GTXAdditions.mm b/Classes/NSObject+GTXAdditions.mm
new file mode 100644
index 0000000..a0d4683
--- /dev/null
+++ b/Classes/NSObject+GTXAdditions.mm
@@ -0,0 +1,148 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "NSObject+GTXAdditions.h"
+
+@implementation NSObject (GTXAdditions)
+
+- (std::unique_ptr<gtx::UIElement>)gtx_UIElement {
+  auto ui_element = std::make_unique<gtx::UIElement>();
+  ui_element->set_is_ax_element([self gtx_isAxElement]);
+  ui_element->set_ax_label([self gtx_axLabel]);
+  ui_element->set_ax_frame([self gtx_axFrame]);
+  ui_element->set_ax_traits([self gtx_axTraits]);
+  return ui_element;
+}
+
+/**
+ *  @returns [self isAccessibilityElement] if implemented, @c false otherwise.
+ */
+- (bool)gtx_isAxElement {
+  return ([self respondsToSelector:@selector(isAccessibilityElement)]
+              ? [self isAccessibilityElement]
+              : false);
+}
+
+/**
+ *  @returns [self accessibilityLabel] if implemented, empty std::string otherwise.
+ */
+- (std::string)gtx_axLabel {
+  const char *labelCString =
+      ([self respondsToSelector:@selector(accessibilityLabel)]
+           ? [[self accessibilityLabel] cStringUsingEncoding:NSASCIIStringEncoding]
+           : NULL);
+  if (!labelCString) {
+    return std::string();
+  }
+  return std::string(labelCString);
+}
+
+/**
+ *  @returns [self accessibilityFrame] if implemented, CGRectZero otherwise.
+ */
+- (gtx::RectData)gtx_axFrame {
+  CGRect rect = ([self respondsToSelector:@selector(accessibilityFrame)] ?
+                 [self accessibilityFrame] : CGRectZero);
+  gtx::RectData frame;
+  frame.mutable_size()->set_width(rect.size.width);
+  frame.mutable_size()->set_height(rect.size.height);
+  frame.mutable_origin()->set_x(rect.origin.x);
+  frame.mutable_origin()->set_y(rect.origin.y);
+  return frame;
+}
+
+/**
+ *  @returns @c gtx::ElementTrait for the given trait of type @c UIAccessibilityTraits.
+ */
++ (gtx::ElementTrait)gtx_gtxTraitFromUIAccessibilityTrait:(UIAccessibilityTraits)trait {
+  // Use if-else to check for trait values since UIAccessibilityTrait* are not considered "constant
+  // expressions".
+  if (trait == UIAccessibilityTraitNone) {
+    return gtx::ElementTrait::kNone;
+  } else if (trait == UIAccessibilityTraitButton) {
+    return gtx::ElementTrait::kButton;
+  } else if (trait == UIAccessibilityTraitLink) {
+    return gtx::ElementTrait::kLink;
+  } else if (trait == UIAccessibilityTraitSearchField) {
+    return gtx::ElementTrait::kSearchField;
+  } else if (trait == UIAccessibilityTraitImage) {
+    return gtx::ElementTrait::kImage;
+  } else if (trait == UIAccessibilityTraitSelected) {
+    return gtx::ElementTrait::kSelected;
+  } else if (trait == UIAccessibilityTraitPlaysSound) {
+    return gtx::ElementTrait::kPlaysSound;
+  } else if (trait == UIAccessibilityTraitKeyboardKey) {
+    return gtx::ElementTrait::kKeyboardKey;
+  } else if (trait == UIAccessibilityTraitStaticText) {
+    return gtx::ElementTrait::kStaticText;
+  } else if (trait == UIAccessibilityTraitSummaryElement) {
+    return gtx::ElementTrait::kSummaryElement;
+  } else if (trait == UIAccessibilityTraitNotEnabled) {
+    return gtx::ElementTrait::kNotEnabled;
+  } else if (trait == UIAccessibilityTraitUpdatesFrequently) {
+    return gtx::ElementTrait::kUpdatesFrequently;
+  } else if (trait == UIAccessibilityTraitStartsMediaSession) {
+    return gtx::ElementTrait::kStartsMediaSession;
+  } else if (trait == UIAccessibilityTraitAdjustable) {
+    return gtx::ElementTrait::kAdjustable;
+  } else if (trait == UIAccessibilityTraitAllowsDirectInteraction) {
+    return gtx::ElementTrait::kAllowsDirectInteraction;
+  } else if (trait == UIAccessibilityTraitCausesPageTurn) {
+    return gtx::ElementTrait::kCausesPageTurn;
+  } else if (trait == UIAccessibilityTraitHeader) {
+    return gtx::ElementTrait::kHeader;
+  } else {
+    NSAssert(NO, @"Unhandled trait %ld", (long)trait);
+  }
+  return gtx::ElementTrait::kNone;
+}
+
+/**
+ *  @returns [self accessibilityTraits] (converted to gtx::ElementTrait) if implemented,
+ *  kNone otherwise.
+ */
+- (gtx::ElementTrait)gtx_axTraits {
+  UIAccessibilityTraits traits = ([self respondsToSelector:@selector(accessibilityTraits)] ?
+                                  [self accessibilityTraits] : 0);
+  NSArray<NSNumber *> *allApplicableTraits = @[
+    @(UIAccessibilityTraitButton),
+    @(UIAccessibilityTraitLink),
+    @(UIAccessibilityTraitSearchField),
+    @(UIAccessibilityTraitImage),
+    @(UIAccessibilityTraitSelected),
+    @(UIAccessibilityTraitPlaysSound),
+    @(UIAccessibilityTraitKeyboardKey),
+    @(UIAccessibilityTraitStaticText),
+    @(UIAccessibilityTraitSummaryElement),
+    @(UIAccessibilityTraitNotEnabled),
+    @(UIAccessibilityTraitUpdatesFrequently),
+    @(UIAccessibilityTraitStartsMediaSession),
+    @(UIAccessibilityTraitAdjustable),
+    @(UIAccessibilityTraitAllowsDirectInteraction),
+    @(UIAccessibilityTraitCausesPageTurn),
+    @(UIAccessibilityTraitHeader),
+  ];
+  gtx::ElementTrait gtxTraits = gtx::ElementTrait::kNone;
+  for (NSNumber *trait in allApplicableTraits) {
+    UIAccessibilityTraits uikitTrait = [trait integerValue];
+    if (uikitTrait & traits) {
+      gtxTraits = gtxTraits | [NSObject gtx_gtxTraitFromUIAccessibilityTrait:uikitTrait];
+    }
+  }
+  return gtxTraits;
+}
+
+@end
diff --git a/Classes/NSString+GTXAdditions.h b/Classes/NSString+GTXAdditions.h
new file mode 100644
index 0000000..cd02620
--- /dev/null
+++ b/Classes/NSString+GTXAdditions.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+#include <string>
+
+/**
+ *  Additions to NSObject to make it easy to create gtx::UIElements from UIViews and
+ *  UIAccessibilityElements.
+ */
+@interface NSString (GTXAdditions)
+
+/**
+ *  @returns an NSString object from the given std::string.
+ */
++ (NSString *)gtx_stringFromSTDString:(const std::string &)string;
+
+/**
+ *  @returns a std::string object for the given NSString instance.
+ */
+- (std::string)gtx_stdString;
+
+@end
diff --git a/Classes/NSString+GTXAdditions.mm b/Classes/NSString+GTXAdditions.mm
new file mode 100644
index 0000000..3bfc265
--- /dev/null
+++ b/Classes/NSString+GTXAdditions.mm
@@ -0,0 +1,29 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "NSString+GTXAdditions.h"
+
+@implementation NSString (GTXAdditions)
+
++ (NSString *)gtx_stringFromSTDString:(const std::string &)string {
+  return [NSString stringWithCString:string.c_str() encoding:NSString.defaultCStringEncoding];
+}
+
+- (std::string)gtx_stdString {
+  return std::string([self cStringUsingEncoding:NSASCIIStringEncoding]);
+}
+
+@end
diff --git a/Tests/UnitTests/GTXBaseTestCase.h b/Classes/UIColor+GTXOOPAdditions.h
similarity index 65%
copy from Tests/UnitTests/GTXBaseTestCase.h
copy to Classes/UIColor+GTXOOPAdditions.h
index 0b4feb3..195d664 100644
--- a/Tests/UnitTests/GTXBaseTestCase.h
+++ b/Classes/UIColor+GTXOOPAdditions.h
@@ -1,5 +1,5 @@
 //
-// Copyright 2018 Google Inc.
+// Copyright 2020 Google Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,16 +15,14 @@
 //
 
 #import <UIKit/UIKit.h>
-#import <XCTest/XCTest.h>
 
-#import "GTXCheckBlock.h"
+#include "gtx_types.h"
 
-extern GTXCheckHandlerBlock noOpCheckBlock;
+@interface UIColor (GTXOOPAdditions)
 
-@interface GTXBaseTestCase : XCTestCase
-
-- (NSObject *)newAccessibleElement;
-- (NSObject *)newInaccessibleElement;
-- (void)createTreeFromPreOrderTraversal:(NSArray *)preOrderTraversal;
+/**
+ *  @return a unique pointer to gtx::Color instance for the given color.
+ */
+- (std::unique_ptr<gtx::Color>)gtx_color;
 
 @end
diff --git a/Classes/UIColor+GTXOOPAdditions.mm b/Classes/UIColor+GTXOOPAdditions.mm
new file mode 100644
index 0000000..a575db6
--- /dev/null
+++ b/Classes/UIColor+GTXOOPAdditions.mm
@@ -0,0 +1,35 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+
+#import "UIColor+GTXOOPAdditions.h"
+
+@implementation UIColor (GTXOOPAdditions)
+
+- (std::unique_ptr<gtx::Color>)gtx_color {
+  auto color = std::make_unique<gtx::Color>();
+  CGFloat red, blue, green, alpha;
+  [self getRed:&red green:&green blue:&blue alpha:&alpha];
+  color->red = 255.0 * red;
+  color->green = 255.0 * green;
+  color->blue = 255.0 * blue;
+  color->alpha = 255.0 * alpha;
+  return color;
+}
+
+@end
+
diff --git a/GTXiLib.podspec b/GTXiLib.podspec
index fc5759f..d79bf2e 100644
--- a/GTXiLib.podspec
+++ b/GTXiLib.podspec
@@ -1,6 +1,6 @@
 Pod::Spec.new do |s|
   s.name         = "GTXiLib"
-  s.version      = "3.1"
+  s.version      = "4.0"
   s.summary      = "iOS Accessibility testing library."
   s.description  = <<-DESC
   iOS Accessibility testing library that works with XCTest based frameworks.
@@ -9,6 +9,7 @@
   s.license      = "Apache License 2.0"
   s.author       = "j-sid"
   s.platform     = :ios
-  s.source       = { :git => "https://github.com/google/GTXiLib.git", :tag => "3.1.0" }
+  s.source       = { :git => "https://github.com/google/GTXiLib.git", :tag => "4.0.0" }
   s.source_files = "Classes/**/*.{h,m,swift}"
+  s.dependency 'Protobuf-C++'
 end
diff --git a/GTXiLib.xcodeproj/project.pbxproj b/GTXiLib.xcodeproj/project.pbxproj
index a44bd16..8dfb4b9 100644
--- a/GTXiLib.xcodeproj/project.pbxproj
+++ b/GTXiLib.xcodeproj/project.pbxproj
@@ -10,54 +10,131 @@
 		610CA3FD204DFC76008BAAA1 /* GTXPluginXCTestCase.h in Headers */ = {isa = PBXBuildFile; fileRef = 610CA3FB204DFC76008BAAA1 /* GTXPluginXCTestCase.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		610CA3FE204DFC76008BAAA1 /* GTXPluginXCTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 610CA3FC204DFC76008BAAA1 /* GTXPluginXCTestCase.m */; };
 		6115E78B204F5BA3003E32F9 /* GTXiLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 613C3F41204A09E8007D44A8 /* GTXiLib.framework */; };
-		6115E79B204F5BC9003E32F9 /* GTXToolKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E791204F5BC6003E32F9 /* GTXToolKitTests.m */; };
-		6115E79C204F5BC9003E32F9 /* GTXTestSuiteTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E792204F5BC6003E32F9 /* GTXTestSuiteTests.m */; };
-		6115E79D204F5BC9003E32F9 /* GTXChecksCollectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E793204F5BC7003E32F9 /* GTXChecksCollectionTests.m */; };
-		6115E79E204F5BC9003E32F9 /* GTXAccessibilityTreeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E794204F5BC7003E32F9 /* GTXAccessibilityTreeTests.m */; };
-		6115E79F204F5BC9003E32F9 /* GTXAnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E795204F5BC8003E32F9 /* GTXAnalyticsTests.m */; };
-		6115E7A0204F5BC9003E32F9 /* GTXTestAccessibilityElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E798204F5BC8003E32F9 /* GTXTestAccessibilityElements.m */; };
-		6115E7A1204F5BC9003E32F9 /* GTXImageAndColorUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E799204F5BC8003E32F9 /* GTXImageAndColorUtilsTests.m */; };
-		6115E7A2204F5BC9003E32F9 /* GTXBaseTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 6115E79A204F5BC9003E32F9 /* GTXBaseTestCase.m */; };
-		61284DCB211E3FE400F8FF29 /* GTXTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DC3211E3FE100F8FF29 /* GTXTestViewController.m */; };
-		61284DCC211E3FE400F8FF29 /* GTXTestViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 61284DC4211E3FE200F8FF29 /* GTXTestViewController.xib */; };
-		61284DCD211E3FE400F8FF29 /* GTXTestAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DC5211E3FE200F8FF29 /* GTXTestAppDelegate.m */; };
-		61284DCE211E3FE400F8FF29 /* GTXTestStepperButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DC6211E3FE200F8FF29 /* GTXTestStepperButton.m */; };
-		61284DCF211E3FE400F8FF29 /* GTXTestApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DCA211E3FE400F8FF29 /* GTXTestApp.m */; };
-		61284DD5211E42CF00F8FF29 /* GTXBlacklistBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DD2211E42CD00F8FF29 /* GTXBlacklistBlock.m */; };
-		61284DD6211E42CF00F8FF29 /* GTXBlacklistBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 61284DD3211E42CE00F8FF29 /* GTXBlacklistBlock.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		61284DD7211E42CF00F8FF29 /* GTXBlacklisting.h in Headers */ = {isa = PBXBuildFile; fileRef = 61284DD4211E42CE00F8FF29 /* GTXBlacklisting.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		6121D2C825CDF4F70081FAE0 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6121D2C725CDF4F70081FAE0 /* UIKit.framework */; };
+		6121D2CA25CDF4FF0081FAE0 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6121D2C925CDF4FF0081FAE0 /* CoreGraphics.framework */; };
 		61284DDA211E437800F8FF29 /* GTXTestEnvironment.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DD8211E437700F8FF29 /* GTXTestEnvironment.m */; };
 		61284DDB211E437800F8FF29 /* GTXTestEnvironment.h in Headers */ = {isa = PBXBuildFile; fileRef = 61284DD9211E437800F8FF29 /* GTXTestEnvironment.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		61284DF9211E447E00F8FF29 /* GTXTestGtxWorksForPassingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DEA211E447800F8FF29 /* GTXTestGtxWorksForPassingTests.m */; };
-		61284DFA211E447E00F8FF29 /* GTXTestFailingClassFailCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DEB211E447900F8FF29 /* GTXTestFailingClassFailCheck.m */; };
-		61284DFB211E447E00F8FF29 /* GTXTestAnalyticsBaseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DEC211E447900F8FF29 /* GTXTestAnalyticsBaseTest.m */; };
-		61284DFC211E447E00F8FF29 /* GTXTestGtxCanBlacklistTestCases.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DED211E447900F8FF29 /* GTXTestGtxCanBlacklistTestCases.m */; };
-		61284DFD211E447E00F8FF29 /* GTXTestGtxCanDetectFailuresInInheritedTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DEE211E447A00F8FF29 /* GTXTestGtxCanDetectFailuresInInheritedTests.m */; };
-		61284DFE211E447E00F8FF29 /* GTXTestGtxCanIgnoreElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DEF211E447A00F8FF29 /* GTXTestGtxCanIgnoreElements.m */; };
-		61284DFF211E447E00F8FF29 /* GTXTestGtxWithDefaultChecks.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF0211E447A00F8FF29 /* GTXTestGtxWithDefaultChecks.m */; };
-		61284E00211E447E00F8FF29 /* GTXTestBaseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF1211E447B00F8FF29 /* GTXTestBaseTest.m */; };
-		61284E01211E447E00F8FF29 /* GTXTestGtxCanWhitelistTestCases.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF2211E447C00F8FF29 /* GTXTestGtxCanWhitelistTestCases.m */; };
-		61284E02211E447E00F8FF29 /* GTXTestAnalyticsIsTriggered.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF3211E447C00F8FF29 /* GTXTestAnalyticsIsTriggered.m */; };
-		61284E03211E447E00F8FF29 /* GTXTestAnalyticsCanBeDisabled.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF5211E447C00F8FF29 /* GTXTestAnalyticsCanBeDisabled.m */; };
-		61284E04211E447E00F8FF29 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF6211E447D00F8FF29 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m */; };
-		61284E05211E447E00F8FF29 /* GTXTestGtxCanDetectFailures.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284DF8211E447D00F8FF29 /* GTXTestGtxCanDetectFailures.m */; };
-		61284E0A211E45C600F8FF29 /* GTXBlacklistFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 61284E08211E45C500F8FF29 /* GTXBlacklistFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		61284E0B211E45C600F8FF29 /* GTXBlacklistFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 61284E09211E45C600F8FF29 /* GTXBlacklistFactory.m */; };
-		6133087023FF2F39003F8D41 /* GTXArtifactCollector.m in Sources */ = {isa = PBXBuildFile; fileRef = 6133086B23FF2F39003F8D41 /* GTXArtifactCollector.m */; };
-		6133087123FF2F39003F8D41 /* GTXArtifactProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 6133086C23FF2F39003F8D41 /* GTXArtifactProcessor.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6133087223FF2F39003F8D41 /* GTXArtifactProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 6133086D23FF2F39003F8D41 /* GTXArtifactProcessor.m */; };
-		6133087323FF2F39003F8D41 /* GTXArtifactCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = 6133086E23FF2F39003F8D41 /* GTXArtifactCollector.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6133087423FF2F39003F8D41 /* GTXArtifactImplementing.h in Headers */ = {isa = PBXBuildFile; fileRef = 6133086F23FF2F39003F8D41 /* GTXArtifactImplementing.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		6133088123FF2F53003F8D41 /* UIColor+GTXAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 6133087523FF2F53003F8D41 /* UIColor+GTXAdditions.m */; };
 		6133088223FF2F53003F8D41 /* UIColor+GTXAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 6133087623FF2F53003F8D41 /* UIColor+GTXAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		6133088323FF2F53003F8D41 /* GTXError.h in Headers */ = {isa = PBXBuildFile; fileRef = 6133087723FF2F53003F8D41 /* GTXError.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6133088423FF2F53003F8D41 /* GTXSnapshotContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6133087823FF2F53003F8D41 /* GTXSnapshotContainer.m */; };
-		6133088523FF2F53003F8D41 /* GTXSnapshotBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 6133087923FF2F53003F8D41 /* GTXSnapshotBuffer.m */; };
 		6133088623FF2F53003F8D41 /* GTXError.m in Sources */ = {isa = PBXBuildFile; fileRef = 6133087A23FF2F53003F8D41 /* GTXError.m */; };
 		6133088823FF2F53003F8D41 /* GTXReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 6133087C23FF2F53003F8D41 /* GTXReport.m */; };
-		6133088923FF2F53003F8D41 /* GTXSnapshotBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6133087D23FF2F53003F8D41 /* GTXSnapshotBuffer.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		6133088B23FF2F53003F8D41 /* GTXSnapshotContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 6133087F23FF2F53003F8D41 /* GTXSnapshotContainer.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		6133088C23FF2F53003F8D41 /* GTXReport.h in Headers */ = {isa = PBXBuildFile; fileRef = 6133088023FF2F53003F8D41 /* GTXReport.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		616FDEE725BF49EC00CCCAD5 /* GTXImageRGBAData+GTXOOPAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEC725BF49EB00CCCAD5 /* GTXImageRGBAData+GTXOOPAdditions.mm */; };
+		616FDEE825BF49EC00CCCAD5 /* GTXXCUIElementProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDEC825BF49EB00CCCAD5 /* GTXXCUIElementProxy.h */; };
+		616FDEE925BF49EC00CCCAD5 /* GTXSwizzler.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEC925BF49EB00CCCAD5 /* GTXSwizzler.m */; };
+		616FDEEA25BF49EC00CCCAD5 /* GTXXCUIElementQueryProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDECA25BF49EB00CCCAD5 /* GTXXCUIElementQueryProxy.h */; };
+		616FDEEB25BF49EC00CCCAD5 /* GTXExcludeListing.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDECB25BF49EB00CCCAD5 /* GTXExcludeListing.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		616FDEEC25BF49EC00CCCAD5 /* GTXSwizzler.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDECC25BF49EB00CCCAD5 /* GTXSwizzler.h */; };
+		616FDEED25BF49EC00CCCAD5 /* GTXElementResultCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDECD25BF49EB00CCCAD5 /* GTXElementResultCollection.h */; };
+		616FDEEE25BF49EC00CCCAD5 /* GTXXCUIApplicationProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDECE25BF49EB00CCCAD5 /* GTXXCUIApplicationProxy.h */; };
+		616FDEEF25BF49EC00CCCAD5 /* GTXToolKit.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDECF25BF49EB00CCCAD5 /* GTXToolKit.mm */; };
+		616FDEF025BF49EC00CCCAD5 /* GTXExcludeListFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDED025BF49EB00CCCAD5 /* GTXExcludeListFactory.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		616FDEF125BF49EC00CCCAD5 /* UIColor+GTXOOPAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDED125BF49EB00CCCAD5 /* UIColor+GTXOOPAdditions.h */; };
+		616FDEF225BF49EC00CCCAD5 /* GTXImageRGBAData+GTXOOPAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDED225BF49EB00CCCAD5 /* GTXImageRGBAData+GTXOOPAdditions.h */; };
+		616FDEF325BF49EC00CCCAD5 /* GTXCheckResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDED325BF49EC00CCCAD5 /* GTXCheckResult.m */; };
+		616FDEF425BF49EC00CCCAD5 /* GTXToolKit+GTXOOPAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDED425BF49EC00CCCAD5 /* GTXToolKit+GTXOOPAdditions.h */; };
+		616FDEF525BF49EC00CCCAD5 /* GTXExcludeListBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDED525BF49EC00CCCAD5 /* GTXExcludeListBlock.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		616FDEF625BF49EC00CCCAD5 /* NSObject+GTXAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDED625BF49EC00CCCAD5 /* NSObject+GTXAdditions.h */; };
+		616FDEF725BF49EC00CCCAD5 /* GTXXCUIElementProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDED725BF49EC00CCCAD5 /* GTXXCUIElementProxy.m */; };
+		616FDEF825BF49EC00CCCAD5 /* UIColor+GTXOOPAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDED825BF49EC00CCCAD5 /* UIColor+GTXOOPAdditions.mm */; };
+		616FDEF925BF49EC00CCCAD5 /* GTXHierarchyResultCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDED925BF49EC00CCCAD5 /* GTXHierarchyResultCollection.h */; };
+		616FDEFA25BF49EC00CCCAD5 /* GTXXCUIApplicationProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEDA25BF49EC00CCCAD5 /* GTXXCUIApplicationProxy.m */; };
+		616FDEFB25BF49EC00CCCAD5 /* GTXElementReference.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEDB25BF49EC00CCCAD5 /* GTXElementReference.m */; };
+		616FDEFC25BF49EC00CCCAD5 /* GTXHierarchyResultCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEDC25BF49EC00CCCAD5 /* GTXHierarchyResultCollection.m */; };
+		616FDEFD25BF49EC00CCCAD5 /* GTXExcludeListFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEDD25BF49EC00CCCAD5 /* GTXExcludeListFactory.m */; };
+		616FDEFE25BF49EC00CCCAD5 /* NSString+GTXAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDEDE25BF49EC00CCCAD5 /* NSString+GTXAdditions.h */; };
+		616FDEFF25BF49EC00CCCAD5 /* NSString+GTXAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEDF25BF49EC00CCCAD5 /* NSString+GTXAdditions.mm */; };
+		616FDF0025BF49EC00CCCAD5 /* GTXElementResultCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEE025BF49EC00CCCAD5 /* GTXElementResultCollection.m */; };
+		616FDF0125BF49EC00CCCAD5 /* GTXImageAndColorUtils.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEE125BF49EC00CCCAD5 /* GTXImageAndColorUtils.mm */; };
+		616FDF0225BF49EC00CCCAD5 /* GTXXCUIElementQueryProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEE225BF49EC00CCCAD5 /* GTXXCUIElementQueryProxy.m */; };
+		616FDF0325BF49EC00CCCAD5 /* GTXExcludeListBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEE325BF49EC00CCCAD5 /* GTXExcludeListBlock.m */; };
+		616FDF0425BF49EC00CCCAD5 /* GTXElementReference.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDEE425BF49EC00CCCAD5 /* GTXElementReference.h */; };
+		616FDF0525BF49EC00CCCAD5 /* NSObject+GTXAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDEE525BF49EC00CCCAD5 /* NSObject+GTXAdditions.mm */; };
+		616FDF0625BF49EC00CCCAD5 /* GTXCheckResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDEE625BF49EC00CCCAD5 /* GTXCheckResult.h */; };
+		616FDF1325BF4ACB00CCCAD5 /* GTXTestApp-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 616FDF1125BF4ACA00CCCAD5 /* GTXTestApp-Info.plist */; };
+		616FDF1425BF4ACB00CCCAD5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 616FDF1225BF4ACA00CCCAD5 /* LaunchScreen.storyboard */; };
+		616FDF2125BF4ADD00CCCAD5 /* GTXTestAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF1925BF4ADC00CCCAD5 /* GTXTestAppDelegate.m */; };
+		616FDF2225BF4ADD00CCCAD5 /* GTXTestApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF1A25BF4ADC00CCCAD5 /* GTXTestApp.m */; };
+		616FDF2325BF4ADD00CCCAD5 /* GTXTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF1B25BF4ADC00CCCAD5 /* GTXTestViewController.m */; };
+		616FDF2425BF4ADD00CCCAD5 /* GTXTestViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 616FDF1E25BF4ADC00CCCAD5 /* GTXTestViewController.xib */; };
+		616FDF2525BF4ADD00CCCAD5 /* GTXTestStepperButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF2025BF4ADC00CCCAD5 /* GTXTestStepperButton.m */; };
+		616FDF4D25BF4B7800CCCAD5 /* GTXReportTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF3825BF4B7800CCCAD5 /* GTXReportTests.m */; };
+		616FDF4E25BF4B7800CCCAD5 /* GTXChecksCollectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF3925BF4B7800CCCAD5 /* GTXChecksCollectionTests.m */; };
+		616FDF4F25BF4B7800CCCAD5 /* GTXToolkitSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF3B25BF4B7800CCCAD5 /* GTXToolkitSwiftTests.swift */; };
+		616FDF5025BF4B7800CCCAD5 /* GTXElementReferenceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF3C25BF4B7800CCCAD5 /* GTXElementReferenceTests.m */; };
+		616FDF5125BF4B7800CCCAD5 /* GTXTestDynamicTypeCheckOptions.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF3D25BF4B7800CCCAD5 /* GTXTestDynamicTypeCheckOptions.m */; };
+		616FDF5225BF4B7800CCCAD5 /* GTXCheckResultTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF3E25BF4B7800CCCAD5 /* GTXCheckResultTests.m */; };
+		616FDF5325BF4B7800CCCAD5 /* GTXAccessibilityTreeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF3F25BF4B7800CCCAD5 /* GTXAccessibilityTreeTests.m */; };
+		616FDF5425BF4B7800CCCAD5 /* GTXBaseTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4025BF4B7800CCCAD5 /* GTXBaseTestCase.m */; };
+		616FDF5525BF4B7800CCCAD5 /* GTXImageAndColorUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4125BF4B7800CCCAD5 /* GTXImageAndColorUtilsTests.m */; };
+		616FDF5625BF4B7800CCCAD5 /* GTXTestAccessibilityElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4225BF4B7800CCCAD5 /* GTXTestAccessibilityElements.m */; };
+		616FDF5725BF4B7800CCCAD5 /* GTXToolkitOOPTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4325BF4B7800CCCAD5 /* GTXToolkitOOPTests.mm */; };
+		616FDF5825BF4B7800CCCAD5 /* GTXElementResultCollectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4525BF4B7800CCCAD5 /* GTXElementResultCollectionTests.m */; };
+		616FDF5925BF4B7800CCCAD5 /* GTXImageRGBADataTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4625BF4B7800CCCAD5 /* GTXImageRGBADataTests.mm */; };
+		616FDF5A25BF4B7800CCCAD5 /* GTXTestSuiteTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4725BF4B7800CCCAD5 /* GTXTestSuiteTests.m */; };
+		616FDF5B25BF4B7800CCCAD5 /* GTXToolKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4825BF4B7800CCCAD5 /* GTXToolKitTests.m */; };
+		616FDF5C25BF4B7800CCCAD5 /* GTXAnalyticsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4925BF4B7800CCCAD5 /* GTXAnalyticsTests.m */; };
+		616FDF5D25BF4B7800CCCAD5 /* GTXResultTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4B25BF4B7800CCCAD5 /* GTXResultTests.m */; };
+		616FDF5E25BF4B7800CCCAD5 /* GTXHierarchyResultCollectionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF4C25BF4B7800CCCAD5 /* GTXHierarchyResultCollectionTests.m */; };
+		616FDF7625BF4BB400CCCAD5 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF6825BF4BB400CCCAD5 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m */; };
+		616FDF7725BF4BB400CCCAD5 /* GTXTestAnalyticsCanBeDisabled.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF6925BF4BB400CCCAD5 /* GTXTestAnalyticsCanBeDisabled.m */; };
+		616FDF7825BF4BB400CCCAD5 /* GTXTestGtxCanWhitelistTestCases.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF6B25BF4BB400CCCAD5 /* GTXTestGtxCanWhitelistTestCases.m */; };
+		616FDF7925BF4BB400CCCAD5 /* GTXTestFailingClassFailCheck.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF6C25BF4BB400CCCAD5 /* GTXTestFailingClassFailCheck.m */; };
+		616FDF7A25BF4BB400CCCAD5 /* GTXTestGtxCanExcludeListTestCases.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF6D25BF4BB400CCCAD5 /* GTXTestGtxCanExcludeListTestCases.m */; };
+		616FDF7B25BF4BB400CCCAD5 /* GTXTestAnalyticsBaseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF6E25BF4BB400CCCAD5 /* GTXTestAnalyticsBaseTest.m */; };
+		616FDF7C25BF4BB400CCCAD5 /* GTXTestGtxCanIgnoreElements.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF6F25BF4BB400CCCAD5 /* GTXTestGtxCanIgnoreElements.m */; };
+		616FDF7D25BF4BB400CCCAD5 /* GTXTestGtxWorksForPassingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF7025BF4BB400CCCAD5 /* GTXTestGtxWorksForPassingTests.m */; };
+		616FDF7E25BF4BB400CCCAD5 /* GTXTestAnalyticsIsTriggered.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF7125BF4BB400CCCAD5 /* GTXTestAnalyticsIsTriggered.m */; };
+		616FDF7F25BF4BB400CCCAD5 /* GTXTestGtxCanDetectFailures.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF7225BF4BB400CCCAD5 /* GTXTestGtxCanDetectFailures.m */; };
+		616FDF8025BF4BB400CCCAD5 /* GTXTestGtxCanDetectFailuresInInheritedTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF7325BF4BB400CCCAD5 /* GTXTestGtxCanDetectFailuresInInheritedTests.m */; };
+		616FDF8125BF4BB400CCCAD5 /* GTXTestBaseTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF7425BF4BB400CCCAD5 /* GTXTestBaseTest.m */; };
+		616FDF8225BF4BB400CCCAD5 /* GTXTestGtxWithDefaultChecks.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF7525BF4BB400CCCAD5 /* GTXTestGtxWithDefaultChecks.m */; };
+		616FDFB825BF4D3500CCCAD5 /* GTXTestPassingIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF9525BF4C1200CCCAD5 /* GTXTestPassingIntegrationTest.m */; };
+		616FDFB925BF4D3500CCCAD5 /* GTXTestIntegrationTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF9425BF4C1200CCCAD5 /* GTXTestIntegrationTestCase.m */; };
+		616FDFBA25BF4D3500CCCAD5 /* GTXTestFailingIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF9725BF4C1200CCCAD5 /* GTXTestFailingIntegrationTest.m */; };
+		616FDFE125BF4DC500CCCAD5 /* ui_element.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFC325BF4DC400CCCAD5 /* ui_element.h */; };
+		616FDFE225BF4DC500CCCAD5 /* localized_strings_manager.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFC425BF4DC400CCCAD5 /* localized_strings_manager.cc */; };
+		616FDFE325BF4DC500CCCAD5 /* check_result.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFC525BF4DC400CCCAD5 /* check_result.cc */; };
+		616FDFE425BF4DC500CCCAD5 /* no_label_check.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFC625BF4DC400CCCAD5 /* no_label_check.h */; };
+		616FDFE525BF4DC500CCCAD5 /* parameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFC725BF4DC400CCCAD5 /* parameters.h */; };
+		616FDFE625BF4DC500CCCAD5 /* gtx_types.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFC825BF4DC400CCCAD5 /* gtx_types.h */; };
+		616FDFE725BF4DC500CCCAD5 /* string_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFC925BF4DC400CCCAD5 /* string_utils.cc */; };
+		616FDFE825BF4DC500CCCAD5 /* accessibility_label_not_punctuated_check.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFCA25BF4DC400CCCAD5 /* accessibility_label_not_punctuated_check.h */; };
+		616FDFE925BF4DC500CCCAD5 /* parameters.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFCB25BF4DC400CCCAD5 /* parameters.cc */; };
+		616FDFEA25BF4DC500CCCAD5 /* image_color_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFCC25BF4DC400CCCAD5 /* image_color_utils.h */; };
+		616FDFEB25BF4DC500CCCAD5 /* contrast_swatch.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFCD25BF4DC400CCCAD5 /* contrast_swatch.cc */; };
+		616FDFEC25BF4DC500CCCAD5 /* error_message.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFCE25BF4DC400CCCAD5 /* error_message.cc */; };
+		616FDFED25BF4DC500CCCAD5 /* toolkit.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFCF25BF4DC400CCCAD5 /* toolkit.h */; };
+		616FDFEE25BF4DC500CCCAD5 /* toolkit.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFD025BF4DC400CCCAD5 /* toolkit.cc */; };
+		616FDFEF25BF4DC500CCCAD5 /* gtx_types.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFD125BF4DC500CCCAD5 /* gtx_types.cc */; };
+		616FDFF025BF4DC500CCCAD5 /* ui_element.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFD225BF4DC500CCCAD5 /* ui_element.cc */; };
+		616FDFF125BF4DC500CCCAD5 /* contrast_check.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFD325BF4DC500CCCAD5 /* contrast_check.cc */; };
+		616FDFF225BF4DC500CCCAD5 /* accessibility_label_not_punctuated_check.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFD425BF4DC500CCCAD5 /* accessibility_label_not_punctuated_check.cc */; };
+		616FDFF325BF4DC500CCCAD5 /* contrast_swatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFD525BF4DC500CCCAD5 /* contrast_swatch.h */; };
+		616FDFF425BF4DC500CCCAD5 /* image_color_utils.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFD625BF4DC500CCCAD5 /* image_color_utils.cc */; };
+		616FDFF525BF4DC500CCCAD5 /* minimum_tappable_area_check.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFD725BF4DC500CCCAD5 /* minimum_tappable_area_check.cc */; };
+		616FDFF625BF4DC500CCCAD5 /* check.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FDFD825BF4DC500CCCAD5 /* check.cc */; };
+		616FDFF725BF4DC500CCCAD5 /* localized_strings_manager.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFD925BF4DC500CCCAD5 /* localized_strings_manager.h */; };
+		616FDFF825BF4DC500CCCAD5 /* error_message.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFDA25BF4DC500CCCAD5 /* error_message.h */; };
+		616FDFF925BF4DC500CCCAD5 /* check.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFDB25BF4DC500CCCAD5 /* check.h */; };
+		616FDFFA25BF4DC500CCCAD5 /* minimum_tappable_area_check.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFDC25BF4DC500CCCAD5 /* minimum_tappable_area_check.h */; };
+		616FDFFB25BF4DC500CCCAD5 /* contrast_check.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFDD25BF4DC500CCCAD5 /* contrast_check.h */; };
+		616FDFFC25BF4DC500CCCAD5 /* check_result.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFDE25BF4DC500CCCAD5 /* check_result.h */; };
+		616FDFFD25BF4DC500CCCAD5 /* string_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFDF25BF4DC500CCCAD5 /* string_utils.h */; };
+		616FDFFE25BF4DC500CCCAD5 /* element_type.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FDFE025BF4DC500CCCAD5 /* element_type.h */; };
+		616FE00625BF4DF700CCCAD5 /* gtx.pb.h in Headers */ = {isa = PBXBuildFile; fileRef = 616FE00425BF4DF700CCCAD5 /* gtx.pb.h */; };
+		616FE00725BF4DF700CCCAD5 /* gtx.pb.cc in Sources */ = {isa = PBXBuildFile; fileRef = 616FE00525BF4DF700CCCAD5 /* gtx.pb.cc */; };
+		616FE01625BF4E8600CCCAD5 /* GTXiLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 613C3F41204A09E8007D44A8 /* GTXiLib.framework */; };
+		616FE02B25BF4E9A00CCCAD5 /* GTXiLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 613C3F41204A09E8007D44A8 /* GTXiLib.framework */; };
+		616FE03F25BF4EAB00CCCAD5 /* GTXUIElementTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF9225BF4BF500CCCAD5 /* GTXUIElementTests.mm */; };
+		616FE04025BF4EAB00CCCAD5 /* GTXTypesTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF9125BF4BF500CCCAD5 /* GTXTypesTests.mm */; };
+		616FE04125BF4EAB00CCCAD5 /* GTXColorSwatchTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF9025BF4BF500CCCAD5 /* GTXColorSwatchTests.mm */; };
+		616FE04225BF4EAB00CCCAD5 /* GTXStringUtilsTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF8E25BF4BF500CCCAD5 /* GTXStringUtilsTests.mm */; };
+		616FE04325BF4EAB00CCCAD5 /* GTXToolkitTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF8F25BF4BF500CCCAD5 /* GTXToolkitTests.mm */; };
+		616FE04B25BF4EB200CCCAD5 /* GTXTestXCUIElementTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF9325BF4C0300CCCAD5 /* GTXTestXCUIElementTests.m */; };
+		616FE05425BF4EDD00CCCAD5 /* XCUIElement+GTXTestAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF9A25BF4C3B00CCCAD5 /* XCUIElement+GTXTestAdditions.mm */; };
+		616FE05D25BF4EE500CCCAD5 /* XCUIElement+GTXTestAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF9A25BF4C3B00CCCAD5 /* XCUIElement+GTXTestAdditions.mm */; };
 		618E065F23FF412800BDD929 /* GTXResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 618E065D23FF412800BDD929 /* GTXResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		618E066023FF412800BDD929 /* GTXResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 618E065E23FF412800BDD929 /* GTXResult.m */; };
 		61A0C4DE2061896300DF0169 /* GTXiLibCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 61A0C4DB2061896300DF0169 /* GTXiLibCore.m */; };
@@ -66,7 +143,6 @@
 		61ABAEB0204A0B0B006DBF0A /* GTXAnalyticsUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAE8E204A0B02006DBF0A /* GTXAnalyticsUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		61ABAEB1204A0B0B006DBF0A /* GTXAnalytics.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAE8F204A0B02006DBF0A /* GTXAnalytics.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		61ABAEB2204A0B0B006DBF0A /* GTXErrorReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAE90204A0B02006DBF0A /* GTXErrorReporter.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		61ABAEB3204A0B0B006DBF0A /* GTXImageAndColorUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAE91204A0B02006DBF0A /* GTXImageAndColorUtils.m */; };
 		61ABAEB4204A0B0B006DBF0A /* GTXTestSuite.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAE92204A0B03006DBF0A /* GTXTestSuite.m */; };
 		61ABAEB5204A0B0B006DBF0A /* GTXAccessibilityTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAE93204A0B03006DBF0A /* GTXAccessibilityTree.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		61ABAEB6204A0B0B006DBF0A /* GTXCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAE94204A0B03006DBF0A /* GTXCommon.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -80,7 +156,6 @@
 		61ABAEBF204A0B0B006DBF0A /* NSError+GTXAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAE9D204A0B05006DBF0A /* NSError+GTXAdditions.m */; };
 		61ABAEC0204A0B0B006DBF0A /* GTXCheckBlock.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAE9E204A0B06006DBF0A /* GTXCheckBlock.m */; };
 		61ABAEC1204A0B0B006DBF0A /* GTXTestSuite.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAE9F204A0B06006DBF0A /* GTXTestSuite.h */; settings = {ATTRIBUTES = (Public, ); }; };
-		61ABAEC2204A0B0B006DBF0A /* GTXToolKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAEA0204A0B06006DBF0A /* GTXToolKit.m */; };
 		61ABAEC3204A0B0B006DBF0A /* GTXTestCase.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAEA1204A0B06006DBF0A /* GTXTestCase.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		61ABAEC4204A0B0B006DBF0A /* GTXImageAndColorUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAEA2204A0B06006DBF0A /* GTXImageAndColorUtils.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		61ABAEC6204A0B0B006DBF0A /* GTXChecksCollection.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAEA4204A0B07006DBF0A /* GTXChecksCollection.m */; };
@@ -91,9 +166,22 @@
 		61ABAECC204A0B0B006DBF0A /* GTXErrorReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAEAA204A0B09006DBF0A /* GTXErrorReporter.m */; };
 		61ABAECD204A0B0B006DBF0A /* GTXToolKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 61ABAEAB204A0B09006DBF0A /* GTXToolKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		61ABAECE204A0B0B006DBF0A /* GTXImageRGBAData.m in Sources */ = {isa = PBXBuildFile; fileRef = 61ABAEAC204A0B0A006DBF0A /* GTXImageRGBAData.m */; };
+		61CC44B025C0CAE600CF632A /* GTXUITestBaseTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 61CC44AF25C0CAE600CF632A /* GTXUITestBaseTest.mm */; };
+		61CC44B125C0CAE600CF632A /* GTXUITestBaseTest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 61CC44AF25C0CAE600CF632A /* GTXUITestBaseTest.mm */; };
+		61E1A12E25C0CD34009FBAD9 /* GTXTestStepperButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF2025BF4ADC00CCCAD5 /* GTXTestStepperButton.m */; };
+		61E1A12F25C0CD34009FBAD9 /* GTXTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF1B25BF4ADC00CCCAD5 /* GTXTestViewController.m */; };
+		61E1A18425C0CDBF009FBAD9 /* GTXTestStepperButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF2025BF4ADC00CCCAD5 /* GTXTestStepperButton.m */; };
+		61E1A18525C0CDBF009FBAD9 /* GTXTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 616FDF1B25BF4ADC00CCCAD5 /* GTXTestViewController.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
+		610AA77325C0C1F5002C9C49 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 613C3F38204A09E7007D44A8 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 613C3F40204A09E7007D44A8;
+			remoteInfo = GTXiLib;
+		};
 		6115E78C204F5BA3003E32F9 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = 613C3F38204A09E7007D44A8 /* Project object */;
@@ -115,71 +203,172 @@
 			remoteGlobalIDString = 613C3F40204A09E7007D44A8;
 			remoteInfo = GTXiLib;
 		};
+		616FDFA925BF4CFE00CCCAD5 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 613C3F38204A09E7007D44A8 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 61284DAC211E3F8300F8FF29;
+			remoteInfo = TestApp;
+		};
+		616FE01725BF4E8600CCCAD5 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 613C3F38204A09E7007D44A8 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 613C3F40204A09E7007D44A8;
+			remoteInfo = GTXiLib;
+		};
+		616FE02C25BF4E9A00CCCAD5 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 613C3F38204A09E7007D44A8 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 613C3F40204A09E7007D44A8;
+			remoteInfo = GTXiLib;
+		};
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXFileReference section */
 		610CA3FB204DFC76008BAAA1 /* GTXPluginXCTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXPluginXCTestCase.h; path = Classes/GTXPluginXCTestCase.h; sourceTree = SOURCE_ROOT; };
 		610CA3FC204DFC76008BAAA1 /* GTXPluginXCTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXPluginXCTestCase.m; path = Classes/GTXPluginXCTestCase.m; sourceTree = SOURCE_ROOT; };
 		6115E786204F5BA2003E32F9 /* GTXiUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GTXiUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		6115E791204F5BC6003E32F9 /* GTXToolKitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXToolKitTests.m; path = Tests/UnitTests/GTXToolKitTests.m; sourceTree = SOURCE_ROOT; };
-		6115E792204F5BC6003E32F9 /* GTXTestSuiteTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestSuiteTests.m; path = Tests/UnitTests/GTXTestSuiteTests.m; sourceTree = SOURCE_ROOT; };
-		6115E793204F5BC7003E32F9 /* GTXChecksCollectionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXChecksCollectionTests.m; path = Tests/UnitTests/GTXChecksCollectionTests.m; sourceTree = SOURCE_ROOT; };
-		6115E794204F5BC7003E32F9 /* GTXAccessibilityTreeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXAccessibilityTreeTests.m; path = Tests/UnitTests/GTXAccessibilityTreeTests.m; sourceTree = SOURCE_ROOT; };
-		6115E795204F5BC8003E32F9 /* GTXAnalyticsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXAnalyticsTests.m; path = Tests/UnitTests/GTXAnalyticsTests.m; sourceTree = SOURCE_ROOT; };
-		6115E796204F5BC8003E32F9 /* GTXTestAccessibilityElements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestAccessibilityElements.h; path = Tests/UnitTests/GTXTestAccessibilityElements.h; sourceTree = SOURCE_ROOT; };
-		6115E797204F5BC8003E32F9 /* GTXBaseTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXBaseTestCase.h; path = Tests/UnitTests/GTXBaseTestCase.h; sourceTree = SOURCE_ROOT; };
-		6115E798204F5BC8003E32F9 /* GTXTestAccessibilityElements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAccessibilityElements.m; path = Tests/UnitTests/GTXTestAccessibilityElements.m; sourceTree = SOURCE_ROOT; };
-		6115E799204F5BC8003E32F9 /* GTXImageAndColorUtilsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXImageAndColorUtilsTests.m; path = Tests/UnitTests/GTXImageAndColorUtilsTests.m; sourceTree = SOURCE_ROOT; };
-		6115E79A204F5BC9003E32F9 /* GTXBaseTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXBaseTestCase.m; path = Tests/UnitTests/GTXBaseTestCase.m; sourceTree = SOURCE_ROOT; };
+		6121D2C725CDF4F70081FAE0 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/iOSSupport/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; };
+		6121D2C925CDF4FF0081FAE0 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreGraphics.framework; sourceTree = DEVELOPER_DIR; };
 		61284DAD211E3F8300F8FF29 /* TestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TestApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
-		61284DC3211E3FE100F8FF29 /* GTXTestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestViewController.m; path = Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.m; sourceTree = SOURCE_ROOT; };
-		61284DC4211E3FE200F8FF29 /* GTXTestViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = GTXTestViewController.xib; path = Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.xib; sourceTree = SOURCE_ROOT; };
-		61284DC5211E3FE200F8FF29 /* GTXTestAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAppDelegate.m; path = Tests/FunctionalTests/TestApp/Sources/GTXTestAppDelegate.m; sourceTree = SOURCE_ROOT; };
-		61284DC6211E3FE200F8FF29 /* GTXTestStepperButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestStepperButton.m; path = Tests/FunctionalTests/TestApp/Sources/GTXTestStepperButton.m; sourceTree = SOURCE_ROOT; };
-		61284DC7211E3FE300F8FF29 /* GTXTestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestViewController.h; path = Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.h; sourceTree = SOURCE_ROOT; };
-		61284DC8211E3FE300F8FF29 /* GTXTestStepperButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestStepperButton.h; path = Tests/FunctionalTests/TestApp/Sources/GTXTestStepperButton.h; sourceTree = SOURCE_ROOT; };
-		61284DC9211E3FE300F8FF29 /* GTXTestAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestAppDelegate.h; path = Tests/FunctionalTests/TestApp/Sources/GTXTestAppDelegate.h; sourceTree = SOURCE_ROOT; };
-		61284DCA211E3FE400F8FF29 /* GTXTestApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestApp.m; path = Tests/FunctionalTests/TestApp/Sources/GTXTestApp.m; sourceTree = SOURCE_ROOT; };
-		61284DD0211E3FF400F8FF29 /* GTXTestApp-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GTXTestApp-Info.plist"; path = "Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist"; sourceTree = SOURCE_ROOT; };
-		61284DD2211E42CD00F8FF29 /* GTXBlacklistBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXBlacklistBlock.m; path = Classes/GTXBlacklistBlock.m; sourceTree = SOURCE_ROOT; };
-		61284DD3211E42CE00F8FF29 /* GTXBlacklistBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXBlacklistBlock.h; path = Classes/GTXBlacklistBlock.h; sourceTree = SOURCE_ROOT; };
-		61284DD4211E42CE00F8FF29 /* GTXBlacklisting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXBlacklisting.h; path = Classes/GTXBlacklisting.h; sourceTree = SOURCE_ROOT; };
 		61284DD8211E437700F8FF29 /* GTXTestEnvironment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestEnvironment.m; path = Classes/GTXTestEnvironment.m; sourceTree = SOURCE_ROOT; };
 		61284DD9211E437800F8FF29 /* GTXTestEnvironment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestEnvironment.h; path = Classes/GTXTestEnvironment.h; sourceTree = SOURCE_ROOT; };
 		61284DE0211E442700F8FF29 /* FunctionalTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FunctionalTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
-		61284DEA211E447800F8FF29 /* GTXTestGtxWorksForPassingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxWorksForPassingTests.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxWorksForPassingTests.m; sourceTree = SOURCE_ROOT; };
-		61284DEB211E447900F8FF29 /* GTXTestFailingClassFailCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestFailingClassFailCheck.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestFailingClassFailCheck.m; sourceTree = SOURCE_ROOT; };
-		61284DEC211E447900F8FF29 /* GTXTestAnalyticsBaseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAnalyticsBaseTest.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestAnalyticsBaseTest.m; sourceTree = SOURCE_ROOT; };
-		61284DED211E447900F8FF29 /* GTXTestGtxCanBlacklistTestCases.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanBlacklistTestCases.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanBlacklistTestCases.m; sourceTree = SOURCE_ROOT; };
-		61284DEE211E447A00F8FF29 /* GTXTestGtxCanDetectFailuresInInheritedTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanDetectFailuresInInheritedTests.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanDetectFailuresInInheritedTests.m; sourceTree = SOURCE_ROOT; };
-		61284DEF211E447A00F8FF29 /* GTXTestGtxCanIgnoreElements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanIgnoreElements.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElements.m; sourceTree = SOURCE_ROOT; };
-		61284DF0211E447A00F8FF29 /* GTXTestGtxWithDefaultChecks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxWithDefaultChecks.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxWithDefaultChecks.m; sourceTree = SOURCE_ROOT; };
-		61284DF1211E447B00F8FF29 /* GTXTestBaseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestBaseTest.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.m; sourceTree = SOURCE_ROOT; };
-		61284DF2211E447C00F8FF29 /* GTXTestGtxCanWhitelistTestCases.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanWhitelistTestCases.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanWhitelistTestCases.m; sourceTree = SOURCE_ROOT; };
-		61284DF3211E447C00F8FF29 /* GTXTestAnalyticsIsTriggered.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAnalyticsIsTriggered.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestAnalyticsIsTriggered.m; sourceTree = SOURCE_ROOT; };
-		61284DF4211E447C00F8FF29 /* GTXTestAnalyticsBaseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestAnalyticsBaseTest.h; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestAnalyticsBaseTest.h; sourceTree = SOURCE_ROOT; };
-		61284DF5211E447C00F8FF29 /* GTXTestAnalyticsCanBeDisabled.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAnalyticsCanBeDisabled.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestAnalyticsCanBeDisabled.m; sourceTree = SOURCE_ROOT; };
-		61284DF6211E447D00F8FF29 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanIgnoreElementsOnSpecificCheck.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanIgnoreElementsOnSpecificCheck.m; sourceTree = SOURCE_ROOT; };
-		61284DF7211E447D00F8FF29 /* GTXTestBaseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestBaseTest.h; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestBaseTest.h; sourceTree = SOURCE_ROOT; };
-		61284DF8211E447D00F8FF29 /* GTXTestGtxCanDetectFailures.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanDetectFailures.m; path = Tests/FunctionalTests/TestApp/TestSources/GTXTestGtxCanDetectFailures.m; sourceTree = SOURCE_ROOT; };
-		61284E08211E45C500F8FF29 /* GTXBlacklistFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXBlacklistFactory.h; path = Classes/GTXBlacklistFactory.h; sourceTree = SOURCE_ROOT; };
-		61284E09211E45C600F8FF29 /* GTXBlacklistFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXBlacklistFactory.m; path = Classes/GTXBlacklistFactory.m; sourceTree = SOURCE_ROOT; };
-		6133086B23FF2F39003F8D41 /* GTXArtifactCollector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXArtifactCollector.m; path = Classes/GTXArtifactCollector.m; sourceTree = SOURCE_ROOT; };
-		6133086C23FF2F39003F8D41 /* GTXArtifactProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXArtifactProcessor.h; path = Classes/GTXArtifactProcessor.h; sourceTree = SOURCE_ROOT; };
-		6133086D23FF2F39003F8D41 /* GTXArtifactProcessor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXArtifactProcessor.m; path = Classes/GTXArtifactProcessor.m; sourceTree = SOURCE_ROOT; };
-		6133086E23FF2F39003F8D41 /* GTXArtifactCollector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXArtifactCollector.h; path = Classes/GTXArtifactCollector.h; sourceTree = SOURCE_ROOT; };
-		6133086F23FF2F39003F8D41 /* GTXArtifactImplementing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXArtifactImplementing.h; path = Classes/GTXArtifactImplementing.h; sourceTree = SOURCE_ROOT; };
 		6133087523FF2F53003F8D41 /* UIColor+GTXAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIColor+GTXAdditions.m"; path = "Classes/UIColor+GTXAdditions.m"; sourceTree = SOURCE_ROOT; };
 		6133087623FF2F53003F8D41 /* UIColor+GTXAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIColor+GTXAdditions.h"; path = "Classes/UIColor+GTXAdditions.h"; sourceTree = SOURCE_ROOT; };
 		6133087723FF2F53003F8D41 /* GTXError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXError.h; path = Classes/GTXError.h; sourceTree = SOURCE_ROOT; };
-		6133087823FF2F53003F8D41 /* GTXSnapshotContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXSnapshotContainer.m; path = Classes/GTXSnapshotContainer.m; sourceTree = SOURCE_ROOT; };
-		6133087923FF2F53003F8D41 /* GTXSnapshotBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXSnapshotBuffer.m; path = Classes/GTXSnapshotBuffer.m; sourceTree = SOURCE_ROOT; };
 		6133087A23FF2F53003F8D41 /* GTXError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXError.m; path = Classes/GTXError.m; sourceTree = SOURCE_ROOT; };
 		6133087C23FF2F53003F8D41 /* GTXReport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXReport.m; path = Classes/GTXReport.m; sourceTree = SOURCE_ROOT; };
-		6133087D23FF2F53003F8D41 /* GTXSnapshotBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXSnapshotBuffer.h; path = Classes/GTXSnapshotBuffer.h; sourceTree = SOURCE_ROOT; };
-		6133087F23FF2F53003F8D41 /* GTXSnapshotContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXSnapshotContainer.h; path = Classes/GTXSnapshotContainer.h; sourceTree = SOURCE_ROOT; };
 		6133088023FF2F53003F8D41 /* GTXReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXReport.h; path = Classes/GTXReport.h; sourceTree = SOURCE_ROOT; };
 		613C3F41204A09E8007D44A8 /* GTXiLib.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GTXiLib.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		616FDEC725BF49EB00CCCAD5 /* GTXImageRGBAData+GTXOOPAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "GTXImageRGBAData+GTXOOPAdditions.mm"; path = "Classes/GTXImageRGBAData+GTXOOPAdditions.mm"; sourceTree = SOURCE_ROOT; };
+		616FDEC825BF49EB00CCCAD5 /* GTXXCUIElementProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXXCUIElementProxy.h; path = Classes/GTXXCUIElementProxy.h; sourceTree = SOURCE_ROOT; };
+		616FDEC925BF49EB00CCCAD5 /* GTXSwizzler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXSwizzler.m; path = Classes/GTXSwizzler.m; sourceTree = SOURCE_ROOT; };
+		616FDECA25BF49EB00CCCAD5 /* GTXXCUIElementQueryProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXXCUIElementQueryProxy.h; path = Classes/GTXXCUIElementQueryProxy.h; sourceTree = SOURCE_ROOT; };
+		616FDECB25BF49EB00CCCAD5 /* GTXExcludeListing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXExcludeListing.h; path = Classes/GTXExcludeListing.h; sourceTree = SOURCE_ROOT; };
+		616FDECC25BF49EB00CCCAD5 /* GTXSwizzler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXSwizzler.h; path = Classes/GTXSwizzler.h; sourceTree = SOURCE_ROOT; };
+		616FDECD25BF49EB00CCCAD5 /* GTXElementResultCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXElementResultCollection.h; path = Classes/GTXElementResultCollection.h; sourceTree = SOURCE_ROOT; };
+		616FDECE25BF49EB00CCCAD5 /* GTXXCUIApplicationProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXXCUIApplicationProxy.h; path = Classes/GTXXCUIApplicationProxy.h; sourceTree = SOURCE_ROOT; };
+		616FDECF25BF49EB00CCCAD5 /* GTXToolKit.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = GTXToolKit.mm; path = Classes/GTXToolKit.mm; sourceTree = SOURCE_ROOT; };
+		616FDED025BF49EB00CCCAD5 /* GTXExcludeListFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXExcludeListFactory.h; path = Classes/GTXExcludeListFactory.h; sourceTree = SOURCE_ROOT; };
+		616FDED125BF49EB00CCCAD5 /* UIColor+GTXOOPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIColor+GTXOOPAdditions.h"; path = "Classes/UIColor+GTXOOPAdditions.h"; sourceTree = SOURCE_ROOT; };
+		616FDED225BF49EB00CCCAD5 /* GTXImageRGBAData+GTXOOPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GTXImageRGBAData+GTXOOPAdditions.h"; path = "Classes/GTXImageRGBAData+GTXOOPAdditions.h"; sourceTree = SOURCE_ROOT; };
+		616FDED325BF49EC00CCCAD5 /* GTXCheckResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXCheckResult.m; path = Classes/GTXCheckResult.m; sourceTree = SOURCE_ROOT; };
+		616FDED425BF49EC00CCCAD5 /* GTXToolKit+GTXOOPAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "GTXToolKit+GTXOOPAdditions.h"; path = "Classes/GTXToolKit+GTXOOPAdditions.h"; sourceTree = SOURCE_ROOT; };
+		616FDED525BF49EC00CCCAD5 /* GTXExcludeListBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXExcludeListBlock.h; path = Classes/GTXExcludeListBlock.h; sourceTree = SOURCE_ROOT; };
+		616FDED625BF49EC00CCCAD5 /* NSObject+GTXAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSObject+GTXAdditions.h"; path = "Classes/NSObject+GTXAdditions.h"; sourceTree = SOURCE_ROOT; };
+		616FDED725BF49EC00CCCAD5 /* GTXXCUIElementProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXXCUIElementProxy.m; path = Classes/GTXXCUIElementProxy.m; sourceTree = SOURCE_ROOT; };
+		616FDED825BF49EC00CCCAD5 /* UIColor+GTXOOPAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "UIColor+GTXOOPAdditions.mm"; path = "Classes/UIColor+GTXOOPAdditions.mm"; sourceTree = SOURCE_ROOT; };
+		616FDED925BF49EC00CCCAD5 /* GTXHierarchyResultCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXHierarchyResultCollection.h; path = Classes/GTXHierarchyResultCollection.h; sourceTree = SOURCE_ROOT; };
+		616FDEDA25BF49EC00CCCAD5 /* GTXXCUIApplicationProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXXCUIApplicationProxy.m; path = Classes/GTXXCUIApplicationProxy.m; sourceTree = SOURCE_ROOT; };
+		616FDEDB25BF49EC00CCCAD5 /* GTXElementReference.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXElementReference.m; path = Classes/GTXElementReference.m; sourceTree = SOURCE_ROOT; };
+		616FDEDC25BF49EC00CCCAD5 /* GTXHierarchyResultCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXHierarchyResultCollection.m; path = Classes/GTXHierarchyResultCollection.m; sourceTree = SOURCE_ROOT; };
+		616FDEDD25BF49EC00CCCAD5 /* GTXExcludeListFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXExcludeListFactory.m; path = Classes/GTXExcludeListFactory.m; sourceTree = SOURCE_ROOT; };
+		616FDEDE25BF49EC00CCCAD5 /* NSString+GTXAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSString+GTXAdditions.h"; path = "Classes/NSString+GTXAdditions.h"; sourceTree = SOURCE_ROOT; };
+		616FDEDF25BF49EC00CCCAD5 /* NSString+GTXAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "NSString+GTXAdditions.mm"; path = "Classes/NSString+GTXAdditions.mm"; sourceTree = SOURCE_ROOT; };
+		616FDEE025BF49EC00CCCAD5 /* GTXElementResultCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXElementResultCollection.m; path = Classes/GTXElementResultCollection.m; sourceTree = SOURCE_ROOT; };
+		616FDEE125BF49EC00CCCAD5 /* GTXImageAndColorUtils.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = GTXImageAndColorUtils.mm; path = Classes/GTXImageAndColorUtils.mm; sourceTree = SOURCE_ROOT; };
+		616FDEE225BF49EC00CCCAD5 /* GTXXCUIElementQueryProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXXCUIElementQueryProxy.m; path = Classes/GTXXCUIElementQueryProxy.m; sourceTree = SOURCE_ROOT; };
+		616FDEE325BF49EC00CCCAD5 /* GTXExcludeListBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXExcludeListBlock.m; path = Classes/GTXExcludeListBlock.m; sourceTree = SOURCE_ROOT; };
+		616FDEE425BF49EC00CCCAD5 /* GTXElementReference.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXElementReference.h; path = Classes/GTXElementReference.h; sourceTree = SOURCE_ROOT; };
+		616FDEE525BF49EC00CCCAD5 /* NSObject+GTXAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "NSObject+GTXAdditions.mm"; path = "Classes/NSObject+GTXAdditions.mm"; sourceTree = SOURCE_ROOT; };
+		616FDEE625BF49EC00CCCAD5 /* GTXCheckResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXCheckResult.h; path = Classes/GTXCheckResult.h; sourceTree = SOURCE_ROOT; };
+		616FDF1125BF4ACA00CCCAD5 /* GTXTestApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = "GTXTestApp-Info.plist"; path = "Tests/Common/TestApp/GTXTestApp-Info.plist"; sourceTree = SOURCE_ROOT; };
+		616FDF1225BF4ACA00CCCAD5 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = Tests/Common/TestApp/LaunchScreen.storyboard; sourceTree = SOURCE_ROOT; };
+		616FDF1925BF4ADC00CCCAD5 /* GTXTestAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAppDelegate.m; path = Tests/Common/TestApp/Sources/GTXTestAppDelegate.m; sourceTree = SOURCE_ROOT; };
+		616FDF1A25BF4ADC00CCCAD5 /* GTXTestApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestApp.m; path = Tests/Common/TestApp/Sources/GTXTestApp.m; sourceTree = SOURCE_ROOT; };
+		616FDF1B25BF4ADC00CCCAD5 /* GTXTestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestViewController.m; path = Tests/Common/TestApp/Sources/GTXTestViewController.m; sourceTree = SOURCE_ROOT; };
+		616FDF1C25BF4ADC00CCCAD5 /* GTXTestStepperButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestStepperButton.h; path = Tests/Common/TestApp/Sources/GTXTestStepperButton.h; sourceTree = SOURCE_ROOT; };
+		616FDF1D25BF4ADC00CCCAD5 /* GTXTestAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestAppDelegate.h; path = Tests/Common/TestApp/Sources/GTXTestAppDelegate.h; sourceTree = SOURCE_ROOT; };
+		616FDF1E25BF4ADC00CCCAD5 /* GTXTestViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = GTXTestViewController.xib; path = Tests/Common/TestApp/Sources/GTXTestViewController.xib; sourceTree = SOURCE_ROOT; };
+		616FDF1F25BF4ADC00CCCAD5 /* GTXTestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestViewController.h; path = Tests/Common/TestApp/Sources/GTXTestViewController.h; sourceTree = SOURCE_ROOT; };
+		616FDF2025BF4ADC00CCCAD5 /* GTXTestStepperButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestStepperButton.m; path = Tests/Common/TestApp/Sources/GTXTestStepperButton.m; sourceTree = SOURCE_ROOT; };
+		616FDF3825BF4B7800CCCAD5 /* GTXReportTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXReportTests.m; path = Tests/GTXTests/UnitTests/GTXReportTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF3925BF4B7800CCCAD5 /* GTXChecksCollectionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXChecksCollectionTests.m; path = Tests/GTXTests/UnitTests/GTXChecksCollectionTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF3A25BF4B7800CCCAD5 /* GTXTestAccessibilityElements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestAccessibilityElements.h; path = Tests/GTXTests/UnitTests/GTXTestAccessibilityElements.h; sourceTree = SOURCE_ROOT; };
+		616FDF3B25BF4B7800CCCAD5 /* GTXToolkitSwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GTXToolkitSwiftTests.swift; path = Tests/GTXTests/UnitTests/GTXToolkitSwiftTests.swift; sourceTree = SOURCE_ROOT; };
+		616FDF3C25BF4B7800CCCAD5 /* GTXElementReferenceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXElementReferenceTests.m; path = Tests/GTXTests/UnitTests/GTXElementReferenceTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF3D25BF4B7800CCCAD5 /* GTXTestDynamicTypeCheckOptions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestDynamicTypeCheckOptions.m; path = Tests/GTXTests/UnitTests/GTXTestDynamicTypeCheckOptions.m; sourceTree = SOURCE_ROOT; };
+		616FDF3E25BF4B7800CCCAD5 /* GTXCheckResultTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXCheckResultTests.m; path = Tests/GTXTests/UnitTests/GTXCheckResultTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF3F25BF4B7800CCCAD5 /* GTXAccessibilityTreeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXAccessibilityTreeTests.m; path = Tests/GTXTests/UnitTests/GTXAccessibilityTreeTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF4025BF4B7800CCCAD5 /* GTXBaseTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXBaseTestCase.m; path = Tests/GTXTests/UnitTests/GTXBaseTestCase.m; sourceTree = SOURCE_ROOT; };
+		616FDF4125BF4B7800CCCAD5 /* GTXImageAndColorUtilsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXImageAndColorUtilsTests.m; path = Tests/GTXTests/UnitTests/GTXImageAndColorUtilsTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF4225BF4B7800CCCAD5 /* GTXTestAccessibilityElements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAccessibilityElements.m; path = Tests/GTXTests/UnitTests/GTXTestAccessibilityElements.m; sourceTree = SOURCE_ROOT; };
+		616FDF4325BF4B7800CCCAD5 /* GTXToolkitOOPTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = GTXToolkitOOPTests.mm; path = Tests/GTXTests/UnitTests/GTXToolkitOOPTests.mm; sourceTree = SOURCE_ROOT; };
+		616FDF4425BF4B7800CCCAD5 /* GTXBaseTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXBaseTestCase.h; path = Tests/GTXTests/UnitTests/GTXBaseTestCase.h; sourceTree = SOURCE_ROOT; };
+		616FDF4525BF4B7800CCCAD5 /* GTXElementResultCollectionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXElementResultCollectionTests.m; path = Tests/GTXTests/UnitTests/GTXElementResultCollectionTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF4625BF4B7800CCCAD5 /* GTXImageRGBADataTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = GTXImageRGBADataTests.mm; path = Tests/GTXTests/UnitTests/GTXImageRGBADataTests.mm; sourceTree = SOURCE_ROOT; };
+		616FDF4725BF4B7800CCCAD5 /* GTXTestSuiteTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestSuiteTests.m; path = Tests/GTXTests/UnitTests/GTXTestSuiteTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF4825BF4B7800CCCAD5 /* GTXToolKitTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXToolKitTests.m; path = Tests/GTXTests/UnitTests/GTXToolKitTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF4925BF4B7800CCCAD5 /* GTXAnalyticsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXAnalyticsTests.m; path = Tests/GTXTests/UnitTests/GTXAnalyticsTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF4A25BF4B7800CCCAD5 /* GTXTestDynamicTypeCheckOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestDynamicTypeCheckOptions.h; path = Tests/GTXTests/UnitTests/GTXTestDynamicTypeCheckOptions.h; sourceTree = SOURCE_ROOT; };
+		616FDF4B25BF4B7800CCCAD5 /* GTXResultTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXResultTests.m; path = Tests/GTXTests/UnitTests/GTXResultTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF4C25BF4B7800CCCAD5 /* GTXHierarchyResultCollectionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXHierarchyResultCollectionTests.m; path = Tests/GTXTests/UnitTests/GTXHierarchyResultCollectionTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF6725BF4BB400CCCAD5 /* GTXTestBaseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestBaseTest.h; path = Tests/GTXTests/FunctionalTests/GTXTestBaseTest.h; sourceTree = SOURCE_ROOT; };
+		616FDF6825BF4BB400CCCAD5 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanIgnoreElementsOnSpecificCheck.m; path = Tests/GTXTests/FunctionalTests/GTXTestGtxCanIgnoreElementsOnSpecificCheck.m; sourceTree = SOURCE_ROOT; };
+		616FDF6925BF4BB400CCCAD5 /* GTXTestAnalyticsCanBeDisabled.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAnalyticsCanBeDisabled.m; path = Tests/GTXTests/FunctionalTests/GTXTestAnalyticsCanBeDisabled.m; sourceTree = SOURCE_ROOT; };
+		616FDF6A25BF4BB400CCCAD5 /* GTXTestAnalyticsBaseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestAnalyticsBaseTest.h; path = Tests/GTXTests/FunctionalTests/GTXTestAnalyticsBaseTest.h; sourceTree = SOURCE_ROOT; };
+		616FDF6B25BF4BB400CCCAD5 /* GTXTestGtxCanWhitelistTestCases.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanWhitelistTestCases.m; path = Tests/GTXTests/FunctionalTests/GTXTestGtxCanWhitelistTestCases.m; sourceTree = SOURCE_ROOT; };
+		616FDF6C25BF4BB400CCCAD5 /* GTXTestFailingClassFailCheck.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestFailingClassFailCheck.m; path = Tests/GTXTests/FunctionalTests/GTXTestFailingClassFailCheck.m; sourceTree = SOURCE_ROOT; };
+		616FDF6D25BF4BB400CCCAD5 /* GTXTestGtxCanExcludeListTestCases.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanExcludeListTestCases.m; path = Tests/GTXTests/FunctionalTests/GTXTestGtxCanExcludeListTestCases.m; sourceTree = SOURCE_ROOT; };
+		616FDF6E25BF4BB400CCCAD5 /* GTXTestAnalyticsBaseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAnalyticsBaseTest.m; path = Tests/GTXTests/FunctionalTests/GTXTestAnalyticsBaseTest.m; sourceTree = SOURCE_ROOT; };
+		616FDF6F25BF4BB400CCCAD5 /* GTXTestGtxCanIgnoreElements.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanIgnoreElements.m; path = Tests/GTXTests/FunctionalTests/GTXTestGtxCanIgnoreElements.m; sourceTree = SOURCE_ROOT; };
+		616FDF7025BF4BB400CCCAD5 /* GTXTestGtxWorksForPassingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxWorksForPassingTests.m; path = Tests/GTXTests/FunctionalTests/GTXTestGtxWorksForPassingTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF7125BF4BB400CCCAD5 /* GTXTestAnalyticsIsTriggered.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestAnalyticsIsTriggered.m; path = Tests/GTXTests/FunctionalTests/GTXTestAnalyticsIsTriggered.m; sourceTree = SOURCE_ROOT; };
+		616FDF7225BF4BB400CCCAD5 /* GTXTestGtxCanDetectFailures.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanDetectFailures.m; path = Tests/GTXTests/FunctionalTests/GTXTestGtxCanDetectFailures.m; sourceTree = SOURCE_ROOT; };
+		616FDF7325BF4BB400CCCAD5 /* GTXTestGtxCanDetectFailuresInInheritedTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxCanDetectFailuresInInheritedTests.m; path = Tests/GTXTests/FunctionalTests/GTXTestGtxCanDetectFailuresInInheritedTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF7425BF4BB400CCCAD5 /* GTXTestBaseTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestBaseTest.m; path = Tests/GTXTests/FunctionalTests/GTXTestBaseTest.m; sourceTree = SOURCE_ROOT; };
+		616FDF7525BF4BB400CCCAD5 /* GTXTestGtxWithDefaultChecks.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestGtxWithDefaultChecks.m; path = Tests/GTXTests/FunctionalTests/GTXTestGtxWithDefaultChecks.m; sourceTree = SOURCE_ROOT; };
+		616FDF8E25BF4BF500CCCAD5 /* GTXStringUtilsTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = GTXStringUtilsTests.mm; path = Tests/GTXOOPTests/UnitTests/GTXStringUtilsTests.mm; sourceTree = SOURCE_ROOT; };
+		616FDF8F25BF4BF500CCCAD5 /* GTXToolkitTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = GTXToolkitTests.mm; path = Tests/GTXOOPTests/UnitTests/GTXToolkitTests.mm; sourceTree = SOURCE_ROOT; };
+		616FDF9025BF4BF500CCCAD5 /* GTXColorSwatchTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = GTXColorSwatchTests.mm; path = Tests/GTXOOPTests/UnitTests/GTXColorSwatchTests.mm; sourceTree = SOURCE_ROOT; };
+		616FDF9125BF4BF500CCCAD5 /* GTXTypesTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = GTXTypesTests.mm; path = Tests/GTXOOPTests/UnitTests/GTXTypesTests.mm; sourceTree = SOURCE_ROOT; };
+		616FDF9225BF4BF500CCCAD5 /* GTXUIElementTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = GTXUIElementTests.mm; path = Tests/GTXOOPTests/UnitTests/GTXUIElementTests.mm; sourceTree = SOURCE_ROOT; };
+		616FDF9325BF4C0300CCCAD5 /* GTXTestXCUIElementTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = GTXTestXCUIElementTests.m; path = Tests/GTXOOPTests/FunctionalTests/GTXTestXCUIElementTests.m; sourceTree = SOURCE_ROOT; };
+		616FDF9425BF4C1200CCCAD5 /* GTXTestIntegrationTestCase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = GTXTestIntegrationTestCase.m; path = Tests/GTXOOPTests/IntegrationTests/GTXTestIntegrationTestCase.m; sourceTree = SOURCE_ROOT; };
+		616FDF9525BF4C1200CCCAD5 /* GTXTestPassingIntegrationTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = GTXTestPassingIntegrationTest.m; path = Tests/GTXOOPTests/IntegrationTests/GTXTestPassingIntegrationTest.m; sourceTree = SOURCE_ROOT; };
+		616FDF9625BF4C1200CCCAD5 /* GTXTestIntegrationTestCase.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = GTXTestIntegrationTestCase.h; path = Tests/GTXOOPTests/IntegrationTests/GTXTestIntegrationTestCase.h; sourceTree = SOURCE_ROOT; };
+		616FDF9725BF4C1200CCCAD5 /* GTXTestFailingIntegrationTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = GTXTestFailingIntegrationTest.m; path = Tests/GTXOOPTests/IntegrationTests/GTXTestFailingIntegrationTest.m; sourceTree = SOURCE_ROOT; };
+		616FDF9825BF4C3B00CCCAD5 /* XCUIElement+GTXTestAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "XCUIElement+GTXTestAdditions.h"; path = "Tests/Common/OOPTestLib/XCUIElement+GTXTestAdditions.h"; sourceTree = SOURCE_ROOT; };
+		616FDF9A25BF4C3B00CCCAD5 /* XCUIElement+GTXTestAdditions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "XCUIElement+GTXTestAdditions.mm"; path = "Tests/Common/OOPTestLib/XCUIElement+GTXTestAdditions.mm"; sourceTree = SOURCE_ROOT; };
+		616FDFA425BF4CFE00CCCAD5 /* GTXOOPIntegrationTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GTXOOPIntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		616FDFC225BF4DAD00CCCAD5 /* gtx.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; name = gtx.proto; path = OOPClasses/Protos/gtx.proto; sourceTree = SOURCE_ROOT; };
+		616FDFC325BF4DC400CCCAD5 /* ui_element.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ui_element.h; path = OOPClasses/ui_element.h; sourceTree = SOURCE_ROOT; };
+		616FDFC425BF4DC400CCCAD5 /* localized_strings_manager.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = localized_strings_manager.cc; path = OOPClasses/localized_strings_manager.cc; sourceTree = SOURCE_ROOT; };
+		616FDFC525BF4DC400CCCAD5 /* check_result.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = check_result.cc; path = OOPClasses/check_result.cc; sourceTree = SOURCE_ROOT; };
+		616FDFC625BF4DC400CCCAD5 /* no_label_check.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = no_label_check.h; path = OOPClasses/no_label_check.h; sourceTree = SOURCE_ROOT; };
+		616FDFC725BF4DC400CCCAD5 /* parameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = parameters.h; path = OOPClasses/parameters.h; sourceTree = SOURCE_ROOT; };
+		616FDFC825BF4DC400CCCAD5 /* gtx_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gtx_types.h; path = OOPClasses/gtx_types.h; sourceTree = SOURCE_ROOT; };
+		616FDFC925BF4DC400CCCAD5 /* string_utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = string_utils.cc; path = OOPClasses/string_utils.cc; sourceTree = SOURCE_ROOT; };
+		616FDFCA25BF4DC400CCCAD5 /* accessibility_label_not_punctuated_check.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = accessibility_label_not_punctuated_check.h; path = OOPClasses/accessibility_label_not_punctuated_check.h; sourceTree = SOURCE_ROOT; };
+		616FDFCB25BF4DC400CCCAD5 /* parameters.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = parameters.cc; path = OOPClasses/parameters.cc; sourceTree = SOURCE_ROOT; };
+		616FDFCC25BF4DC400CCCAD5 /* image_color_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = image_color_utils.h; path = OOPClasses/image_color_utils.h; sourceTree = SOURCE_ROOT; };
+		616FDFCD25BF4DC400CCCAD5 /* contrast_swatch.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = contrast_swatch.cc; path = OOPClasses/contrast_swatch.cc; sourceTree = SOURCE_ROOT; };
+		616FDFCE25BF4DC400CCCAD5 /* error_message.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = error_message.cc; path = OOPClasses/error_message.cc; sourceTree = SOURCE_ROOT; };
+		616FDFCF25BF4DC400CCCAD5 /* toolkit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = toolkit.h; path = OOPClasses/toolkit.h; sourceTree = SOURCE_ROOT; };
+		616FDFD025BF4DC400CCCAD5 /* toolkit.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = toolkit.cc; path = OOPClasses/toolkit.cc; sourceTree = SOURCE_ROOT; };
+		616FDFD125BF4DC500CCCAD5 /* gtx_types.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gtx_types.cc; path = OOPClasses/gtx_types.cc; sourceTree = SOURCE_ROOT; };
+		616FDFD225BF4DC500CCCAD5 /* ui_element.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ui_element.cc; path = OOPClasses/ui_element.cc; sourceTree = SOURCE_ROOT; };
+		616FDFD325BF4DC500CCCAD5 /* contrast_check.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = contrast_check.cc; path = OOPClasses/contrast_check.cc; sourceTree = SOURCE_ROOT; };
+		616FDFD425BF4DC500CCCAD5 /* accessibility_label_not_punctuated_check.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = accessibility_label_not_punctuated_check.cc; path = OOPClasses/accessibility_label_not_punctuated_check.cc; sourceTree = SOURCE_ROOT; };
+		616FDFD525BF4DC500CCCAD5 /* contrast_swatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = contrast_swatch.h; path = OOPClasses/contrast_swatch.h; sourceTree = SOURCE_ROOT; };
+		616FDFD625BF4DC500CCCAD5 /* image_color_utils.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = image_color_utils.cc; path = OOPClasses/image_color_utils.cc; sourceTree = SOURCE_ROOT; };
+		616FDFD725BF4DC500CCCAD5 /* minimum_tappable_area_check.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = minimum_tappable_area_check.cc; path = OOPClasses/minimum_tappable_area_check.cc; sourceTree = SOURCE_ROOT; };
+		616FDFD825BF4DC500CCCAD5 /* check.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = check.cc; path = OOPClasses/check.cc; sourceTree = SOURCE_ROOT; };
+		616FDFD925BF4DC500CCCAD5 /* localized_strings_manager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = localized_strings_manager.h; path = OOPClasses/localized_strings_manager.h; sourceTree = SOURCE_ROOT; };
+		616FDFDA25BF4DC500CCCAD5 /* error_message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = error_message.h; path = OOPClasses/error_message.h; sourceTree = SOURCE_ROOT; };
+		616FDFDB25BF4DC500CCCAD5 /* check.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = check.h; path = OOPClasses/check.h; sourceTree = SOURCE_ROOT; };
+		616FDFDC25BF4DC500CCCAD5 /* minimum_tappable_area_check.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = minimum_tappable_area_check.h; path = OOPClasses/minimum_tappable_area_check.h; sourceTree = SOURCE_ROOT; };
+		616FDFDD25BF4DC500CCCAD5 /* contrast_check.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = contrast_check.h; path = OOPClasses/contrast_check.h; sourceTree = SOURCE_ROOT; };
+		616FDFDE25BF4DC500CCCAD5 /* check_result.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = check_result.h; path = OOPClasses/check_result.h; sourceTree = SOURCE_ROOT; };
+		616FDFDF25BF4DC500CCCAD5 /* string_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = string_utils.h; path = OOPClasses/string_utils.h; sourceTree = SOURCE_ROOT; };
+		616FDFE025BF4DC500CCCAD5 /* element_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = element_type.h; path = OOPClasses/element_type.h; sourceTree = SOURCE_ROOT; };
+		616FE00425BF4DF700CCCAD5 /* gtx.pb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gtx.pb.h; path = OOPClasses/Protos/gtx.pb.h; sourceTree = SOURCE_ROOT; };
+		616FE00525BF4DF700CCCAD5 /* gtx.pb.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gtx.pb.cc; path = OOPClasses/Protos/gtx.pb.cc; sourceTree = SOURCE_ROOT; };
+		616FE01125BF4E8600CCCAD5 /* GTXOOPFunctionalTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GTXOOPFunctionalTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		616FE02625BF4E9A00CCCAD5 /* GTXOOPUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GTXOOPUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		618E065D23FF412800BDD929 /* GTXResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXResult.h; path = Classes/GTXResult.h; sourceTree = SOURCE_ROOT; };
 		618E065E23FF412800BDD929 /* GTXResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXResult.m; path = Classes/GTXResult.m; sourceTree = SOURCE_ROOT; };
 		61A0C4DB2061896300DF0169 /* GTXiLibCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXiLibCore.m; path = Classes/GTXiLibCore.m; sourceTree = SOURCE_ROOT; };
@@ -189,7 +378,6 @@
 		61ABAE8E204A0B02006DBF0A /* GTXAnalyticsUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXAnalyticsUtils.h; path = Classes/GTXAnalyticsUtils.h; sourceTree = SOURCE_ROOT; };
 		61ABAE8F204A0B02006DBF0A /* GTXAnalytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXAnalytics.h; path = Classes/GTXAnalytics.h; sourceTree = SOURCE_ROOT; };
 		61ABAE90204A0B02006DBF0A /* GTXErrorReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXErrorReporter.h; path = Classes/GTXErrorReporter.h; sourceTree = SOURCE_ROOT; };
-		61ABAE91204A0B02006DBF0A /* GTXImageAndColorUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXImageAndColorUtils.m; path = Classes/GTXImageAndColorUtils.m; sourceTree = SOURCE_ROOT; };
 		61ABAE92204A0B03006DBF0A /* GTXTestSuite.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXTestSuite.m; path = Classes/GTXTestSuite.m; sourceTree = SOURCE_ROOT; };
 		61ABAE93204A0B03006DBF0A /* GTXAccessibilityTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXAccessibilityTree.h; path = Classes/GTXAccessibilityTree.h; sourceTree = SOURCE_ROOT; };
 		61ABAE94204A0B03006DBF0A /* GTXCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXCommon.h; path = Classes/GTXCommon.h; sourceTree = SOURCE_ROOT; };
@@ -203,7 +391,6 @@
 		61ABAE9D204A0B05006DBF0A /* NSError+GTXAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSError+GTXAdditions.m"; path = "Classes/NSError+GTXAdditions.m"; sourceTree = SOURCE_ROOT; };
 		61ABAE9E204A0B06006DBF0A /* GTXCheckBlock.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXCheckBlock.m; path = Classes/GTXCheckBlock.m; sourceTree = SOURCE_ROOT; };
 		61ABAE9F204A0B06006DBF0A /* GTXTestSuite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestSuite.h; path = Classes/GTXTestSuite.h; sourceTree = SOURCE_ROOT; };
-		61ABAEA0204A0B06006DBF0A /* GTXToolKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXToolKit.m; path = Classes/GTXToolKit.m; sourceTree = SOURCE_ROOT; };
 		61ABAEA1204A0B06006DBF0A /* GTXTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXTestCase.h; path = Classes/GTXTestCase.h; sourceTree = SOURCE_ROOT; };
 		61ABAEA2204A0B06006DBF0A /* GTXImageAndColorUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXImageAndColorUtils.h; path = Classes/GTXImageAndColorUtils.h; sourceTree = SOURCE_ROOT; };
 		61ABAEA4204A0B07006DBF0A /* GTXChecksCollection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXChecksCollection.m; path = Classes/GTXChecksCollection.m; sourceTree = SOURCE_ROOT; };
@@ -215,6 +402,8 @@
 		61ABAEAB204A0B09006DBF0A /* GTXToolKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXToolKit.h; path = Classes/GTXToolKit.h; sourceTree = SOURCE_ROOT; };
 		61ABAEAC204A0B0A006DBF0A /* GTXImageRGBAData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GTXImageRGBAData.m; path = Classes/GTXImageRGBAData.m; sourceTree = SOURCE_ROOT; };
 		61B7F4A2204A15D30062DF65 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
+		61CC44AE25C0CAE600CF632A /* GTXUITestBaseTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GTXUITestBaseTest.h; path = Tests/Common/OOPTestLib/GTXUITestBaseTest.h; sourceTree = SOURCE_ROOT; };
+		61CC44AF25C0CAE600CF632A /* GTXUITestBaseTest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = GTXUITestBaseTest.mm; path = Tests/Common/OOPTestLib/GTXUITestBaseTest.mm; sourceTree = SOURCE_ROOT; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -247,54 +436,38 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		616FDFA125BF4CFE00CCCAD5 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		616FE00E25BF4E8600CCCAD5 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				616FE01625BF4E8600CCCAD5 /* GTXiLib.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		616FE02325BF4E9A00CCCAD5 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				6121D2CA25CDF4FF0081FAE0 /* CoreGraphics.framework in Frameworks */,
+				6121D2C825CDF4F70081FAE0 /* UIKit.framework in Frameworks */,
+				616FE02B25BF4E9A00CCCAD5 /* GTXiLib.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-		61284DAE211E3F8300F8FF29 /* TestApp */ = {
-			isa = PBXGroup;
-			children = (
-				61284DD0211E3FF400F8FF29 /* GTXTestApp-Info.plist */,
-				61284DCA211E3FE400F8FF29 /* GTXTestApp.m */,
-				61284DC9211E3FE300F8FF29 /* GTXTestAppDelegate.h */,
-				61284DC5211E3FE200F8FF29 /* GTXTestAppDelegate.m */,
-				61284DC8211E3FE300F8FF29 /* GTXTestStepperButton.h */,
-				61284DC6211E3FE200F8FF29 /* GTXTestStepperButton.m */,
-				61284DC7211E3FE300F8FF29 /* GTXTestViewController.h */,
-				61284DC3211E3FE100F8FF29 /* GTXTestViewController.m */,
-				61284DC4211E3FE200F8FF29 /* GTXTestViewController.xib */,
-			);
-			path = TestApp;
-			sourceTree = "<group>";
-		};
-		61284DE1211E442700F8FF29 /* FunctionalTests */ = {
-			isa = PBXGroup;
-			children = (
-				61284DF4211E447C00F8FF29 /* GTXTestAnalyticsBaseTest.h */,
-				61284DEC211E447900F8FF29 /* GTXTestAnalyticsBaseTest.m */,
-				61284DF5211E447C00F8FF29 /* GTXTestAnalyticsCanBeDisabled.m */,
-				61284DF3211E447C00F8FF29 /* GTXTestAnalyticsIsTriggered.m */,
-				61284DF7211E447D00F8FF29 /* GTXTestBaseTest.h */,
-				61284DF1211E447B00F8FF29 /* GTXTestBaseTest.m */,
-				61284DEB211E447900F8FF29 /* GTXTestFailingClassFailCheck.m */,
-				61284DED211E447900F8FF29 /* GTXTestGtxCanBlacklistTestCases.m */,
-				61284DF8211E447D00F8FF29 /* GTXTestGtxCanDetectFailures.m */,
-				61284DEE211E447A00F8FF29 /* GTXTestGtxCanDetectFailuresInInheritedTests.m */,
-				61284DEF211E447A00F8FF29 /* GTXTestGtxCanIgnoreElements.m */,
-				61284DF6211E447D00F8FF29 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m */,
-				61284DF2211E447C00F8FF29 /* GTXTestGtxCanWhitelistTestCases.m */,
-				61284DF0211E447A00F8FF29 /* GTXTestGtxWithDefaultChecks.m */,
-				61284DEA211E447800F8FF29 /* GTXTestGtxWorksForPassingTests.m */,
-			);
-			path = FunctionalTests;
-			sourceTree = "<group>";
-		};
 		613C3F37204A09E7007D44A8 = {
 			isa = PBXGroup;
 			children = (
 				613C3F43204A09E8007D44A8 /* GTXiLib */,
-				61BC5526204E2736004D2FB9 /* GTXiUnitTests */,
-				61284DAE211E3F8300F8FF29 /* TestApp */,
-				61284DE1211E442700F8FF29 /* FunctionalTests */,
 				613C3F42204A09E8007D44A8 /* Products */,
 				61B7F4A1204A15D30062DF65 /* Frameworks */,
 			);
@@ -307,6 +480,9 @@
 				6115E786204F5BA2003E32F9 /* GTXiUnitTests.xctest */,
 				61284DAD211E3F8300F8FF29 /* TestApp.app */,
 				61284DE0211E442700F8FF29 /* FunctionalTests.xctest */,
+				616FDFA425BF4CFE00CCCAD5 /* GTXOOPIntegrationTests.xctest */,
+				616FE01125BF4E8600CCCAD5 /* GTXOOPFunctionalTests.xctest */,
+				616FE02625BF4E9A00CCCAD5 /* GTXOOPUnitTests.xctest */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -314,37 +490,255 @@
 		613C3F43204A09E8007D44A8 /* GTXiLib */ = {
 			isa = PBXGroup;
 			children = (
+				616FDFC025BF4D7E00CCCAD5 /* OOPClasses */,
 				61ABAE8D204A0AF1006DBF0A /* Classes */,
 				61ABAE8A204A0AA3006DBF0A /* Info.plist */,
+				616FDF0B25BF4A0800CCCAD5 /* Tests */,
 			);
 			path = GTXiLib;
 			sourceTree = "<group>";
 		};
+		616FDF0B25BF4A0800CCCAD5 /* Tests */ = {
+			isa = PBXGroup;
+			children = (
+				616FDF0E25BF4A3C00CCCAD5 /* GTXOOPTests */,
+				616FDF0D25BF4A3300CCCAD5 /* GTXTests */,
+				616FDF0C25BF4A2200CCCAD5 /* Common */,
+			);
+			name = Tests;
+			sourceTree = "<group>";
+		};
+		616FDF0C25BF4A2200CCCAD5 /* Common */ = {
+			isa = PBXGroup;
+			children = (
+				616FDF1025BF4A6300CCCAD5 /* TestApp */,
+				616FDF0F25BF4A5600CCCAD5 /* OOPTestLib */,
+			);
+			name = Common;
+			sourceTree = "<group>";
+		};
+		616FDF0D25BF4A3300CCCAD5 /* GTXTests */ = {
+			isa = PBXGroup;
+			children = (
+				616FDF3325BF4B5100CCCAD5 /* FunctionalTests */,
+				616FDF3225BF4B4B00CCCAD5 /* UnitTests */,
+			);
+			name = GTXTests;
+			sourceTree = "<group>";
+		};
+		616FDF0E25BF4A3C00CCCAD5 /* GTXOOPTests */ = {
+			isa = PBXGroup;
+			children = (
+				616FDF8D25BF4BDB00CCCAD5 /* IntegrationTests */,
+				616FDF8C25BF4BD300CCCAD5 /* FunctionalTests */,
+				616FDF8B25BF4BCC00CCCAD5 /* UnitTests */,
+			);
+			name = GTXOOPTests;
+			sourceTree = "<group>";
+		};
+		616FDF0F25BF4A5600CCCAD5 /* OOPTestLib */ = {
+			isa = PBXGroup;
+			children = (
+				61CC44AE25C0CAE600CF632A /* GTXUITestBaseTest.h */,
+				61CC44AF25C0CAE600CF632A /* GTXUITestBaseTest.mm */,
+				616FDF9825BF4C3B00CCCAD5 /* XCUIElement+GTXTestAdditions.h */,
+				616FDF9A25BF4C3B00CCCAD5 /* XCUIElement+GTXTestAdditions.mm */,
+			);
+			name = OOPTestLib;
+			sourceTree = "<group>";
+		};
+		616FDF1025BF4A6300CCCAD5 /* TestApp */ = {
+			isa = PBXGroup;
+			children = (
+				616FDF1A25BF4ADC00CCCAD5 /* GTXTestApp.m */,
+				616FDF1D25BF4ADC00CCCAD5 /* GTXTestAppDelegate.h */,
+				616FDF1925BF4ADC00CCCAD5 /* GTXTestAppDelegate.m */,
+				616FDF1C25BF4ADC00CCCAD5 /* GTXTestStepperButton.h */,
+				616FDF2025BF4ADC00CCCAD5 /* GTXTestStepperButton.m */,
+				616FDF1F25BF4ADC00CCCAD5 /* GTXTestViewController.h */,
+				616FDF1B25BF4ADC00CCCAD5 /* GTXTestViewController.m */,
+				616FDF1E25BF4ADC00CCCAD5 /* GTXTestViewController.xib */,
+				616FDF1125BF4ACA00CCCAD5 /* GTXTestApp-Info.plist */,
+				616FDF1225BF4ACA00CCCAD5 /* LaunchScreen.storyboard */,
+			);
+			name = TestApp;
+			sourceTree = "<group>";
+		};
+		616FDF3225BF4B4B00CCCAD5 /* UnitTests */ = {
+			isa = PBXGroup;
+			children = (
+				616FDF3F25BF4B7800CCCAD5 /* GTXAccessibilityTreeTests.m */,
+				616FDF4925BF4B7800CCCAD5 /* GTXAnalyticsTests.m */,
+				616FDF4425BF4B7800CCCAD5 /* GTXBaseTestCase.h */,
+				616FDF4025BF4B7800CCCAD5 /* GTXBaseTestCase.m */,
+				616FDF3E25BF4B7800CCCAD5 /* GTXCheckResultTests.m */,
+				616FDF3925BF4B7800CCCAD5 /* GTXChecksCollectionTests.m */,
+				616FDF3C25BF4B7800CCCAD5 /* GTXElementReferenceTests.m */,
+				616FDF4525BF4B7800CCCAD5 /* GTXElementResultCollectionTests.m */,
+				616FDF4C25BF4B7800CCCAD5 /* GTXHierarchyResultCollectionTests.m */,
+				616FDF4125BF4B7800CCCAD5 /* GTXImageAndColorUtilsTests.m */,
+				616FDF4625BF4B7800CCCAD5 /* GTXImageRGBADataTests.mm */,
+				616FDF3825BF4B7800CCCAD5 /* GTXReportTests.m */,
+				616FDF4B25BF4B7800CCCAD5 /* GTXResultTests.m */,
+				616FDF3A25BF4B7800CCCAD5 /* GTXTestAccessibilityElements.h */,
+				616FDF4225BF4B7800CCCAD5 /* GTXTestAccessibilityElements.m */,
+				616FDF4A25BF4B7800CCCAD5 /* GTXTestDynamicTypeCheckOptions.h */,
+				616FDF3D25BF4B7800CCCAD5 /* GTXTestDynamicTypeCheckOptions.m */,
+				616FDF4725BF4B7800CCCAD5 /* GTXTestSuiteTests.m */,
+				616FDF4325BF4B7800CCCAD5 /* GTXToolkitOOPTests.mm */,
+				616FDF3B25BF4B7800CCCAD5 /* GTXToolkitSwiftTests.swift */,
+				616FDF4825BF4B7800CCCAD5 /* GTXToolKitTests.m */,
+			);
+			name = UnitTests;
+			sourceTree = "<group>";
+		};
+		616FDF3325BF4B5100CCCAD5 /* FunctionalTests */ = {
+			isa = PBXGroup;
+			children = (
+				616FDF6A25BF4BB400CCCAD5 /* GTXTestAnalyticsBaseTest.h */,
+				616FDF6E25BF4BB400CCCAD5 /* GTXTestAnalyticsBaseTest.m */,
+				616FDF6925BF4BB400CCCAD5 /* GTXTestAnalyticsCanBeDisabled.m */,
+				616FDF7125BF4BB400CCCAD5 /* GTXTestAnalyticsIsTriggered.m */,
+				616FDF6725BF4BB400CCCAD5 /* GTXTestBaseTest.h */,
+				616FDF7425BF4BB400CCCAD5 /* GTXTestBaseTest.m */,
+				616FDF6C25BF4BB400CCCAD5 /* GTXTestFailingClassFailCheck.m */,
+				616FDF7225BF4BB400CCCAD5 /* GTXTestGtxCanDetectFailures.m */,
+				616FDF7325BF4BB400CCCAD5 /* GTXTestGtxCanDetectFailuresInInheritedTests.m */,
+				616FDF6D25BF4BB400CCCAD5 /* GTXTestGtxCanExcludeListTestCases.m */,
+				616FDF6F25BF4BB400CCCAD5 /* GTXTestGtxCanIgnoreElements.m */,
+				616FDF6825BF4BB400CCCAD5 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m */,
+				616FDF6B25BF4BB400CCCAD5 /* GTXTestGtxCanWhitelistTestCases.m */,
+				616FDF7525BF4BB400CCCAD5 /* GTXTestGtxWithDefaultChecks.m */,
+				616FDF7025BF4BB400CCCAD5 /* GTXTestGtxWorksForPassingTests.m */,
+			);
+			name = FunctionalTests;
+			sourceTree = "<group>";
+		};
+		616FDF8B25BF4BCC00CCCAD5 /* UnitTests */ = {
+			isa = PBXGroup;
+			children = (
+				616FDF9025BF4BF500CCCAD5 /* GTXColorSwatchTests.mm */,
+				616FDF8E25BF4BF500CCCAD5 /* GTXStringUtilsTests.mm */,
+				616FDF8F25BF4BF500CCCAD5 /* GTXToolkitTests.mm */,
+				616FDF9125BF4BF500CCCAD5 /* GTXTypesTests.mm */,
+				616FDF9225BF4BF500CCCAD5 /* GTXUIElementTests.mm */,
+			);
+			name = UnitTests;
+			sourceTree = "<group>";
+		};
+		616FDF8C25BF4BD300CCCAD5 /* FunctionalTests */ = {
+			isa = PBXGroup;
+			children = (
+				616FDF9325BF4C0300CCCAD5 /* GTXTestXCUIElementTests.m */,
+			);
+			name = FunctionalTests;
+			sourceTree = "<group>";
+		};
+		616FDF8D25BF4BDB00CCCAD5 /* IntegrationTests */ = {
+			isa = PBXGroup;
+			children = (
+				616FDF9725BF4C1200CCCAD5 /* GTXTestFailingIntegrationTest.m */,
+				616FDF9625BF4C1200CCCAD5 /* GTXTestIntegrationTestCase.h */,
+				616FDF9425BF4C1200CCCAD5 /* GTXTestIntegrationTestCase.m */,
+				616FDF9525BF4C1200CCCAD5 /* GTXTestPassingIntegrationTest.m */,
+			);
+			name = IntegrationTests;
+			sourceTree = "<group>";
+		};
+		616FDFC025BF4D7E00CCCAD5 /* OOPClasses */ = {
+			isa = PBXGroup;
+			children = (
+				616FDFD425BF4DC500CCCAD5 /* accessibility_label_not_punctuated_check.cc */,
+				616FDFCA25BF4DC400CCCAD5 /* accessibility_label_not_punctuated_check.h */,
+				616FDFC525BF4DC400CCCAD5 /* check_result.cc */,
+				616FDFDE25BF4DC500CCCAD5 /* check_result.h */,
+				616FDFD825BF4DC500CCCAD5 /* check.cc */,
+				616FDFDB25BF4DC500CCCAD5 /* check.h */,
+				616FDFD325BF4DC500CCCAD5 /* contrast_check.cc */,
+				616FDFDD25BF4DC500CCCAD5 /* contrast_check.h */,
+				616FDFCD25BF4DC400CCCAD5 /* contrast_swatch.cc */,
+				616FDFD525BF4DC500CCCAD5 /* contrast_swatch.h */,
+				616FDFE025BF4DC500CCCAD5 /* element_type.h */,
+				616FDFCE25BF4DC400CCCAD5 /* error_message.cc */,
+				616FDFDA25BF4DC500CCCAD5 /* error_message.h */,
+				616FDFD125BF4DC500CCCAD5 /* gtx_types.cc */,
+				616FDFC825BF4DC400CCCAD5 /* gtx_types.h */,
+				616FDFD625BF4DC500CCCAD5 /* image_color_utils.cc */,
+				616FDFCC25BF4DC400CCCAD5 /* image_color_utils.h */,
+				616FDFC425BF4DC400CCCAD5 /* localized_strings_manager.cc */,
+				616FDFD925BF4DC500CCCAD5 /* localized_strings_manager.h */,
+				616FDFD725BF4DC500CCCAD5 /* minimum_tappable_area_check.cc */,
+				616FDFDC25BF4DC500CCCAD5 /* minimum_tappable_area_check.h */,
+				616FDFC625BF4DC400CCCAD5 /* no_label_check.h */,
+				616FDFCB25BF4DC400CCCAD5 /* parameters.cc */,
+				616FDFC725BF4DC400CCCAD5 /* parameters.h */,
+				616FDFC925BF4DC400CCCAD5 /* string_utils.cc */,
+				616FDFDF25BF4DC500CCCAD5 /* string_utils.h */,
+				616FDFD025BF4DC400CCCAD5 /* toolkit.cc */,
+				616FDFCF25BF4DC400CCCAD5 /* toolkit.h */,
+				616FDFD225BF4DC500CCCAD5 /* ui_element.cc */,
+				616FDFC325BF4DC400CCCAD5 /* ui_element.h */,
+				616FDFC125BF4D8D00CCCAD5 /* Protos */,
+			);
+			name = OOPClasses;
+			sourceTree = "<group>";
+		};
+		616FDFC125BF4D8D00CCCAD5 /* Protos */ = {
+			isa = PBXGroup;
+			children = (
+				616FE00525BF4DF700CCCAD5 /* gtx.pb.cc */,
+				616FE00425BF4DF700CCCAD5 /* gtx.pb.h */,
+				616FDFC225BF4DAD00CCCAD5 /* gtx.proto */,
+			);
+			name = Protos;
+			sourceTree = "<group>";
+		};
 		61ABAE8D204A0AF1006DBF0A /* Classes */ = {
 			isa = PBXGroup;
 			children = (
+				616FDEE625BF49EC00CCCAD5 /* GTXCheckResult.h */,
+				616FDED325BF49EC00CCCAD5 /* GTXCheckResult.m */,
+				616FDEE425BF49EC00CCCAD5 /* GTXElementReference.h */,
+				616FDEDB25BF49EC00CCCAD5 /* GTXElementReference.m */,
+				616FDECD25BF49EB00CCCAD5 /* GTXElementResultCollection.h */,
+				616FDEE025BF49EC00CCCAD5 /* GTXElementResultCollection.m */,
+				616FDED525BF49EC00CCCAD5 /* GTXExcludeListBlock.h */,
+				616FDEE325BF49EC00CCCAD5 /* GTXExcludeListBlock.m */,
+				616FDED025BF49EB00CCCAD5 /* GTXExcludeListFactory.h */,
+				616FDEDD25BF49EC00CCCAD5 /* GTXExcludeListFactory.m */,
+				616FDECB25BF49EB00CCCAD5 /* GTXExcludeListing.h */,
+				616FDED925BF49EC00CCCAD5 /* GTXHierarchyResultCollection.h */,
+				616FDEDC25BF49EC00CCCAD5 /* GTXHierarchyResultCollection.m */,
+				616FDEE125BF49EC00CCCAD5 /* GTXImageAndColorUtils.mm */,
+				616FDED225BF49EB00CCCAD5 /* GTXImageRGBAData+GTXOOPAdditions.h */,
+				616FDEC725BF49EB00CCCAD5 /* GTXImageRGBAData+GTXOOPAdditions.mm */,
+				616FDECC25BF49EB00CCCAD5 /* GTXSwizzler.h */,
+				616FDEC925BF49EB00CCCAD5 /* GTXSwizzler.m */,
+				616FDECF25BF49EB00CCCAD5 /* GTXToolKit.mm */,
+				616FDED425BF49EC00CCCAD5 /* GTXToolKit+GTXOOPAdditions.h */,
+				616FDECE25BF49EB00CCCAD5 /* GTXXCUIApplicationProxy.h */,
+				616FDEDA25BF49EC00CCCAD5 /* GTXXCUIApplicationProxy.m */,
+				616FDEC825BF49EB00CCCAD5 /* GTXXCUIElementProxy.h */,
+				616FDED725BF49EC00CCCAD5 /* GTXXCUIElementProxy.m */,
+				616FDECA25BF49EB00CCCAD5 /* GTXXCUIElementQueryProxy.h */,
+				616FDEE225BF49EC00CCCAD5 /* GTXXCUIElementQueryProxy.m */,
+				616FDED625BF49EC00CCCAD5 /* NSObject+GTXAdditions.h */,
+				616FDEE525BF49EC00CCCAD5 /* NSObject+GTXAdditions.mm */,
+				616FDEDE25BF49EC00CCCAD5 /* NSString+GTXAdditions.h */,
+				616FDEDF25BF49EC00CCCAD5 /* NSString+GTXAdditions.mm */,
+				616FDED125BF49EB00CCCAD5 /* UIColor+GTXOOPAdditions.h */,
+				616FDED825BF49EC00CCCAD5 /* UIColor+GTXOOPAdditions.mm */,
 				618E065D23FF412800BDD929 /* GTXResult.h */,
 				618E065E23FF412800BDD929 /* GTXResult.m */,
 				6133087723FF2F53003F8D41 /* GTXError.h */,
 				6133087A23FF2F53003F8D41 /* GTXError.m */,
 				6133088023FF2F53003F8D41 /* GTXReport.h */,
 				6133087C23FF2F53003F8D41 /* GTXReport.m */,
-				6133087D23FF2F53003F8D41 /* GTXSnapshotBuffer.h */,
-				6133087923FF2F53003F8D41 /* GTXSnapshotBuffer.m */,
-				6133087F23FF2F53003F8D41 /* GTXSnapshotContainer.h */,
-				6133087823FF2F53003F8D41 /* GTXSnapshotContainer.m */,
 				6133087623FF2F53003F8D41 /* UIColor+GTXAdditions.h */,
 				6133087523FF2F53003F8D41 /* UIColor+GTXAdditions.m */,
-				6133086E23FF2F39003F8D41 /* GTXArtifactCollector.h */,
-				6133086B23FF2F39003F8D41 /* GTXArtifactCollector.m */,
-				6133086F23FF2F39003F8D41 /* GTXArtifactImplementing.h */,
-				6133086C23FF2F39003F8D41 /* GTXArtifactProcessor.h */,
-				6133086D23FF2F39003F8D41 /* GTXArtifactProcessor.m */,
 				61A0C4DC2061896300DF0169 /* GTXiLib.h */,
 				61A0C4DD2061896300DF0169 /* GTXiLibCore.h */,
 				61A0C4DB2061896300DF0169 /* GTXiLibCore.m */,
-				61284E08211E45C500F8FF29 /* GTXBlacklistFactory.h */,
-				61284E09211E45C600F8FF29 /* GTXBlacklistFactory.m */,
 				61ABAE93204A0B03006DBF0A /* GTXAccessibilityTree.h */,
 				61ABAE9A204A0B04006DBF0A /* GTXAccessibilityTree.m */,
 				61ABAE8F204A0B02006DBF0A /* GTXAnalytics.h */,
@@ -352,9 +746,6 @@
 				61ABAE8E204A0B02006DBF0A /* GTXAnalyticsUtils.h */,
 				61ABAE96204A0B03006DBF0A /* GTXAnalyticsUtils.m */,
 				61ABAE9B204A0B05006DBF0A /* GTXAssertions.h */,
-				61284DD3211E42CE00F8FF29 /* GTXBlacklistBlock.h */,
-				61284DD2211E42CD00F8FF29 /* GTXBlacklistBlock.m */,
-				61284DD4211E42CE00F8FF29 /* GTXBlacklisting.h */,
 				61ABAEA9204A0B09006DBF0A /* GTXCheckBlock.h */,
 				61ABAE9E204A0B06006DBF0A /* GTXCheckBlock.m */,
 				610CA3FB204DFC76008BAAA1 /* GTXPluginXCTestCase.h */,
@@ -366,7 +757,6 @@
 				61ABAE90204A0B02006DBF0A /* GTXErrorReporter.h */,
 				61ABAEAA204A0B09006DBF0A /* GTXErrorReporter.m */,
 				61ABAEA2204A0B06006DBF0A /* GTXImageAndColorUtils.h */,
-				61ABAE91204A0B02006DBF0A /* GTXImageAndColorUtils.m */,
 				61ABAE9C204A0B05006DBF0A /* GTXImageRGBAData.h */,
 				61ABAEAC204A0B0A006DBF0A /* GTXImageRGBAData.m */,
 				61ABAE95204A0B03006DBF0A /* GTXLogging.h */,
@@ -377,7 +767,6 @@
 				61ABAE9F204A0B06006DBF0A /* GTXTestSuite.h */,
 				61ABAE92204A0B03006DBF0A /* GTXTestSuite.m */,
 				61ABAEAB204A0B09006DBF0A /* GTXToolKit.h */,
-				61ABAEA0204A0B06006DBF0A /* GTXToolKit.m */,
 				61ABAEA6204A0B08006DBF0A /* NSError+GTXAdditions.h */,
 				61ABAE9D204A0B05006DBF0A /* NSError+GTXAdditions.m */,
 			);
@@ -387,28 +776,13 @@
 		61B7F4A1204A15D30062DF65 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				6121D2C925CDF4FF0081FAE0 /* CoreGraphics.framework */,
+				6121D2C725CDF4F70081FAE0 /* UIKit.framework */,
 				61B7F4A2204A15D30062DF65 /* XCTest.framework */,
 			);
 			name = Frameworks;
 			sourceTree = "<group>";
 		};
-		61BC5526204E2736004D2FB9 /* GTXiUnitTests */ = {
-			isa = PBXGroup;
-			children = (
-				6115E794204F5BC7003E32F9 /* GTXAccessibilityTreeTests.m */,
-				6115E795204F5BC8003E32F9 /* GTXAnalyticsTests.m */,
-				6115E797204F5BC8003E32F9 /* GTXBaseTestCase.h */,
-				6115E79A204F5BC9003E32F9 /* GTXBaseTestCase.m */,
-				6115E793204F5BC7003E32F9 /* GTXChecksCollectionTests.m */,
-				6115E799204F5BC8003E32F9 /* GTXImageAndColorUtilsTests.m */,
-				6115E796204F5BC8003E32F9 /* GTXTestAccessibilityElements.h */,
-				6115E798204F5BC8003E32F9 /* GTXTestAccessibilityElements.m */,
-				6115E792204F5BC6003E32F9 /* GTXTestSuiteTests.m */,
-				6115E791204F5BC6003E32F9 /* GTXToolKitTests.m */,
-			);
-			path = GTXiUnitTests;
-			sourceTree = "<group>";
-		};
 /* End PBXGroup section */
 
 /* Begin PBXHeadersBuildPhase section */
@@ -416,38 +790,63 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				616FDFFA25BF4DC500CCCAD5 /* minimum_tappable_area_check.h in Headers */,
+				616FDFE625BF4DC500CCCAD5 /* gtx_types.h in Headers */,
+				616FDEEB25BF49EC00CCCAD5 /* GTXExcludeListing.h in Headers */,
+				616FDFE825BF4DC500CCCAD5 /* accessibility_label_not_punctuated_check.h in Headers */,
 				61284DDB211E437800F8FF29 /* GTXTestEnvironment.h in Headers */,
-				6133087423FF2F39003F8D41 /* GTXArtifactImplementing.h in Headers */,
 				61ABAEB5204A0B0B006DBF0A /* GTXAccessibilityTree.h in Headers */,
 				61ABAECD204A0B0B006DBF0A /* GTXToolKit.h in Headers */,
+				616FDFF925BF4DC500CCCAD5 /* check.h in Headers */,
+				616FDEEC25BF49EC00CCCAD5 /* GTXSwizzler.h in Headers */,
+				616FDFE425BF4DC500CCCAD5 /* no_label_check.h in Headers */,
+				616FDEF225BF49EC00CCCAD5 /* GTXImageRGBAData+GTXOOPAdditions.h in Headers */,
+				616FDFED25BF4DC500CCCAD5 /* toolkit.h in Headers */,
+				616FDFE125BF4DC500CCCAD5 /* ui_element.h in Headers */,
+				616FDF0625BF49EC00CCCAD5 /* GTXCheckResult.h in Headers */,
 				61ABAEC8204A0B0B006DBF0A /* NSError+GTXAdditions.h in Headers */,
 				6133088323FF2F53003F8D41 /* GTXError.h in Headers */,
+				616FDEE825BF49EC00CCCAD5 /* GTXXCUIElementProxy.h in Headers */,
 				61ABAEC4204A0B0B006DBF0A /* GTXImageAndColorUtils.h in Headers */,
 				61ABAEB6204A0B0B006DBF0A /* GTXCommon.h in Headers */,
 				61ABAEBD204A0B0B006DBF0A /* GTXAssertions.h in Headers */,
 				610CA3FD204DFC76008BAAA1 /* GTXPluginXCTestCase.h in Headers */,
 				61ABAECB204A0B0B006DBF0A /* GTXCheckBlock.h in Headers */,
-				61284DD6211E42CF00F8FF29 /* GTXBlacklistBlock.h in Headers */,
 				6133088223FF2F53003F8D41 /* UIColor+GTXAdditions.h in Headers */,
+				616FDFF725BF4DC500CCCAD5 /* localized_strings_manager.h in Headers */,
 				61ABAEB9204A0B0B006DBF0A /* GTXChecking.h in Headers */,
-				61284E0A211E45C600F8FF29 /* GTXBlacklistFactory.h in Headers */,
+				616FDEF925BF49EC00CCCAD5 /* GTXHierarchyResultCollection.h in Headers */,
 				6133088C23FF2F53003F8D41 /* GTXReport.h in Headers */,
-				6133088923FF2F53003F8D41 /* GTXSnapshotBuffer.h in Headers */,
 				61ABAEBE204A0B0B006DBF0A /* GTXImageRGBAData.h in Headers */,
-				6133087123FF2F39003F8D41 /* GTXArtifactProcessor.h in Headers */,
+				616FDFFC25BF4DC500CCCAD5 /* check_result.h in Headers */,
+				616FDFEA25BF4DC500CCCAD5 /* image_color_utils.h in Headers */,
+				616FDEF625BF49EC00CCCAD5 /* NSObject+GTXAdditions.h in Headers */,
 				618E065F23FF412800BDD929 /* GTXResult.h in Headers */,
+				616FDFE525BF4DC500CCCAD5 /* parameters.h in Headers */,
+				616FDEF025BF49EC00CCCAD5 /* GTXExcludeListFactory.h in Headers */,
+				616FDFF325BF4DC500CCCAD5 /* contrast_swatch.h in Headers */,
 				61ABAEB2204A0B0B006DBF0A /* GTXErrorReporter.h in Headers */,
 				61ABAEC3204A0B0B006DBF0A /* GTXTestCase.h in Headers */,
-				6133088B23FF2F53003F8D41 /* GTXSnapshotContainer.h in Headers */,
+				616FDF0425BF49EC00CCCAD5 /* GTXElementReference.h in Headers */,
+				616FDFF825BF4DC500CCCAD5 /* error_message.h in Headers */,
+				616FDEFE25BF49EC00CCCAD5 /* NSString+GTXAdditions.h in Headers */,
 				61ABAEB1204A0B0B006DBF0A /* GTXAnalytics.h in Headers */,
-				61284DD7211E42CF00F8FF29 /* GTXBlacklisting.h in Headers */,
 				61A0C4E02061896300DF0169 /* GTXiLibCore.h in Headers */,
+				616FDEF125BF49EC00CCCAD5 /* UIColor+GTXOOPAdditions.h in Headers */,
+				616FDFFB25BF4DC500CCCAD5 /* contrast_check.h in Headers */,
+				616FE00625BF4DF700CCCAD5 /* gtx.pb.h in Headers */,
 				61A0C4DF2061896300DF0169 /* GTXiLib.h in Headers */,
 				61ABAECA204A0B0B006DBF0A /* GTXChecksCollection.h in Headers */,
+				616FDEED25BF49EC00CCCAD5 /* GTXElementResultCollection.h in Headers */,
+				616FDFFE25BF4DC500CCCAD5 /* element_type.h in Headers */,
+				616FDEF425BF49EC00CCCAD5 /* GTXToolKit+GTXOOPAdditions.h in Headers */,
+				616FDEEA25BF49EC00CCCAD5 /* GTXXCUIElementQueryProxy.h in Headers */,
 				61ABAEC1204A0B0B006DBF0A /* GTXTestSuite.h in Headers */,
+				616FDEEE25BF49EC00CCCAD5 /* GTXXCUIApplicationProxy.h in Headers */,
 				61ABAEB7204A0B0B006DBF0A /* GTXLogging.h in Headers */,
+				616FDFFD25BF4DC500CCCAD5 /* string_utils.h in Headers */,
+				616FDEF525BF49EC00CCCAD5 /* GTXExcludeListBlock.h in Headers */,
 				61ABAEB0204A0B0B006DBF0A /* GTXAnalyticsUtils.h in Headers */,
-				6133087323FF2F39003F8D41 /* GTXArtifactCollector.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -526,6 +925,61 @@
 			productReference = 613C3F41204A09E8007D44A8 /* GTXiLib.framework */;
 			productType = "com.apple.product-type.framework";
 		};
+		616FDFA325BF4CFE00CCCAD5 /* GTXOOPIntegrationTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 616FDFAB25BF4CFE00CCCAD5 /* Build configuration list for PBXNativeTarget "GTXOOPIntegrationTests" */;
+			buildPhases = (
+				616FDFA025BF4CFE00CCCAD5 /* Sources */,
+				616FDFA125BF4CFE00CCCAD5 /* Frameworks */,
+				616FDFA225BF4CFE00CCCAD5 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				610AA77425C0C1F5002C9C49 /* PBXTargetDependency */,
+				616FDFAA25BF4CFE00CCCAD5 /* PBXTargetDependency */,
+			);
+			name = GTXOOPIntegrationTests;
+			productName = GTXOOPIntegrationTests;
+			productReference = 616FDFA425BF4CFE00CCCAD5 /* GTXOOPIntegrationTests.xctest */;
+			productType = "com.apple.product-type.bundle.ui-testing";
+		};
+		616FE01025BF4E8600CCCAD5 /* GTXOOPFunctionalTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 616FE01925BF4E8600CCCAD5 /* Build configuration list for PBXNativeTarget "GTXOOPFunctionalTests" */;
+			buildPhases = (
+				616FE00D25BF4E8600CCCAD5 /* Sources */,
+				616FE00E25BF4E8600CCCAD5 /* Frameworks */,
+				616FE00F25BF4E8600CCCAD5 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				616FE01825BF4E8600CCCAD5 /* PBXTargetDependency */,
+			);
+			name = GTXOOPFunctionalTests;
+			productName = GTXOOPFunctionalTests;
+			productReference = 616FE01125BF4E8600CCCAD5 /* GTXOOPFunctionalTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
+		616FE02525BF4E9A00CCCAD5 /* GTXOOPUnitTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 616FE02E25BF4E9A00CCCAD5 /* Build configuration list for PBXNativeTarget "GTXOOPUnitTests" */;
+			buildPhases = (
+				616FE02225BF4E9A00CCCAD5 /* Sources */,
+				616FE02325BF4E9A00CCCAD5 /* Frameworks */,
+				616FE02425BF4E9A00CCCAD5 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				616FE02D25BF4E9A00CCCAD5 /* PBXTargetDependency */,
+			);
+			name = GTXOOPUnitTests;
+			productName = GTXOOPUnitTests;
+			productReference = 616FE02625BF4E9A00CCCAD5 /* GTXOOPUnitTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
 /* End PBXNativeTarget section */
 
 /* Begin PBXProject section */
@@ -537,6 +991,7 @@
 				TargetAttributes = {
 					6115E785204F5BA2003E32F9 = {
 						CreatedOnToolsVersion = 9.1;
+						LastSwiftMigration = 1210;
 						ProvisioningStyle = Automatic;
 					};
 					61284DAC211E3F8300F8FF29 = {
@@ -552,6 +1007,19 @@
 						CreatedOnToolsVersion = 9.1;
 						ProvisioningStyle = Automatic;
 					};
+					616FDFA325BF4CFE00CCCAD5 = {
+						CreatedOnToolsVersion = 12.1;
+						ProvisioningStyle = Automatic;
+						TestTargetID = 61284DAC211E3F8300F8FF29;
+					};
+					616FE01025BF4E8600CCCAD5 = {
+						CreatedOnToolsVersion = 12.1;
+						ProvisioningStyle = Automatic;
+					};
+					616FE02525BF4E9A00CCCAD5 = {
+						CreatedOnToolsVersion = 12.1;
+						ProvisioningStyle = Automatic;
+					};
 				};
 			};
 			buildConfigurationList = 613C3F3B204A09E7007D44A8 /* Build configuration list for PBXProject "GTXiLib" */;
@@ -571,6 +1039,9 @@
 				6115E785204F5BA2003E32F9 /* GTXiUnitTests */,
 				61284DAC211E3F8300F8FF29 /* TestApp */,
 				61284DDF211E442700F8FF29 /* FunctionalTests */,
+				616FDFA325BF4CFE00CCCAD5 /* GTXOOPIntegrationTests */,
+				616FE01025BF4E8600CCCAD5 /* GTXOOPFunctionalTests */,
+				616FE02525BF4E9A00CCCAD5 /* GTXOOPUnitTests */,
 			);
 		};
 /* End PBXProject section */
@@ -587,7 +1058,9 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				61284DCC211E3FE400F8FF29 /* GTXTestViewController.xib in Resources */,
+				616FDF2425BF4ADD00CCCAD5 /* GTXTestViewController.xib in Resources */,
+				616FDF1425BF4ACB00CCCAD5 /* LaunchScreen.storyboard in Resources */,
+				616FDF1325BF4ACB00CCCAD5 /* GTXTestApp-Info.plist in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -605,6 +1078,27 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		616FDFA225BF4CFE00CCCAD5 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		616FE00F25BF4E8600CCCAD5 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		616FE02425BF4E9A00CCCAD5 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXResourcesBuildPhase section */
 
 /* Begin PBXSourcesBuildPhase section */
@@ -612,14 +1106,24 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				6115E79E204F5BC9003E32F9 /* GTXAccessibilityTreeTests.m in Sources */,
-				6115E79C204F5BC9003E32F9 /* GTXTestSuiteTests.m in Sources */,
-				6115E79D204F5BC9003E32F9 /* GTXChecksCollectionTests.m in Sources */,
-				6115E79F204F5BC9003E32F9 /* GTXAnalyticsTests.m in Sources */,
-				6115E7A1204F5BC9003E32F9 /* GTXImageAndColorUtilsTests.m in Sources */,
-				6115E79B204F5BC9003E32F9 /* GTXToolKitTests.m in Sources */,
-				6115E7A2204F5BC9003E32F9 /* GTXBaseTestCase.m in Sources */,
-				6115E7A0204F5BC9003E32F9 /* GTXTestAccessibilityElements.m in Sources */,
+				616FDF5925BF4B7800CCCAD5 /* GTXImageRGBADataTests.mm in Sources */,
+				616FDF4E25BF4B7800CCCAD5 /* GTXChecksCollectionTests.m in Sources */,
+				616FDF4D25BF4B7800CCCAD5 /* GTXReportTests.m in Sources */,
+				616FDF5025BF4B7800CCCAD5 /* GTXElementReferenceTests.m in Sources */,
+				616FDF5E25BF4B7800CCCAD5 /* GTXHierarchyResultCollectionTests.m in Sources */,
+				616FDF5D25BF4B7800CCCAD5 /* GTXResultTests.m in Sources */,
+				616FDF5525BF4B7800CCCAD5 /* GTXImageAndColorUtilsTests.m in Sources */,
+				616FDF5425BF4B7800CCCAD5 /* GTXBaseTestCase.m in Sources */,
+				616FDF5325BF4B7800CCCAD5 /* GTXAccessibilityTreeTests.m in Sources */,
+				616FDF5625BF4B7800CCCAD5 /* GTXTestAccessibilityElements.m in Sources */,
+				616FDF5B25BF4B7800CCCAD5 /* GTXToolKitTests.m in Sources */,
+				616FDF5825BF4B7800CCCAD5 /* GTXElementResultCollectionTests.m in Sources */,
+				616FDF5125BF4B7800CCCAD5 /* GTXTestDynamicTypeCheckOptions.m in Sources */,
+				616FDF5725BF4B7800CCCAD5 /* GTXToolkitOOPTests.mm in Sources */,
+				616FDF5225BF4B7800CCCAD5 /* GTXCheckResultTests.m in Sources */,
+				616FDF5C25BF4B7800CCCAD5 /* GTXAnalyticsTests.m in Sources */,
+				616FDF4F25BF4B7800CCCAD5 /* GTXToolkitSwiftTests.swift in Sources */,
+				616FDF5A25BF4B7800CCCAD5 /* GTXTestSuiteTests.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -627,10 +1131,10 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				61284DCD211E3FE400F8FF29 /* GTXTestAppDelegate.m in Sources */,
-				61284DCE211E3FE400F8FF29 /* GTXTestStepperButton.m in Sources */,
-				61284DCB211E3FE400F8FF29 /* GTXTestViewController.m in Sources */,
-				61284DCF211E3FE400F8FF29 /* GTXTestApp.m in Sources */,
+				616FDF2525BF4ADD00CCCAD5 /* GTXTestStepperButton.m in Sources */,
+				616FDF2225BF4ADD00CCCAD5 /* GTXTestApp.m in Sources */,
+				616FDF2325BF4ADD00CCCAD5 /* GTXTestViewController.m in Sources */,
+				616FDF2125BF4ADD00CCCAD5 /* GTXTestAppDelegate.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -638,19 +1142,19 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				61284E05211E447E00F8FF29 /* GTXTestGtxCanDetectFailures.m in Sources */,
-				61284DFD211E447E00F8FF29 /* GTXTestGtxCanDetectFailuresInInheritedTests.m in Sources */,
-				61284DFC211E447E00F8FF29 /* GTXTestGtxCanBlacklistTestCases.m in Sources */,
-				61284E00211E447E00F8FF29 /* GTXTestBaseTest.m in Sources */,
-				61284DFA211E447E00F8FF29 /* GTXTestFailingClassFailCheck.m in Sources */,
-				61284E02211E447E00F8FF29 /* GTXTestAnalyticsIsTriggered.m in Sources */,
-				61284DFF211E447E00F8FF29 /* GTXTestGtxWithDefaultChecks.m in Sources */,
-				61284DFE211E447E00F8FF29 /* GTXTestGtxCanIgnoreElements.m in Sources */,
-				61284DF9211E447E00F8FF29 /* GTXTestGtxWorksForPassingTests.m in Sources */,
-				61284DFB211E447E00F8FF29 /* GTXTestAnalyticsBaseTest.m in Sources */,
-				61284E04211E447E00F8FF29 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m in Sources */,
-				61284E03211E447E00F8FF29 /* GTXTestAnalyticsCanBeDisabled.m in Sources */,
-				61284E01211E447E00F8FF29 /* GTXTestGtxCanWhitelistTestCases.m in Sources */,
+				616FDF7E25BF4BB400CCCAD5 /* GTXTestAnalyticsIsTriggered.m in Sources */,
+				616FDF8025BF4BB400CCCAD5 /* GTXTestGtxCanDetectFailuresInInheritedTests.m in Sources */,
+				616FDF7725BF4BB400CCCAD5 /* GTXTestAnalyticsCanBeDisabled.m in Sources */,
+				616FDF7F25BF4BB400CCCAD5 /* GTXTestGtxCanDetectFailures.m in Sources */,
+				616FDF7625BF4BB400CCCAD5 /* GTXTestGtxCanIgnoreElementsOnSpecificCheck.m in Sources */,
+				616FDF7A25BF4BB400CCCAD5 /* GTXTestGtxCanExcludeListTestCases.m in Sources */,
+				616FDF7C25BF4BB400CCCAD5 /* GTXTestGtxCanIgnoreElements.m in Sources */,
+				616FDF7D25BF4BB400CCCAD5 /* GTXTestGtxWorksForPassingTests.m in Sources */,
+				616FDF8225BF4BB400CCCAD5 /* GTXTestGtxWithDefaultChecks.m in Sources */,
+				616FDF7925BF4BB400CCCAD5 /* GTXTestFailingClassFailCheck.m in Sources */,
+				616FDF7825BF4BB400CCCAD5 /* GTXTestGtxCanWhitelistTestCases.m in Sources */,
+				616FDF8125BF4BB400CCCAD5 /* GTXTestBaseTest.m in Sources */,
+				616FDF7B25BF4BB400CCCAD5 /* GTXTestAnalyticsBaseTest.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -658,37 +1162,103 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				616FE00725BF4DF700CCCAD5 /* gtx.pb.cc in Sources */,
 				61ABAEC6204A0B0B006DBF0A /* GTXChecksCollection.m in Sources */,
+				616FDFF425BF4DC500CCCAD5 /* image_color_utils.cc in Sources */,
+				616FDEFF25BF49EC00CCCAD5 /* NSString+GTXAdditions.mm in Sources */,
+				616FDFE225BF4DC500CCCAD5 /* localized_strings_manager.cc in Sources */,
 				61ABAECC204A0B0B006DBF0A /* GTXErrorReporter.m in Sources */,
+				616FDEE725BF49EC00CCCAD5 /* GTXImageRGBAData+GTXOOPAdditions.mm in Sources */,
+				616FDEE925BF49EC00CCCAD5 /* GTXSwizzler.m in Sources */,
+				616FDFE725BF4DC500CCCAD5 /* string_utils.cc in Sources */,
+				616FDF0025BF49EC00CCCAD5 /* GTXElementResultCollection.m in Sources */,
 				61ABAEB4204A0B0B006DBF0A /* GTXTestSuite.m in Sources */,
-				61ABAEB3204A0B0B006DBF0A /* GTXImageAndColorUtils.m in Sources */,
-				6133087223FF2F39003F8D41 /* GTXArtifactProcessor.m in Sources */,
+				616FDFE325BF4DC500CCCAD5 /* check_result.cc in Sources */,
 				618E066023FF412800BDD929 /* GTXResult.m in Sources */,
-				61284E0B211E45C600F8FF29 /* GTXBlacklistFactory.m in Sources */,
-				61ABAEC2204A0B0B006DBF0A /* GTXToolKit.m in Sources */,
+				616FDEFA25BF49EC00CCCAD5 /* GTXXCUIApplicationProxy.m in Sources */,
 				6133088123FF2F53003F8D41 /* UIColor+GTXAdditions.m in Sources */,
 				61ABAEC9204A0B0B006DBF0A /* GTXAnalytics.m in Sources */,
+				616FDEF825BF49EC00CCCAD5 /* UIColor+GTXOOPAdditions.mm in Sources */,
 				610CA3FE204DFC76008BAAA1 /* GTXPluginXCTestCase.m in Sources */,
 				61284DDA211E437800F8FF29 /* GTXTestEnvironment.m in Sources */,
+				616FDFF125BF4DC500CCCAD5 /* contrast_check.cc in Sources */,
+				616FDEFD25BF49EC00CCCAD5 /* GTXExcludeListFactory.m in Sources */,
 				61ABAEB8204A0B0B006DBF0A /* GTXAnalyticsUtils.m in Sources */,
 				6133088623FF2F53003F8D41 /* GTXError.m in Sources */,
-				61284DD5211E42CF00F8FF29 /* GTXBlacklistBlock.m in Sources */,
+				616FDFEE25BF4DC500CCCAD5 /* toolkit.cc in Sources */,
+				616FDFF525BF4DC500CCCAD5 /* minimum_tappable_area_check.cc in Sources */,
+				616FDF0225BF49EC00CCCAD5 /* GTXXCUIElementQueryProxy.m in Sources */,
 				61ABAEBF204A0B0B006DBF0A /* NSError+GTXAdditions.m in Sources */,
+				616FDEF325BF49EC00CCCAD5 /* GTXCheckResult.m in Sources */,
+				616FDF0325BF49EC00CCCAD5 /* GTXExcludeListBlock.m in Sources */,
 				61ABAEBC204A0B0B006DBF0A /* GTXAccessibilityTree.m in Sources */,
-				6133088523FF2F53003F8D41 /* GTXSnapshotBuffer.m in Sources */,
-				6133088423FF2F53003F8D41 /* GTXSnapshotContainer.m in Sources */,
+				616FDFEC25BF4DC500CCCAD5 /* error_message.cc in Sources */,
+				616FDFEB25BF4DC500CCCAD5 /* contrast_swatch.cc in Sources */,
+				616FDEEF25BF49EC00CCCAD5 /* GTXToolKit.mm in Sources */,
+				616FDF0525BF49EC00CCCAD5 /* NSObject+GTXAdditions.mm in Sources */,
+				616FDFF225BF4DC500CCCAD5 /* accessibility_label_not_punctuated_check.cc in Sources */,
+				616FDEFB25BF49EC00CCCAD5 /* GTXElementReference.m in Sources */,
 				61ABAEC0204A0B0B006DBF0A /* GTXCheckBlock.m in Sources */,
+				616FDFEF25BF4DC500CCCAD5 /* gtx_types.cc in Sources */,
+				616FDFF625BF4DC500CCCAD5 /* check.cc in Sources */,
 				61ABAEBB204A0B0B006DBF0A /* GTXTestCase.m in Sources */,
-				6133087023FF2F39003F8D41 /* GTXArtifactCollector.m in Sources */,
+				616FDEF725BF49EC00CCCAD5 /* GTXXCUIElementProxy.m in Sources */,
+				616FDEFC25BF49EC00CCCAD5 /* GTXHierarchyResultCollection.m in Sources */,
+				616FDFF025BF4DC500CCCAD5 /* ui_element.cc in Sources */,
 				61ABAECE204A0B0B006DBF0A /* GTXImageRGBAData.m in Sources */,
+				616FDF0125BF49EC00CCCAD5 /* GTXImageAndColorUtils.mm in Sources */,
+				616FDFE925BF4DC500CCCAD5 /* parameters.cc in Sources */,
 				61A0C4DE2061896300DF0169 /* GTXiLibCore.m in Sources */,
 				6133088823FF2F53003F8D41 /* GTXReport.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		616FDFA025BF4CFE00CCCAD5 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				61CC44B025C0CAE600CF632A /* GTXUITestBaseTest.mm in Sources */,
+				61E1A12E25C0CD34009FBAD9 /* GTXTestStepperButton.m in Sources */,
+				616FE05D25BF4EE500CCCAD5 /* XCUIElement+GTXTestAdditions.mm in Sources */,
+				616FDFB925BF4D3500CCCAD5 /* GTXTestIntegrationTestCase.m in Sources */,
+				616FDFB825BF4D3500CCCAD5 /* GTXTestPassingIntegrationTest.m in Sources */,
+				61E1A12F25C0CD34009FBAD9 /* GTXTestViewController.m in Sources */,
+				616FDFBA25BF4D3500CCCAD5 /* GTXTestFailingIntegrationTest.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		616FE00D25BF4E8600CCCAD5 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				61CC44B125C0CAE600CF632A /* GTXUITestBaseTest.mm in Sources */,
+				616FE05425BF4EDD00CCCAD5 /* XCUIElement+GTXTestAdditions.mm in Sources */,
+				616FE04B25BF4EB200CCCAD5 /* GTXTestXCUIElementTests.m in Sources */,
+				61E1A18525C0CDBF009FBAD9 /* GTXTestViewController.m in Sources */,
+				61E1A18425C0CDBF009FBAD9 /* GTXTestStepperButton.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		616FE02225BF4E9A00CCCAD5 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				616FE04225BF4EAB00CCCAD5 /* GTXStringUtilsTests.mm in Sources */,
+				616FE03F25BF4EAB00CCCAD5 /* GTXUIElementTests.mm in Sources */,
+				616FE04025BF4EAB00CCCAD5 /* GTXTypesTests.mm in Sources */,
+				616FE04125BF4EAB00CCCAD5 /* GTXColorSwatchTests.mm in Sources */,
+				616FE04325BF4EAB00CCCAD5 /* GTXToolkitTests.mm in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
+		610AA77425C0C1F5002C9C49 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 613C3F40204A09E7007D44A8 /* GTXiLib */;
+			targetProxy = 610AA77325C0C1F5002C9C49 /* PBXContainerItemProxy */;
+		};
 		6115E78D204F5BA3003E32F9 /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = 613C3F40204A09E7007D44A8 /* GTXiLib */;
@@ -704,17 +1274,35 @@
 			target = 613C3F40204A09E7007D44A8 /* GTXiLib */;
 			targetProxy = 61284E06211E448F00F8FF29 /* PBXContainerItemProxy */;
 		};
+		616FDFAA25BF4CFE00CCCAD5 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 61284DAC211E3F8300F8FF29 /* TestApp */;
+			targetProxy = 616FDFA925BF4CFE00CCCAD5 /* PBXContainerItemProxy */;
+		};
+		616FE01825BF4E8600CCCAD5 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 613C3F40204A09E7007D44A8 /* GTXiLib */;
+			targetProxy = 616FE01725BF4E8600CCCAD5 /* PBXContainerItemProxy */;
+		};
+		616FE02D25BF4E9A00CCCAD5 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 613C3F40204A09E7007D44A8 /* GTXiLib */;
+			targetProxy = 616FE02C25BF4E9A00CCCAD5 /* PBXContainerItemProxy */;
+		};
 /* End PBXTargetDependency section */
 
 /* Begin XCBuildConfiguration section */
 		6115E78F204F5BA3003E32F9 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
 				INFOPLIST_FILE = "";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.test.google.GTAxeUnitTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
 			};
 			name = Debug;
@@ -722,11 +1310,13 @@
 		6115E790204F5BA3003E32F9 /* Release */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
+				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_STYLE = Automatic;
 				INFOPLIST_FILE = "";
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.test.google.GTAxeUnitTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
 			};
 			name = Release;
@@ -739,7 +1329,7 @@
 				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CODE_SIGN_STYLE = Automatic;
-				INFOPLIST_FILE = "$(SRCROOT)/Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist";
+				INFOPLIST_FILE = "$(SRCROOT)/Tests/Common/TestApp/GTXTestApp-Info.plist";
 				IPHONEOS_DEPLOYMENT_TARGET = 11.4;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.TestApp;
@@ -756,7 +1346,7 @@
 				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CODE_SIGN_STYLE = Automatic;
-				INFOPLIST_FILE = "$(SRCROOT)/Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist";
+				INFOPLIST_FILE = "$(SRCROOT)/Tests/Common/TestApp/GTXTestApp-Info.plist";
 				IPHONEOS_DEPLOYMENT_TARGET = 11.4;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.TestApp;
@@ -773,8 +1363,8 @@
 				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CODE_SIGN_STYLE = Automatic;
-				INFOPLIST_FILE = "Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist";
-				IPHONEOS_DEPLOYMENT_TARGET = 11.4;
+				INFOPLIST_FILE = "";
+				IPHONEOS_DEPLOYMENT_TARGET = 11.1;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.FunctionalTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -791,8 +1381,8 @@
 				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CODE_SIGN_STYLE = Automatic;
-				INFOPLIST_FILE = "Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist";
-				IPHONEOS_DEPLOYMENT_TARGET = 11.4;
+				INFOPLIST_FILE = "";
+				IPHONEOS_DEPLOYMENT_TARGET = 11.1;
 				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
 				PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.FunctionalTests;
 				PRODUCT_NAME = "$(TARGET_NAME)";
@@ -854,7 +1444,7 @@
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = iphoneos;
-				VERSIONING_SYSTEM = "apple-generic";
+				VERSIONING_SYSTEM = "";
 				VERSION_INFO_PREFIX = "";
 			};
 			name = Debug;
@@ -906,7 +1496,7 @@
 				MTL_ENABLE_DEBUG_INFO = NO;
 				SDKROOT = iphoneos;
 				VALIDATE_PRODUCT = YES;
-				VERSIONING_SYSTEM = "apple-generic";
+				VERSIONING_SYSTEM = "";
 				VERSION_INFO_PREFIX = "";
 			};
 			name = Release;
@@ -949,6 +1539,119 @@
 			};
 			name = Release;
 		};
+		616FDFAC25BF4CFE00CCCAD5 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CODE_SIGN_STYLE = Automatic;
+				INFOPLIST_FILE = "";
+				IPHONEOS_DEPLOYMENT_TARGET = 11.1;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.GTXOOPIntegrationTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				TEST_TARGET_NAME = TestApp;
+			};
+			name = Debug;
+		};
+		616FDFAD25BF4CFE00CCCAD5 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CODE_SIGN_STYLE = Automatic;
+				INFOPLIST_FILE = "";
+				IPHONEOS_DEPLOYMENT_TARGET = 11.1;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.GTXOOPIntegrationTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				TEST_TARGET_NAME = TestApp;
+			};
+			name = Release;
+		};
+		616FE01A25BF4E8600CCCAD5 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CODE_SIGN_STYLE = Automatic;
+				INFOPLIST_FILE = "";
+				IPHONEOS_DEPLOYMENT_TARGET = 11.1;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.GTXOOPFunctionalTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		616FE01B25BF4E8600CCCAD5 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CODE_SIGN_STYLE = Automatic;
+				INFOPLIST_FILE = "";
+				IPHONEOS_DEPLOYMENT_TARGET = 11.1;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.GTXOOPFunctionalTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
+		616FE02F25BF4E9A00CCCAD5 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CODE_SIGN_STYLE = Automatic;
+				INFOPLIST_FILE = "";
+				IPHONEOS_DEPLOYMENT_TARGET = 11.1;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.GTXOOPUnitTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		616FE03025BF4E9A00CCCAD5 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CODE_SIGN_STYLE = Automatic;
+				INFOPLIST_FILE = "";
+				IPHONEOS_DEPLOYMENT_TARGET = 11.1;
+				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				MTL_FAST_MATH = YES;
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.gtx.dev.GTXOOPUnitTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
@@ -997,6 +1700,33 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		616FDFAB25BF4CFE00CCCAD5 /* Build configuration list for PBXNativeTarget "GTXOOPIntegrationTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				616FDFAC25BF4CFE00CCCAD5 /* Debug */,
+				616FDFAD25BF4CFE00CCCAD5 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		616FE01925BF4E8600CCCAD5 /* Build configuration list for PBXNativeTarget "GTXOOPFunctionalTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				616FE01A25BF4E8600CCCAD5 /* Debug */,
+				616FE01B25BF4E8600CCCAD5 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		616FE02E25BF4E9A00CCCAD5 /* Build configuration list for PBXNativeTarget "GTXOOPUnitTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				616FE02F25BF4E9A00CCCAD5 /* Debug */,
+				616FE03025BF4E9A00CCCAD5 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 /* End XCConfigurationList section */
 	};
 	rootObject = 613C3F38204A09E7007D44A8 /* Project object */;
diff --git a/GTXiLib.xcodeproj/xcshareddata/xcschemes/GTXiLib.xcscheme b/GTXiLib.xcodeproj/xcshareddata/xcschemes/GTXiLib.xcscheme
index 52587bd..9f47da0 100644
--- a/GTXiLib.xcodeproj/xcshareddata/xcschemes/GTXiLib.xcscheme
+++ b/GTXiLib.xcodeproj/xcshareddata/xcschemes/GTXiLib.xcscheme
@@ -20,6 +20,62 @@
                ReferencedContainer = "container:GTXiLib.xcodeproj">
             </BuildableReference>
          </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "NO"
+            buildForProfiling = "NO"
+            buildForArchiving = "NO"
+            buildForAnalyzing = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "61284DDF211E442700F8FF29"
+               BuildableName = "FunctionalTests.xctest"
+               BlueprintName = "FunctionalTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "NO"
+            buildForProfiling = "NO"
+            buildForArchiving = "NO"
+            buildForAnalyzing = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "616FE01025BF4E8600CCCAD5"
+               BuildableName = "GTXOOPFunctionalTests.xctest"
+               BlueprintName = "GTXOOPFunctionalTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "NO"
+            buildForProfiling = "NO"
+            buildForArchiving = "NO"
+            buildForAnalyzing = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "616FDFA325BF4CFE00CCCAD5"
+               BuildableName = "GTXOOPIntegrationTests.xctest"
+               BlueprintName = "GTXOOPIntegrationTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "NO"
+            buildForProfiling = "NO"
+            buildForArchiving = "NO"
+            buildForAnalyzing = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "616FE02525BF4E9A00CCCAD5"
+               BuildableName = "GTXOOPUnitTests.xctest"
+               BlueprintName = "GTXOOPUnitTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
       </BuildActionEntries>
    </BuildAction>
    <TestAction
@@ -27,6 +83,15 @@
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       shouldUseLaunchSchemeArgsEnv = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "613C3F40204A09E7007D44A8"
+            BuildableName = "GTXiLib.framework"
+            BlueprintName = "GTXiLib"
+            ReferencedContainer = "container:GTXiLib.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -38,18 +103,47 @@
                ReferencedContainer = "container:GTXiLib.xcodeproj">
             </BuildableReference>
          </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "61284DDF211E442700F8FF29"
+               BuildableName = "FunctionalTests.xctest"
+               BlueprintName = "FunctionalTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "616FE01025BF4E8600CCCAD5"
+               BuildableName = "GTXOOPFunctionalTests.xctest"
+               BlueprintName = "GTXOOPFunctionalTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "616FDFA325BF4CFE00CCCAD5"
+               BuildableName = "GTXOOPIntegrationTests.xctest"
+               BlueprintName = "GTXOOPIntegrationTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "616FE02525BF4E9A00CCCAD5"
+               BuildableName = "GTXOOPUnitTests.xctest"
+               BlueprintName = "GTXOOPUnitTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
       </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "613C3F40204A09E7007D44A8"
-            BuildableName = "GTXiLib.framework"
-            BlueprintName = "GTXiLib"
-            ReferencedContainer = "container:GTXiLib.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -70,8 +164,6 @@
             ReferencedContainer = "container:GTXiLib.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/GTXiLib.xcodeproj/xcshareddata/xcschemes/TestApp.xcscheme b/GTXiLib.xcodeproj/xcshareddata/xcschemes/TestApp.xcscheme
new file mode 100644
index 0000000..0b71a83
--- /dev/null
+++ b/GTXiLib.xcodeproj/xcshareddata/xcschemes/TestApp.xcscheme
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1210"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "61284DAC211E3F8300F8FF29"
+               BuildableName = "TestApp.app"
+               BlueprintName = "TestApp"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "61284DDF211E442700F8FF29"
+               BuildableName = "FunctionalTests.xctest"
+               BlueprintName = "FunctionalTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "616FE01025BF4E8600CCCAD5"
+               BuildableName = "GTXOOPFunctionalTests.xctest"
+               BlueprintName = "GTXOOPFunctionalTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+         <TestableReference
+            skipped = "NO">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "616FDFA325BF4CFE00CCCAD5"
+               BuildableName = "GTXOOPIntegrationTests.xctest"
+               BlueprintName = "GTXOOPIntegrationTests"
+               ReferencedContainer = "container:GTXiLib.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "61284DAC211E3F8300F8FF29"
+            BuildableName = "TestApp.app"
+            BlueprintName = "TestApp"
+            ReferencedContainer = "container:GTXiLib.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "61284DAC211E3F8300F8FF29"
+            BuildableName = "TestApp.app"
+            BlueprintName = "TestApp"
+            ReferencedContainer = "container:GTXiLib.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OOPClasses/Protos/gtx.pb.cc b/OOPClasses/Protos/gtx.pb.cc
new file mode 100644
index 0000000..a94fc6f
--- /dev/null
+++ b/OOPClasses/Protos/gtx.pb.cc
@@ -0,0 +1,1775 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: gtx.proto
+
+#include "gtx.pb.h"
+
+#include <algorithm>
+
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/wire_format_lite.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+extern PROTOBUF_INTERNAL_EXPORT_gtx_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Point_gtx_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_gtx_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_Rect_gtx_2eproto;
+extern PROTOBUF_INTERNAL_EXPORT_gtx_2eproto ::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Size_gtx_2eproto;
+namespace gtxilib {
+namespace oopclasses {
+namespace protos {
+class PointDefaultTypeInternal {
+ public:
+  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Point> _instance;
+} _Point_default_instance_;
+class SizeDefaultTypeInternal {
+ public:
+  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Size> _instance;
+} _Size_default_instance_;
+class RectDefaultTypeInternal {
+ public:
+  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<Rect> _instance;
+} _Rect_default_instance_;
+class ElementTypeDefaultTypeInternal {
+ public:
+  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<ElementType> _instance;
+} _ElementType_default_instance_;
+class UIElementDefaultTypeInternal {
+ public:
+  ::PROTOBUF_NAMESPACE_ID::internal::ExplicitlyConstructed<UIElement> _instance;
+} _UIElement_default_instance_;
+}  // namespace protos
+}  // namespace oopclasses
+}  // namespace gtxilib
+static void InitDefaultsscc_info_ElementType_gtx_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::gtxilib::oopclasses::protos::_ElementType_default_instance_;
+    new (ptr) ::gtxilib::oopclasses::protos::ElementType();
+    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
+  }
+}
+
+::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_ElementType_gtx_2eproto =
+    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_ElementType_gtx_2eproto}, {}};
+
+static void InitDefaultsscc_info_Point_gtx_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::gtxilib::oopclasses::protos::_Point_default_instance_;
+    new (ptr) ::gtxilib::oopclasses::protos::Point();
+    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
+  }
+}
+
+::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Point_gtx_2eproto =
+    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Point_gtx_2eproto}, {}};
+
+static void InitDefaultsscc_info_Rect_gtx_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::gtxilib::oopclasses::protos::_Rect_default_instance_;
+    new (ptr) ::gtxilib::oopclasses::protos::Rect();
+    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
+  }
+}
+
+::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<2> scc_info_Rect_gtx_2eproto =
+    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 2, 0, InitDefaultsscc_info_Rect_gtx_2eproto}, {
+      &scc_info_Point_gtx_2eproto.base,
+      &scc_info_Size_gtx_2eproto.base,}};
+
+static void InitDefaultsscc_info_Size_gtx_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::gtxilib::oopclasses::protos::_Size_default_instance_;
+    new (ptr) ::gtxilib::oopclasses::protos::Size();
+    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
+  }
+}
+
+::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<0> scc_info_Size_gtx_2eproto =
+    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 0, 0, InitDefaultsscc_info_Size_gtx_2eproto}, {}};
+
+static void InitDefaultsscc_info_UIElement_gtx_2eproto() {
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  {
+    void* ptr = &::gtxilib::oopclasses::protos::_UIElement_default_instance_;
+    new (ptr) ::gtxilib::oopclasses::protos::UIElement();
+    ::PROTOBUF_NAMESPACE_ID::internal::OnShutdownDestroyMessage(ptr);
+  }
+}
+
+::PROTOBUF_NAMESPACE_ID::internal::SCCInfo<1> scc_info_UIElement_gtx_2eproto =
+    {{ATOMIC_VAR_INIT(::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase::kUninitialized), 1, 0, InitDefaultsscc_info_UIElement_gtx_2eproto}, {
+      &scc_info_Rect_gtx_2eproto.base,}};
+
+static ::PROTOBUF_NAMESPACE_ID::Metadata file_level_metadata_gtx_2eproto[5];
+static const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* file_level_enum_descriptors_gtx_2eproto[1];
+static constexpr ::PROTOBUF_NAMESPACE_ID::ServiceDescriptor const** file_level_service_descriptors_gtx_2eproto = nullptr;
+
+const ::PROTOBUF_NAMESPACE_ID::uint32 TableStruct_gtx_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Point, _has_bits_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Point, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Point, x_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Point, y_),
+  0,
+  1,
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Size, _has_bits_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Size, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Size, width_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Size, height_),
+  0,
+  1,
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Rect, _has_bits_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Rect, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Rect, origin_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::Rect, size_),
+  0,
+  1,
+  ~0u,  // no _has_bits_
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::ElementType, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::UIElement, _has_bits_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::UIElement, _internal_metadata_),
+  ~0u,  // no _extensions_
+  ~0u,  // no _oneof_case_
+  ~0u,  // no _weak_field_map_
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::UIElement, is_ax_element_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::UIElement, ax_traits_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::UIElement, ax_label_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::UIElement, ax_frame_),
+  PROTOBUF_FIELD_OFFSET(::gtxilib::oopclasses::protos::UIElement, ax_element_type_),
+  3,
+  2,
+  0,
+  1,
+  4,
+};
+static const ::PROTOBUF_NAMESPACE_ID::internal::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+  { 0, 7, sizeof(::gtxilib::oopclasses::protos::Point)},
+  { 9, 16, sizeof(::gtxilib::oopclasses::protos::Size)},
+  { 18, 25, sizeof(::gtxilib::oopclasses::protos::Rect)},
+  { 27, -1, sizeof(::gtxilib::oopclasses::protos::ElementType)},
+  { 32, 42, sizeof(::gtxilib::oopclasses::protos::UIElement)},
+};
+
+static ::PROTOBUF_NAMESPACE_ID::Message const * const file_default_instances[] = {
+  reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::gtxilib::oopclasses::protos::_Point_default_instance_),
+  reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::gtxilib::oopclasses::protos::_Size_default_instance_),
+  reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::gtxilib::oopclasses::protos::_Rect_default_instance_),
+  reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::gtxilib::oopclasses::protos::_ElementType_default_instance_),
+  reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::Message*>(&::gtxilib::oopclasses::protos::_UIElement_default_instance_),
+};
+
+const char descriptor_table_protodef_gtx_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
+  "\n\tgtx.proto\022\031gtxilib.oopclasses.protos\"3"
+  "\n\005Point\022\016\n\001x\030\001 \001(\002H\000\210\001\001\022\016\n\001y\030\002 \001(\002H\001\210\001\001B"
+  "\004\n\002_xB\004\n\002_y\"D\n\004Size\022\022\n\005width\030\001 \001(\002H\000\210\001\001\022"
+  "\023\n\006height\030\002 \001(\002H\001\210\001\001B\010\n\006_widthB\t\n\007_heigh"
+  "t\"\205\001\n\004Rect\0225\n\006origin\030\001 \001(\0132 .gtxilib.oop"
+  "classes.protos.PointH\000\210\001\001\0222\n\004size\030\002 \001(\0132"
+  "\037.gtxilib.oopclasses.protos.SizeH\001\210\001\001B\t\n"
+  "\007_originB\007\n\005_size\"\233\n\n\013ElementType\"\213\n\n\017El"
+  "ementTypeEnum\022\007\n\003ANY\020\000\022\t\n\005OTHER\020\001\022\017\n\013APP"
+  "LICATION\020\002\022\t\n\005GROUP\020\003\022\n\n\006WINDOW\020\004\022\t\n\005SHE"
+  "ET\020\005\022\n\n\006DRAWER\020\006\022\t\n\005ALERT\020\007\022\n\n\006DIALOG\020\010\022"
+  "\n\n\006BUTTON\020\t\022\020\n\014RADIO_BUTTON\020\n\022\017\n\013RADIO_G"
+  "ROUP\020\013\022\r\n\tCHECK_BOX\020\014\022\027\n\023DISCLOSURE_TRIA"
+  "NGLE\020\r\022\021\n\rPOP_UP_BUTTON\020\016\022\r\n\tCOMBO_BOX\020\017"
+  "\022\017\n\013MENU_BUTTON\020\020\022\022\n\016TOOLBAR_BUTTON\020\021\022\013\n"
+  "\007POPOVER\020\022\022\014\n\010KEYBOARD\020\023\022\007\n\003KEY\020\024\022\022\n\016NAV"
+  "IGATION_BAR\020\025\022\013\n\007TAB_BAR\020\026\022\r\n\tTAB_GROUP\020"
+  "\027\022\013\n\007TOOLBAR\020\030\022\016\n\nSTATUS_BAR\020\031\022\t\n\005TABLE\020"
+  "\032\022\r\n\tTABLE_ROW\020\033\022\020\n\014TABLE_COLUMN\020\034\022\013\n\007OU"
+  "TLINE\020\035\022\017\n\013OUTLINE_ROW\020\036\022\013\n\007BROWSER\020\037\022\023\n"
+  "\017COLLECTION_VIEW\020 \022\n\n\006SLIDER\020!\022\022\n\016PAGE_I"
+  "NDICATOR\020\"\022\026\n\022PROGRESS_INDICATOR\020#\022\026\n\022AC"
+  "TIVITY_INDICATOR\020$\022\025\n\021SEGMENTED_CONTROL\020"
+  "%\022\n\n\006PICKER\020&\022\020\n\014PICKER_WHEEL\020\'\022\n\n\006SWITC"
+  "H\020(\022\n\n\006TOGGLE\020)\022\010\n\004LINK\020*\022\t\n\005IMAGE\020+\022\010\n\004"
+  "ICON\020,\022\020\n\014SEARCH_FIELD\020-\022\017\n\013SCROLL_VIEW\020"
+  ".\022\016\n\nSCROLL_BAR\020/\022\017\n\013STATIC_TEXT\0200\022\016\n\nTE"
+  "XT_FIELD\0201\022\025\n\021SECURE_TEXT_FIELD\0202\022\017\n\013DAT"
+  "E_PICKER\0203\022\r\n\tTEXT_VIEW\0204\022\010\n\004MENU\0205\022\r\n\tM"
+  "ENU_ITEM\0206\022\014\n\010MENU_BAR\0207\022\021\n\rMENU_BAR_ITE"
+  "M\0208\022\007\n\003MAP\0209\022\014\n\010WEB_VIEW\020:\022\023\n\017INCREMENT_"
+  "ARROW\020;\022\023\n\017DECREMENT_ARROW\020<\022\014\n\010TIMELINE"
+  "\020=\022\024\n\020RATING_INDICATOR\020>\022\023\n\017VALUE_INDICA"
+  "TOR\020\?\022\017\n\013SPLIT_GROUP\020@\022\014\n\010SPLITTER\020A\022\027\n\023"
+  "RELEVANCE_INDICATOR\020B\022\016\n\nCOLOR_WELL\020C\022\014\n"
+  "\010HELP_TAG\020D\022\t\n\005MATTE\020E\022\r\n\tDOCK_ITEM\020F\022\t\n"
+  "\005RULER\020G\022\020\n\014RULER_MARKER\020H\022\010\n\004GRID\020I\022\023\n\017"
+  "LEVEL_INDICATOR\020J\022\010\n\004CELL\020K\022\017\n\013LAYOUT_AR"
+  "EA\020L\022\017\n\013LAYOUT_ITEM\020M\022\n\n\006HANDLE\020N\022\013\n\007STE"
+  "PPER\020O\022\007\n\003TAB\020P\022\r\n\tTOUCH_BAR\020Q\022\017\n\013STATUS"
+  "_ITEM\020R\"\262\002\n\tUIElement\022\032\n\ris_ax_element\030\001"
+  " \001(\010H\000\210\001\001\022\026\n\tax_traits\030\002 \001(\004H\001\210\001\001\022\025\n\010ax_"
+  "label\030\003 \001(\tH\002\210\001\001\0226\n\010ax_frame\030\004 \001(\0132\037.gtx"
+  "ilib.oopclasses.protos.RectH\003\210\001\001\022T\n\017ax_e"
+  "lement_type\030\005 \001(\01626.gtxilib.oopclasses.p"
+  "rotos.ElementType.ElementTypeEnumH\004\210\001\001B\020"
+  "\n\016_is_ax_elementB\014\n\n_ax_traitsB\013\n\t_ax_la"
+  "belB\013\n\t_ax_frameB\022\n\020_ax_element_typeb\006pr"
+  "oto3"
+  ;
+static const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable*const descriptor_table_gtx_2eproto_deps[1] = {
+};
+static ::PROTOBUF_NAMESPACE_ID::internal::SCCInfoBase*const descriptor_table_gtx_2eproto_sccs[5] = {
+  &scc_info_ElementType_gtx_2eproto.base,
+  &scc_info_Point_gtx_2eproto.base,
+  &scc_info_Rect_gtx_2eproto.base,
+  &scc_info_Size_gtx_2eproto.base,
+  &scc_info_UIElement_gtx_2eproto.base,
+};
+static ::PROTOBUF_NAMESPACE_ID::internal::once_flag descriptor_table_gtx_2eproto_once;
+const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_gtx_2eproto = {
+  false, false, descriptor_table_protodef_gtx_2eproto, "gtx.proto", 1924,
+  &descriptor_table_gtx_2eproto_once, descriptor_table_gtx_2eproto_sccs, descriptor_table_gtx_2eproto_deps, 5, 0,
+  schemas, file_default_instances, TableStruct_gtx_2eproto::offsets,
+  file_level_metadata_gtx_2eproto, 5, file_level_enum_descriptors_gtx_2eproto, file_level_service_descriptors_gtx_2eproto,
+};
+
+// Force running AddDescriptors() at dynamic initialization time.
+static bool dynamic_init_dummy_gtx_2eproto = (static_cast<void>(::PROTOBUF_NAMESPACE_ID::internal::AddDescriptors(&descriptor_table_gtx_2eproto)), true);
+namespace gtxilib {
+namespace oopclasses {
+namespace protos {
+const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* ElementType_ElementTypeEnum_descriptor() {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_gtx_2eproto);
+  return file_level_enum_descriptors_gtx_2eproto[0];
+}
+bool ElementType_ElementTypeEnum_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+    case 14:
+    case 15:
+    case 16:
+    case 17:
+    case 18:
+    case 19:
+    case 20:
+    case 21:
+    case 22:
+    case 23:
+    case 24:
+    case 25:
+    case 26:
+    case 27:
+    case 28:
+    case 29:
+    case 30:
+    case 31:
+    case 32:
+    case 33:
+    case 34:
+    case 35:
+    case 36:
+    case 37:
+    case 38:
+    case 39:
+    case 40:
+    case 41:
+    case 42:
+    case 43:
+    case 44:
+    case 45:
+    case 46:
+    case 47:
+    case 48:
+    case 49:
+    case 50:
+    case 51:
+    case 52:
+    case 53:
+    case 54:
+    case 55:
+    case 56:
+    case 57:
+    case 58:
+    case 59:
+    case 60:
+    case 61:
+    case 62:
+    case 63:
+    case 64:
+    case 65:
+    case 66:
+    case 67:
+    case 68:
+    case 69:
+    case 70:
+    case 71:
+    case 72:
+    case 73:
+    case 74:
+    case 75:
+    case 76:
+    case 77:
+    case 78:
+    case 79:
+    case 80:
+    case 81:
+    case 82:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#if (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900)
+constexpr ElementType_ElementTypeEnum ElementType::ANY;
+constexpr ElementType_ElementTypeEnum ElementType::OTHER;
+constexpr ElementType_ElementTypeEnum ElementType::APPLICATION;
+constexpr ElementType_ElementTypeEnum ElementType::GROUP;
+constexpr ElementType_ElementTypeEnum ElementType::WINDOW;
+constexpr ElementType_ElementTypeEnum ElementType::SHEET;
+constexpr ElementType_ElementTypeEnum ElementType::DRAWER;
+constexpr ElementType_ElementTypeEnum ElementType::ALERT;
+constexpr ElementType_ElementTypeEnum ElementType::DIALOG;
+constexpr ElementType_ElementTypeEnum ElementType::BUTTON;
+constexpr ElementType_ElementTypeEnum ElementType::RADIO_BUTTON;
+constexpr ElementType_ElementTypeEnum ElementType::RADIO_GROUP;
+constexpr ElementType_ElementTypeEnum ElementType::CHECK_BOX;
+constexpr ElementType_ElementTypeEnum ElementType::DISCLOSURE_TRIANGLE;
+constexpr ElementType_ElementTypeEnum ElementType::POP_UP_BUTTON;
+constexpr ElementType_ElementTypeEnum ElementType::COMBO_BOX;
+constexpr ElementType_ElementTypeEnum ElementType::MENU_BUTTON;
+constexpr ElementType_ElementTypeEnum ElementType::TOOLBAR_BUTTON;
+constexpr ElementType_ElementTypeEnum ElementType::POPOVER;
+constexpr ElementType_ElementTypeEnum ElementType::KEYBOARD;
+constexpr ElementType_ElementTypeEnum ElementType::KEY;
+constexpr ElementType_ElementTypeEnum ElementType::NAVIGATION_BAR;
+constexpr ElementType_ElementTypeEnum ElementType::TAB_BAR;
+constexpr ElementType_ElementTypeEnum ElementType::TAB_GROUP;
+constexpr ElementType_ElementTypeEnum ElementType::TOOLBAR;
+constexpr ElementType_ElementTypeEnum ElementType::STATUS_BAR;
+constexpr ElementType_ElementTypeEnum ElementType::TABLE;
+constexpr ElementType_ElementTypeEnum ElementType::TABLE_ROW;
+constexpr ElementType_ElementTypeEnum ElementType::TABLE_COLUMN;
+constexpr ElementType_ElementTypeEnum ElementType::OUTLINE;
+constexpr ElementType_ElementTypeEnum ElementType::OUTLINE_ROW;
+constexpr ElementType_ElementTypeEnum ElementType::BROWSER;
+constexpr ElementType_ElementTypeEnum ElementType::COLLECTION_VIEW;
+constexpr ElementType_ElementTypeEnum ElementType::SLIDER;
+constexpr ElementType_ElementTypeEnum ElementType::PAGE_INDICATOR;
+constexpr ElementType_ElementTypeEnum ElementType::PROGRESS_INDICATOR;
+constexpr ElementType_ElementTypeEnum ElementType::ACTIVITY_INDICATOR;
+constexpr ElementType_ElementTypeEnum ElementType::SEGMENTED_CONTROL;
+constexpr ElementType_ElementTypeEnum ElementType::PICKER;
+constexpr ElementType_ElementTypeEnum ElementType::PICKER_WHEEL;
+constexpr ElementType_ElementTypeEnum ElementType::SWITCH;
+constexpr ElementType_ElementTypeEnum ElementType::TOGGLE;
+constexpr ElementType_ElementTypeEnum ElementType::LINK;
+constexpr ElementType_ElementTypeEnum ElementType::IMAGE;
+constexpr ElementType_ElementTypeEnum ElementType::ICON;
+constexpr ElementType_ElementTypeEnum ElementType::SEARCH_FIELD;
+constexpr ElementType_ElementTypeEnum ElementType::SCROLL_VIEW;
+constexpr ElementType_ElementTypeEnum ElementType::SCROLL_BAR;
+constexpr ElementType_ElementTypeEnum ElementType::STATIC_TEXT;
+constexpr ElementType_ElementTypeEnum ElementType::TEXT_FIELD;
+constexpr ElementType_ElementTypeEnum ElementType::SECURE_TEXT_FIELD;
+constexpr ElementType_ElementTypeEnum ElementType::DATE_PICKER;
+constexpr ElementType_ElementTypeEnum ElementType::TEXT_VIEW;
+constexpr ElementType_ElementTypeEnum ElementType::MENU;
+constexpr ElementType_ElementTypeEnum ElementType::MENU_ITEM;
+constexpr ElementType_ElementTypeEnum ElementType::MENU_BAR;
+constexpr ElementType_ElementTypeEnum ElementType::MENU_BAR_ITEM;
+constexpr ElementType_ElementTypeEnum ElementType::MAP;
+constexpr ElementType_ElementTypeEnum ElementType::WEB_VIEW;
+constexpr ElementType_ElementTypeEnum ElementType::INCREMENT_ARROW;
+constexpr ElementType_ElementTypeEnum ElementType::DECREMENT_ARROW;
+constexpr ElementType_ElementTypeEnum ElementType::TIMELINE;
+constexpr ElementType_ElementTypeEnum ElementType::RATING_INDICATOR;
+constexpr ElementType_ElementTypeEnum ElementType::VALUE_INDICATOR;
+constexpr ElementType_ElementTypeEnum ElementType::SPLIT_GROUP;
+constexpr ElementType_ElementTypeEnum ElementType::SPLITTER;
+constexpr ElementType_ElementTypeEnum ElementType::RELEVANCE_INDICATOR;
+constexpr ElementType_ElementTypeEnum ElementType::COLOR_WELL;
+constexpr ElementType_ElementTypeEnum ElementType::HELP_TAG;
+constexpr ElementType_ElementTypeEnum ElementType::MATTE;
+constexpr ElementType_ElementTypeEnum ElementType::DOCK_ITEM;
+constexpr ElementType_ElementTypeEnum ElementType::RULER;
+constexpr ElementType_ElementTypeEnum ElementType::RULER_MARKER;
+constexpr ElementType_ElementTypeEnum ElementType::GRID;
+constexpr ElementType_ElementTypeEnum ElementType::LEVEL_INDICATOR;
+constexpr ElementType_ElementTypeEnum ElementType::CELL;
+constexpr ElementType_ElementTypeEnum ElementType::LAYOUT_AREA;
+constexpr ElementType_ElementTypeEnum ElementType::LAYOUT_ITEM;
+constexpr ElementType_ElementTypeEnum ElementType::HANDLE;
+constexpr ElementType_ElementTypeEnum ElementType::STEPPER;
+constexpr ElementType_ElementTypeEnum ElementType::TAB;
+constexpr ElementType_ElementTypeEnum ElementType::TOUCH_BAR;
+constexpr ElementType_ElementTypeEnum ElementType::STATUS_ITEM;
+constexpr ElementType_ElementTypeEnum ElementType::ElementTypeEnum_MIN;
+constexpr ElementType_ElementTypeEnum ElementType::ElementTypeEnum_MAX;
+constexpr int ElementType::ElementTypeEnum_ARRAYSIZE;
+#endif  // (__cplusplus < 201703) && (!defined(_MSC_VER) || _MSC_VER >= 1900)
+
+// ===================================================================
+
+class Point::_Internal {
+ public:
+  using HasBits = decltype(std::declval<Point>()._has_bits_);
+  static void set_has_x(HasBits* has_bits) {
+    (*has_bits)[0] |= 1u;
+  }
+  static void set_has_y(HasBits* has_bits) {
+    (*has_bits)[0] |= 2u;
+  }
+};
+
+Point::Point(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:gtxilib.oopclasses.protos.Point)
+}
+Point::Point(const Point& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message(),
+      _has_bits_(from._has_bits_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  ::memcpy(&x_, &from.x_,
+    static_cast<size_t>(reinterpret_cast<char*>(&y_) -
+    reinterpret_cast<char*>(&x_)) + sizeof(y_));
+  // @@protoc_insertion_point(copy_constructor:gtxilib.oopclasses.protos.Point)
+}
+
+void Point::SharedCtor() {
+  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+      reinterpret_cast<char*>(&x_) - reinterpret_cast<char*>(this)),
+      0, static_cast<size_t>(reinterpret_cast<char*>(&y_) -
+      reinterpret_cast<char*>(&x_)) + sizeof(y_));
+}
+
+Point::~Point() {
+  // @@protoc_insertion_point(destructor:gtxilib.oopclasses.protos.Point)
+  SharedDtor();
+  _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+void Point::SharedDtor() {
+  GOOGLE_DCHECK(GetArena() == nullptr);
+}
+
+void Point::ArenaDtor(void* object) {
+  Point* _this = reinterpret_cast< Point* >(object);
+  (void)_this;
+}
+void Point::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void Point::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Point& Point::default_instance() {
+  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Point_gtx_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Point::Clear() {
+// @@protoc_insertion_point(message_clear_start:gtxilib.oopclasses.protos.Point)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000003u) {
+    ::memset(&x_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&y_) -
+        reinterpret_cast<char*>(&x_)) + sizeof(y_));
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* Point::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  _Internal::HasBits has_bits{};
+  while (!ctx->Done(&ptr)) {
+    ::PROTOBUF_NAMESPACE_ID::uint32 tag;
+    ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+    CHK_(ptr);
+    switch (tag >> 3) {
+      // float x = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 13)) {
+          _Internal::set_has_x(&has_bits);
+          x_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<float>(ptr);
+          ptr += sizeof(float);
+        } else goto handle_unusual;
+        continue;
+      // float y = 2;
+      case 2:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 21)) {
+          _Internal::set_has_y(&has_bits);
+          y_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<float>(ptr);
+          ptr += sizeof(float);
+        } else goto handle_unusual;
+        continue;
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->SetLastTag(tag);
+          goto success;
+        }
+        ptr = UnknownFieldParse(tag,
+            _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+            ptr, ctx);
+        CHK_(ptr != nullptr);
+        continue;
+      }
+    }  // switch
+  }  // while
+success:
+  _has_bits_.Or(has_bits);
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto success;
+#undef CHK_
+}
+
+::PROTOBUF_NAMESPACE_ID::uint8* Point::_InternalSerialize(
+    ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:gtxilib.oopclasses.protos.Point)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // float x = 1;
+  if (_internal_has_x()) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(1, this->_internal_x(), target);
+  }
+
+  // float y = 2;
+  if (_internal_has_y()) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(2, this->_internal_y(), target);
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:gtxilib.oopclasses.protos.Point)
+  return target;
+}
+
+size_t Point::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:gtxilib.oopclasses.protos.Point)
+  size_t total_size = 0;
+
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000003u) {
+    // float x = 1;
+    if (cached_has_bits & 0x00000001u) {
+      total_size += 1 + 4;
+    }
+
+    // float y = 2;
+    if (cached_has_bits & 0x00000002u) {
+      total_size += 1 + 4;
+    }
+
+  }
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize(
+        _internal_metadata_, total_size, &_cached_size_);
+  }
+  int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Point::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:gtxilib.oopclasses.protos.Point)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Point* source =
+      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Point>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:gtxilib.oopclasses.protos.Point)
+    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:gtxilib.oopclasses.protos.Point)
+    MergeFrom(*source);
+  }
+}
+
+void Point::MergeFrom(const Point& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:gtxilib.oopclasses.protos.Point)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = from._has_bits_[0];
+  if (cached_has_bits & 0x00000003u) {
+    if (cached_has_bits & 0x00000001u) {
+      x_ = from.x_;
+    }
+    if (cached_has_bits & 0x00000002u) {
+      y_ = from.y_;
+    }
+    _has_bits_[0] |= cached_has_bits;
+  }
+}
+
+void Point::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:gtxilib.oopclasses.protos.Point)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Point::CopyFrom(const Point& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:gtxilib.oopclasses.protos.Point)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Point::IsInitialized() const {
+  return true;
+}
+
+void Point::InternalSwap(Point* other) {
+  using std::swap;
+  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  ::PROTOBUF_NAMESPACE_ID::internal::memswap<
+      PROTOBUF_FIELD_OFFSET(Point, y_)
+      + sizeof(Point::y_)
+      - PROTOBUF_FIELD_OFFSET(Point, x_)>(
+          reinterpret_cast<char*>(&x_),
+          reinterpret_cast<char*>(&other->x_));
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata Point::GetMetadata() const {
+  return GetMetadataStatic();
+}
+
+
+// ===================================================================
+
+class Size::_Internal {
+ public:
+  using HasBits = decltype(std::declval<Size>()._has_bits_);
+  static void set_has_width(HasBits* has_bits) {
+    (*has_bits)[0] |= 1u;
+  }
+  static void set_has_height(HasBits* has_bits) {
+    (*has_bits)[0] |= 2u;
+  }
+};
+
+Size::Size(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:gtxilib.oopclasses.protos.Size)
+}
+Size::Size(const Size& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message(),
+      _has_bits_(from._has_bits_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  ::memcpy(&width_, &from.width_,
+    static_cast<size_t>(reinterpret_cast<char*>(&height_) -
+    reinterpret_cast<char*>(&width_)) + sizeof(height_));
+  // @@protoc_insertion_point(copy_constructor:gtxilib.oopclasses.protos.Size)
+}
+
+void Size::SharedCtor() {
+  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+      reinterpret_cast<char*>(&width_) - reinterpret_cast<char*>(this)),
+      0, static_cast<size_t>(reinterpret_cast<char*>(&height_) -
+      reinterpret_cast<char*>(&width_)) + sizeof(height_));
+}
+
+Size::~Size() {
+  // @@protoc_insertion_point(destructor:gtxilib.oopclasses.protos.Size)
+  SharedDtor();
+  _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+void Size::SharedDtor() {
+  GOOGLE_DCHECK(GetArena() == nullptr);
+}
+
+void Size::ArenaDtor(void* object) {
+  Size* _this = reinterpret_cast< Size* >(object);
+  (void)_this;
+}
+void Size::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void Size::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Size& Size::default_instance() {
+  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Size_gtx_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Size::Clear() {
+// @@protoc_insertion_point(message_clear_start:gtxilib.oopclasses.protos.Size)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000003u) {
+    ::memset(&width_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&height_) -
+        reinterpret_cast<char*>(&width_)) + sizeof(height_));
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* Size::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  _Internal::HasBits has_bits{};
+  while (!ctx->Done(&ptr)) {
+    ::PROTOBUF_NAMESPACE_ID::uint32 tag;
+    ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+    CHK_(ptr);
+    switch (tag >> 3) {
+      // float width = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 13)) {
+          _Internal::set_has_width(&has_bits);
+          width_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<float>(ptr);
+          ptr += sizeof(float);
+        } else goto handle_unusual;
+        continue;
+      // float height = 2;
+      case 2:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 21)) {
+          _Internal::set_has_height(&has_bits);
+          height_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<float>(ptr);
+          ptr += sizeof(float);
+        } else goto handle_unusual;
+        continue;
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->SetLastTag(tag);
+          goto success;
+        }
+        ptr = UnknownFieldParse(tag,
+            _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+            ptr, ctx);
+        CHK_(ptr != nullptr);
+        continue;
+      }
+    }  // switch
+  }  // while
+success:
+  _has_bits_.Or(has_bits);
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto success;
+#undef CHK_
+}
+
+::PROTOBUF_NAMESPACE_ID::uint8* Size::_InternalSerialize(
+    ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:gtxilib.oopclasses.protos.Size)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // float width = 1;
+  if (_internal_has_width()) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(1, this->_internal_width(), target);
+  }
+
+  // float height = 2;
+  if (_internal_has_height()) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteFloatToArray(2, this->_internal_height(), target);
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:gtxilib.oopclasses.protos.Size)
+  return target;
+}
+
+size_t Size::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:gtxilib.oopclasses.protos.Size)
+  size_t total_size = 0;
+
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000003u) {
+    // float width = 1;
+    if (cached_has_bits & 0x00000001u) {
+      total_size += 1 + 4;
+    }
+
+    // float height = 2;
+    if (cached_has_bits & 0x00000002u) {
+      total_size += 1 + 4;
+    }
+
+  }
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize(
+        _internal_metadata_, total_size, &_cached_size_);
+  }
+  int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Size::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:gtxilib.oopclasses.protos.Size)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Size* source =
+      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Size>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:gtxilib.oopclasses.protos.Size)
+    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:gtxilib.oopclasses.protos.Size)
+    MergeFrom(*source);
+  }
+}
+
+void Size::MergeFrom(const Size& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:gtxilib.oopclasses.protos.Size)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = from._has_bits_[0];
+  if (cached_has_bits & 0x00000003u) {
+    if (cached_has_bits & 0x00000001u) {
+      width_ = from.width_;
+    }
+    if (cached_has_bits & 0x00000002u) {
+      height_ = from.height_;
+    }
+    _has_bits_[0] |= cached_has_bits;
+  }
+}
+
+void Size::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:gtxilib.oopclasses.protos.Size)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Size::CopyFrom(const Size& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:gtxilib.oopclasses.protos.Size)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Size::IsInitialized() const {
+  return true;
+}
+
+void Size::InternalSwap(Size* other) {
+  using std::swap;
+  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  ::PROTOBUF_NAMESPACE_ID::internal::memswap<
+      PROTOBUF_FIELD_OFFSET(Size, height_)
+      + sizeof(Size::height_)
+      - PROTOBUF_FIELD_OFFSET(Size, width_)>(
+          reinterpret_cast<char*>(&width_),
+          reinterpret_cast<char*>(&other->width_));
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata Size::GetMetadata() const {
+  return GetMetadataStatic();
+}
+
+
+// ===================================================================
+
+class Rect::_Internal {
+ public:
+  using HasBits = decltype(std::declval<Rect>()._has_bits_);
+  static const ::gtxilib::oopclasses::protos::Point& origin(const Rect* msg);
+  static void set_has_origin(HasBits* has_bits) {
+    (*has_bits)[0] |= 1u;
+  }
+  static const ::gtxilib::oopclasses::protos::Size& size(const Rect* msg);
+  static void set_has_size(HasBits* has_bits) {
+    (*has_bits)[0] |= 2u;
+  }
+};
+
+const ::gtxilib::oopclasses::protos::Point&
+Rect::_Internal::origin(const Rect* msg) {
+  return *msg->origin_;
+}
+const ::gtxilib::oopclasses::protos::Size&
+Rect::_Internal::size(const Rect* msg) {
+  return *msg->size_;
+}
+Rect::Rect(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:gtxilib.oopclasses.protos.Rect)
+}
+Rect::Rect(const Rect& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message(),
+      _has_bits_(from._has_bits_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  if (from._internal_has_origin()) {
+    origin_ = new ::gtxilib::oopclasses::protos::Point(*from.origin_);
+  } else {
+    origin_ = nullptr;
+  }
+  if (from._internal_has_size()) {
+    size_ = new ::gtxilib::oopclasses::protos::Size(*from.size_);
+  } else {
+    size_ = nullptr;
+  }
+  // @@protoc_insertion_point(copy_constructor:gtxilib.oopclasses.protos.Rect)
+}
+
+void Rect::SharedCtor() {
+  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_Rect_gtx_2eproto.base);
+  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+      reinterpret_cast<char*>(&origin_) - reinterpret_cast<char*>(this)),
+      0, static_cast<size_t>(reinterpret_cast<char*>(&size_) -
+      reinterpret_cast<char*>(&origin_)) + sizeof(size_));
+}
+
+Rect::~Rect() {
+  // @@protoc_insertion_point(destructor:gtxilib.oopclasses.protos.Rect)
+  SharedDtor();
+  _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+void Rect::SharedDtor() {
+  GOOGLE_DCHECK(GetArena() == nullptr);
+  if (this != internal_default_instance()) delete origin_;
+  if (this != internal_default_instance()) delete size_;
+}
+
+void Rect::ArenaDtor(void* object) {
+  Rect* _this = reinterpret_cast< Rect* >(object);
+  (void)_this;
+}
+void Rect::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void Rect::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const Rect& Rect::default_instance() {
+  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_Rect_gtx_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void Rect::Clear() {
+// @@protoc_insertion_point(message_clear_start:gtxilib.oopclasses.protos.Rect)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000003u) {
+    if (cached_has_bits & 0x00000001u) {
+      if (GetArena() == nullptr && origin_ != nullptr) {
+        delete origin_;
+      }
+      origin_ = nullptr;
+    }
+    if (cached_has_bits & 0x00000002u) {
+      if (GetArena() == nullptr && size_ != nullptr) {
+        delete size_;
+      }
+      size_ = nullptr;
+    }
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* Rect::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  _Internal::HasBits has_bits{};
+  while (!ctx->Done(&ptr)) {
+    ::PROTOBUF_NAMESPACE_ID::uint32 tag;
+    ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+    CHK_(ptr);
+    switch (tag >> 3) {
+      // .gtxilib.oopclasses.protos.Point origin = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 10)) {
+          ptr = ctx->ParseMessage(_internal_mutable_origin(), ptr);
+          CHK_(ptr);
+        } else goto handle_unusual;
+        continue;
+      // .gtxilib.oopclasses.protos.Size size = 2;
+      case 2:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 18)) {
+          ptr = ctx->ParseMessage(_internal_mutable_size(), ptr);
+          CHK_(ptr);
+        } else goto handle_unusual;
+        continue;
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->SetLastTag(tag);
+          goto success;
+        }
+        ptr = UnknownFieldParse(tag,
+            _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+            ptr, ctx);
+        CHK_(ptr != nullptr);
+        continue;
+      }
+    }  // switch
+  }  // while
+success:
+  _has_bits_.Or(has_bits);
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto success;
+#undef CHK_
+}
+
+::PROTOBUF_NAMESPACE_ID::uint8* Rect::_InternalSerialize(
+    ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:gtxilib.oopclasses.protos.Rect)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // .gtxilib.oopclasses.protos.Point origin = 1;
+  if (_internal_has_origin()) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
+      InternalWriteMessage(
+        1, _Internal::origin(this), target, stream);
+  }
+
+  // .gtxilib.oopclasses.protos.Size size = 2;
+  if (_internal_has_size()) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
+      InternalWriteMessage(
+        2, _Internal::size(this), target, stream);
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:gtxilib.oopclasses.protos.Rect)
+  return target;
+}
+
+size_t Rect::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:gtxilib.oopclasses.protos.Rect)
+  size_t total_size = 0;
+
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000003u) {
+    // .gtxilib.oopclasses.protos.Point origin = 1;
+    if (cached_has_bits & 0x00000001u) {
+      total_size += 1 +
+        ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
+          *origin_);
+    }
+
+    // .gtxilib.oopclasses.protos.Size size = 2;
+    if (cached_has_bits & 0x00000002u) {
+      total_size += 1 +
+        ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
+          *size_);
+    }
+
+  }
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize(
+        _internal_metadata_, total_size, &_cached_size_);
+  }
+  int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void Rect::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:gtxilib.oopclasses.protos.Rect)
+  GOOGLE_DCHECK_NE(&from, this);
+  const Rect* source =
+      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<Rect>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:gtxilib.oopclasses.protos.Rect)
+    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:gtxilib.oopclasses.protos.Rect)
+    MergeFrom(*source);
+  }
+}
+
+void Rect::MergeFrom(const Rect& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:gtxilib.oopclasses.protos.Rect)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = from._has_bits_[0];
+  if (cached_has_bits & 0x00000003u) {
+    if (cached_has_bits & 0x00000001u) {
+      _internal_mutable_origin()->::gtxilib::oopclasses::protos::Point::MergeFrom(from._internal_origin());
+    }
+    if (cached_has_bits & 0x00000002u) {
+      _internal_mutable_size()->::gtxilib::oopclasses::protos::Size::MergeFrom(from._internal_size());
+    }
+  }
+}
+
+void Rect::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:gtxilib.oopclasses.protos.Rect)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Rect::CopyFrom(const Rect& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:gtxilib.oopclasses.protos.Rect)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Rect::IsInitialized() const {
+  return true;
+}
+
+void Rect::InternalSwap(Rect* other) {
+  using std::swap;
+  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  ::PROTOBUF_NAMESPACE_ID::internal::memswap<
+      PROTOBUF_FIELD_OFFSET(Rect, size_)
+      + sizeof(Rect::size_)
+      - PROTOBUF_FIELD_OFFSET(Rect, origin_)>(
+          reinterpret_cast<char*>(&origin_),
+          reinterpret_cast<char*>(&other->origin_));
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata Rect::GetMetadata() const {
+  return GetMetadataStatic();
+}
+
+
+// ===================================================================
+
+class ElementType::_Internal {
+ public:
+};
+
+ElementType::ElementType(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:gtxilib.oopclasses.protos.ElementType)
+}
+ElementType::ElementType(const ElementType& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message() {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  // @@protoc_insertion_point(copy_constructor:gtxilib.oopclasses.protos.ElementType)
+}
+
+void ElementType::SharedCtor() {
+}
+
+ElementType::~ElementType() {
+  // @@protoc_insertion_point(destructor:gtxilib.oopclasses.protos.ElementType)
+  SharedDtor();
+  _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+void ElementType::SharedDtor() {
+  GOOGLE_DCHECK(GetArena() == nullptr);
+}
+
+void ElementType::ArenaDtor(void* object) {
+  ElementType* _this = reinterpret_cast< ElementType* >(object);
+  (void)_this;
+}
+void ElementType::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void ElementType::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const ElementType& ElementType::default_instance() {
+  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_ElementType_gtx_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void ElementType::Clear() {
+// @@protoc_insertion_point(message_clear_start:gtxilib.oopclasses.protos.ElementType)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* ElementType::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  while (!ctx->Done(&ptr)) {
+    ::PROTOBUF_NAMESPACE_ID::uint32 tag;
+    ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+    CHK_(ptr);
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->SetLastTag(tag);
+          goto success;
+        }
+        ptr = UnknownFieldParse(tag,
+            _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+            ptr, ctx);
+        CHK_(ptr != nullptr);
+        continue;
+  }  // while
+success:
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto success;
+#undef CHK_
+}
+
+::PROTOBUF_NAMESPACE_ID::uint8* ElementType::_InternalSerialize(
+    ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:gtxilib.oopclasses.protos.ElementType)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:gtxilib.oopclasses.protos.ElementType)
+  return target;
+}
+
+size_t ElementType::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:gtxilib.oopclasses.protos.ElementType)
+  size_t total_size = 0;
+
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize(
+        _internal_metadata_, total_size, &_cached_size_);
+  }
+  int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void ElementType::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:gtxilib.oopclasses.protos.ElementType)
+  GOOGLE_DCHECK_NE(&from, this);
+  const ElementType* source =
+      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<ElementType>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:gtxilib.oopclasses.protos.ElementType)
+    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:gtxilib.oopclasses.protos.ElementType)
+    MergeFrom(*source);
+  }
+}
+
+void ElementType::MergeFrom(const ElementType& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:gtxilib.oopclasses.protos.ElementType)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+}
+
+void ElementType::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:gtxilib.oopclasses.protos.ElementType)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void ElementType::CopyFrom(const ElementType& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:gtxilib.oopclasses.protos.ElementType)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool ElementType::IsInitialized() const {
+  return true;
+}
+
+void ElementType::InternalSwap(ElementType* other) {
+  using std::swap;
+  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata ElementType::GetMetadata() const {
+  return GetMetadataStatic();
+}
+
+
+// ===================================================================
+
+class UIElement::_Internal {
+ public:
+  using HasBits = decltype(std::declval<UIElement>()._has_bits_);
+  static void set_has_is_ax_element(HasBits* has_bits) {
+    (*has_bits)[0] |= 8u;
+  }
+  static void set_has_ax_traits(HasBits* has_bits) {
+    (*has_bits)[0] |= 4u;
+  }
+  static void set_has_ax_label(HasBits* has_bits) {
+    (*has_bits)[0] |= 1u;
+  }
+  static const ::gtxilib::oopclasses::protos::Rect& ax_frame(const UIElement* msg);
+  static void set_has_ax_frame(HasBits* has_bits) {
+    (*has_bits)[0] |= 2u;
+  }
+  static void set_has_ax_element_type(HasBits* has_bits) {
+    (*has_bits)[0] |= 16u;
+  }
+};
+
+const ::gtxilib::oopclasses::protos::Rect&
+UIElement::_Internal::ax_frame(const UIElement* msg) {
+  return *msg->ax_frame_;
+}
+UIElement::UIElement(::PROTOBUF_NAMESPACE_ID::Arena* arena)
+  : ::PROTOBUF_NAMESPACE_ID::Message(arena) {
+  SharedCtor();
+  RegisterArenaDtor(arena);
+  // @@protoc_insertion_point(arena_constructor:gtxilib.oopclasses.protos.UIElement)
+}
+UIElement::UIElement(const UIElement& from)
+  : ::PROTOBUF_NAMESPACE_ID::Message(),
+      _has_bits_(from._has_bits_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  ax_label_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+  if (from._internal_has_ax_label()) {
+    ax_label_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, from._internal_ax_label(), 
+      GetArena());
+  }
+  if (from._internal_has_ax_frame()) {
+    ax_frame_ = new ::gtxilib::oopclasses::protos::Rect(*from.ax_frame_);
+  } else {
+    ax_frame_ = nullptr;
+  }
+  ::memcpy(&ax_traits_, &from.ax_traits_,
+    static_cast<size_t>(reinterpret_cast<char*>(&ax_element_type_) -
+    reinterpret_cast<char*>(&ax_traits_)) + sizeof(ax_element_type_));
+  // @@protoc_insertion_point(copy_constructor:gtxilib.oopclasses.protos.UIElement)
+}
+
+void UIElement::SharedCtor() {
+  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&scc_info_UIElement_gtx_2eproto.base);
+  ax_label_.UnsafeSetDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+  ::memset(reinterpret_cast<char*>(this) + static_cast<size_t>(
+      reinterpret_cast<char*>(&ax_frame_) - reinterpret_cast<char*>(this)),
+      0, static_cast<size_t>(reinterpret_cast<char*>(&ax_element_type_) -
+      reinterpret_cast<char*>(&ax_frame_)) + sizeof(ax_element_type_));
+}
+
+UIElement::~UIElement() {
+  // @@protoc_insertion_point(destructor:gtxilib.oopclasses.protos.UIElement)
+  SharedDtor();
+  _internal_metadata_.Delete<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+void UIElement::SharedDtor() {
+  GOOGLE_DCHECK(GetArena() == nullptr);
+  ax_label_.DestroyNoArena(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited());
+  if (this != internal_default_instance()) delete ax_frame_;
+}
+
+void UIElement::ArenaDtor(void* object) {
+  UIElement* _this = reinterpret_cast< UIElement* >(object);
+  (void)_this;
+}
+void UIElement::RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena*) {
+}
+void UIElement::SetCachedSize(int size) const {
+  _cached_size_.Set(size);
+}
+const UIElement& UIElement::default_instance() {
+  ::PROTOBUF_NAMESPACE_ID::internal::InitSCC(&::scc_info_UIElement_gtx_2eproto.base);
+  return *internal_default_instance();
+}
+
+
+void UIElement::Clear() {
+// @@protoc_insertion_point(message_clear_start:gtxilib.oopclasses.protos.UIElement)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x00000003u) {
+    if (cached_has_bits & 0x00000001u) {
+      ax_label_.ClearNonDefaultToEmpty();
+    }
+    if (cached_has_bits & 0x00000002u) {
+      if (GetArena() == nullptr && ax_frame_ != nullptr) {
+        delete ax_frame_;
+      }
+      ax_frame_ = nullptr;
+    }
+  }
+  if (cached_has_bits & 0x0000001cu) {
+    ::memset(&ax_traits_, 0, static_cast<size_t>(
+        reinterpret_cast<char*>(&ax_element_type_) -
+        reinterpret_cast<char*>(&ax_traits_)) + sizeof(ax_element_type_));
+  }
+  _has_bits_.Clear();
+  _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
+}
+
+const char* UIElement::_InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) {
+#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
+  _Internal::HasBits has_bits{};
+  while (!ctx->Done(&ptr)) {
+    ::PROTOBUF_NAMESPACE_ID::uint32 tag;
+    ptr = ::PROTOBUF_NAMESPACE_ID::internal::ReadTag(ptr, &tag);
+    CHK_(ptr);
+    switch (tag >> 3) {
+      // bool is_ax_element = 1;
+      case 1:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 8)) {
+          _Internal::set_has_is_ax_element(&has_bits);
+          is_ax_element_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+          CHK_(ptr);
+        } else goto handle_unusual;
+        continue;
+      // uint64 ax_traits = 2;
+      case 2:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 16)) {
+          _Internal::set_has_ax_traits(&has_bits);
+          ax_traits_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+          CHK_(ptr);
+        } else goto handle_unusual;
+        continue;
+      // string ax_label = 3;
+      case 3:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 26)) {
+          auto str = _internal_mutable_ax_label();
+          ptr = ::PROTOBUF_NAMESPACE_ID::internal::InlineGreedyStringParser(str, ptr, ctx);
+          CHK_(::PROTOBUF_NAMESPACE_ID::internal::VerifyUTF8(str, "gtxilib.oopclasses.protos.UIElement.ax_label"));
+          CHK_(ptr);
+        } else goto handle_unusual;
+        continue;
+      // .gtxilib.oopclasses.protos.Rect ax_frame = 4;
+      case 4:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 34)) {
+          ptr = ctx->ParseMessage(_internal_mutable_ax_frame(), ptr);
+          CHK_(ptr);
+        } else goto handle_unusual;
+        continue;
+      // .gtxilib.oopclasses.protos.ElementType.ElementTypeEnum ax_element_type = 5;
+      case 5:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::PROTOBUF_NAMESPACE_ID::uint8>(tag) == 40)) {
+          ::PROTOBUF_NAMESPACE_ID::uint64 val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+          CHK_(ptr);
+          _internal_set_ax_element_type(static_cast<::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum>(val));
+        } else goto handle_unusual;
+        continue;
+      default: {
+      handle_unusual:
+        if ((tag & 7) == 4 || tag == 0) {
+          ctx->SetLastTag(tag);
+          goto success;
+        }
+        ptr = UnknownFieldParse(tag,
+            _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(),
+            ptr, ctx);
+        CHK_(ptr != nullptr);
+        continue;
+      }
+    }  // switch
+  }  // while
+success:
+  _has_bits_.Or(has_bits);
+  return ptr;
+failure:
+  ptr = nullptr;
+  goto success;
+#undef CHK_
+}
+
+::PROTOBUF_NAMESPACE_ID::uint8* UIElement::_InternalSerialize(
+    ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+  // @@protoc_insertion_point(serialize_to_array_start:gtxilib.oopclasses.protos.UIElement)
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  // bool is_ax_element = 1;
+  if (_internal_has_is_ax_element()) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteBoolToArray(1, this->_internal_is_ax_element(), target);
+  }
+
+  // uint64 ax_traits = 2;
+  if (_internal_has_ax_traits()) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteUInt64ToArray(2, this->_internal_ax_traits(), target);
+  }
+
+  // string ax_label = 3;
+  if (_internal_has_ax_label()) {
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
+      this->_internal_ax_label().data(), static_cast<int>(this->_internal_ax_label().length()),
+      ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
+      "gtxilib.oopclasses.protos.UIElement.ax_label");
+    target = stream->WriteStringMaybeAliased(
+        3, this->_internal_ax_label(), target);
+  }
+
+  // .gtxilib.oopclasses.protos.Rect ax_frame = 4;
+  if (_internal_has_ax_frame()) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
+      InternalWriteMessage(
+        4, _Internal::ax_frame(this), target, stream);
+  }
+
+  // .gtxilib.oopclasses.protos.ElementType.ElementTypeEnum ax_element_type = 5;
+  if (_internal_has_ax_element_type()) {
+    target = stream->EnsureSpace(target);
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::WriteEnumToArray(
+      5, this->_internal_ax_element_type(), target);
+  }
+
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::InternalSerializeUnknownFieldsToArray(
+        _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
+  }
+  // @@protoc_insertion_point(serialize_to_array_end:gtxilib.oopclasses.protos.UIElement)
+  return target;
+}
+
+size_t UIElement::ByteSizeLong() const {
+// @@protoc_insertion_point(message_byte_size_start:gtxilib.oopclasses.protos.UIElement)
+  size_t total_size = 0;
+
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  // Prevent compiler warnings about cached_has_bits being unused
+  (void) cached_has_bits;
+
+  cached_has_bits = _has_bits_[0];
+  if (cached_has_bits & 0x0000001fu) {
+    // string ax_label = 3;
+    if (cached_has_bits & 0x00000001u) {
+      total_size += 1 +
+        ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+          this->_internal_ax_label());
+    }
+
+    // .gtxilib.oopclasses.protos.Rect ax_frame = 4;
+    if (cached_has_bits & 0x00000002u) {
+      total_size += 1 +
+        ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
+          *ax_frame_);
+    }
+
+    // uint64 ax_traits = 2;
+    if (cached_has_bits & 0x00000004u) {
+      total_size += 1 +
+        ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::UInt64Size(
+          this->_internal_ax_traits());
+    }
+
+    // bool is_ax_element = 1;
+    if (cached_has_bits & 0x00000008u) {
+      total_size += 1 + 1;
+    }
+
+    // .gtxilib.oopclasses.protos.ElementType.ElementTypeEnum ax_element_type = 5;
+    if (cached_has_bits & 0x00000010u) {
+      total_size += 1 +
+        ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::EnumSize(this->_internal_ax_element_type());
+    }
+
+  }
+  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
+    return ::PROTOBUF_NAMESPACE_ID::internal::ComputeUnknownFieldsSize(
+        _internal_metadata_, total_size, &_cached_size_);
+  }
+  int cached_size = ::PROTOBUF_NAMESPACE_ID::internal::ToCachedSize(total_size);
+  SetCachedSize(cached_size);
+  return total_size;
+}
+
+void UIElement::MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_merge_from_start:gtxilib.oopclasses.protos.UIElement)
+  GOOGLE_DCHECK_NE(&from, this);
+  const UIElement* source =
+      ::PROTOBUF_NAMESPACE_ID::DynamicCastToGenerated<UIElement>(
+          &from);
+  if (source == nullptr) {
+  // @@protoc_insertion_point(generalized_merge_from_cast_fail:gtxilib.oopclasses.protos.UIElement)
+    ::PROTOBUF_NAMESPACE_ID::internal::ReflectionOps::Merge(from, this);
+  } else {
+  // @@protoc_insertion_point(generalized_merge_from_cast_success:gtxilib.oopclasses.protos.UIElement)
+    MergeFrom(*source);
+  }
+}
+
+void UIElement::MergeFrom(const UIElement& from) {
+// @@protoc_insertion_point(class_specific_merge_from_start:gtxilib.oopclasses.protos.UIElement)
+  GOOGLE_DCHECK_NE(&from, this);
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
+  ::PROTOBUF_NAMESPACE_ID::uint32 cached_has_bits = 0;
+  (void) cached_has_bits;
+
+  cached_has_bits = from._has_bits_[0];
+  if (cached_has_bits & 0x0000001fu) {
+    if (cached_has_bits & 0x00000001u) {
+      _internal_set_ax_label(from._internal_ax_label());
+    }
+    if (cached_has_bits & 0x00000002u) {
+      _internal_mutable_ax_frame()->::gtxilib::oopclasses::protos::Rect::MergeFrom(from._internal_ax_frame());
+    }
+    if (cached_has_bits & 0x00000004u) {
+      ax_traits_ = from.ax_traits_;
+    }
+    if (cached_has_bits & 0x00000008u) {
+      is_ax_element_ = from.is_ax_element_;
+    }
+    if (cached_has_bits & 0x00000010u) {
+      ax_element_type_ = from.ax_element_type_;
+    }
+    _has_bits_[0] |= cached_has_bits;
+  }
+}
+
+void UIElement::CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) {
+// @@protoc_insertion_point(generalized_copy_from_start:gtxilib.oopclasses.protos.UIElement)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void UIElement::CopyFrom(const UIElement& from) {
+// @@protoc_insertion_point(class_specific_copy_from_start:gtxilib.oopclasses.protos.UIElement)
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool UIElement::IsInitialized() const {
+  return true;
+}
+
+void UIElement::InternalSwap(UIElement* other) {
+  using std::swap;
+  _internal_metadata_.Swap<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(&other->_internal_metadata_);
+  swap(_has_bits_[0], other->_has_bits_[0]);
+  ax_label_.Swap(&other->ax_label_, &::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+  ::PROTOBUF_NAMESPACE_ID::internal::memswap<
+      PROTOBUF_FIELD_OFFSET(UIElement, ax_element_type_)
+      + sizeof(UIElement::ax_element_type_)
+      - PROTOBUF_FIELD_OFFSET(UIElement, ax_frame_)>(
+          reinterpret_cast<char*>(&ax_frame_),
+          reinterpret_cast<char*>(&other->ax_frame_));
+}
+
+::PROTOBUF_NAMESPACE_ID::Metadata UIElement::GetMetadata() const {
+  return GetMetadataStatic();
+}
+
+
+// @@protoc_insertion_point(namespace_scope)
+}  // namespace protos
+}  // namespace oopclasses
+}  // namespace gtxilib
+PROTOBUF_NAMESPACE_OPEN
+template<> PROTOBUF_NOINLINE ::gtxilib::oopclasses::protos::Point* Arena::CreateMaybeMessage< ::gtxilib::oopclasses::protos::Point >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::gtxilib::oopclasses::protos::Point >(arena);
+}
+template<> PROTOBUF_NOINLINE ::gtxilib::oopclasses::protos::Size* Arena::CreateMaybeMessage< ::gtxilib::oopclasses::protos::Size >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::gtxilib::oopclasses::protos::Size >(arena);
+}
+template<> PROTOBUF_NOINLINE ::gtxilib::oopclasses::protos::Rect* Arena::CreateMaybeMessage< ::gtxilib::oopclasses::protos::Rect >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::gtxilib::oopclasses::protos::Rect >(arena);
+}
+template<> PROTOBUF_NOINLINE ::gtxilib::oopclasses::protos::ElementType* Arena::CreateMaybeMessage< ::gtxilib::oopclasses::protos::ElementType >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::gtxilib::oopclasses::protos::ElementType >(arena);
+}
+template<> PROTOBUF_NOINLINE ::gtxilib::oopclasses::protos::UIElement* Arena::CreateMaybeMessage< ::gtxilib::oopclasses::protos::UIElement >(Arena* arena) {
+  return Arena::CreateMessageInternal< ::gtxilib::oopclasses::protos::UIElement >(arena);
+}
+PROTOBUF_NAMESPACE_CLOSE
+
+// @@protoc_insertion_point(global_scope)
+#include <google/protobuf/port_undef.inc>
diff --git a/OOPClasses/Protos/gtx.pb.h b/OOPClasses/Protos/gtx.pb.h
new file mode 100644
index 0000000..4d25d67
--- /dev/null
+++ b/OOPClasses/Protos/gtx.pb.h
@@ -0,0 +1,1786 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: gtx.proto
+
+#ifndef GOOGLE_PROTOBUF_INCLUDED_gtx_2eproto
+#define GOOGLE_PROTOBUF_INCLUDED_gtx_2eproto
+
+#include <limits>
+#include <string>
+
+#include <google/protobuf/port_def.inc>
+#if PROTOBUF_VERSION < 3014000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please update
+#error your headers.
+#endif
+#if 3014000 < PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers. Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/port_undef.inc>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/arena.h>
+#include <google/protobuf/arenastring.h>
+#include <google/protobuf/generated_message_table_driven.h>
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/metadata_lite.h>
+#include <google/protobuf/generated_message_reflection.h>
+#include <google/protobuf/message.h>
+#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
+#include <google/protobuf/extension_set.h>  // IWYU pragma: export
+#include <google/protobuf/generated_enum_reflection.h>
+#include <google/protobuf/unknown_field_set.h>
+// @@protoc_insertion_point(includes)
+#include <google/protobuf/port_def.inc>
+#define PROTOBUF_INTERNAL_EXPORT_gtx_2eproto
+PROTOBUF_NAMESPACE_OPEN
+namespace internal {
+class AnyMetadata;
+}  // namespace internal
+PROTOBUF_NAMESPACE_CLOSE
+
+// Internal implementation detail -- do not use these members.
+struct TableStruct_gtx_2eproto {
+  static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTableField entries[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::PROTOBUF_NAMESPACE_ID::internal::AuxiliaryParseTableField aux[]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::PROTOBUF_NAMESPACE_ID::internal::ParseTable schema[5]
+    PROTOBUF_SECTION_VARIABLE(protodesc_cold);
+  static const ::PROTOBUF_NAMESPACE_ID::internal::FieldMetadata field_metadata[];
+  static const ::PROTOBUF_NAMESPACE_ID::internal::SerializationTable serialization_table[];
+  static const ::PROTOBUF_NAMESPACE_ID::uint32 offsets[];
+};
+extern const ::PROTOBUF_NAMESPACE_ID::internal::DescriptorTable descriptor_table_gtx_2eproto;
+namespace gtxilib {
+namespace oopclasses {
+namespace protos {
+class ElementType;
+class ElementTypeDefaultTypeInternal;
+extern ElementTypeDefaultTypeInternal _ElementType_default_instance_;
+class Point;
+class PointDefaultTypeInternal;
+extern PointDefaultTypeInternal _Point_default_instance_;
+class Rect;
+class RectDefaultTypeInternal;
+extern RectDefaultTypeInternal _Rect_default_instance_;
+class Size;
+class SizeDefaultTypeInternal;
+extern SizeDefaultTypeInternal _Size_default_instance_;
+class UIElement;
+class UIElementDefaultTypeInternal;
+extern UIElementDefaultTypeInternal _UIElement_default_instance_;
+}  // namespace protos
+}  // namespace oopclasses
+}  // namespace gtxilib
+PROTOBUF_NAMESPACE_OPEN
+template<> ::gtxilib::oopclasses::protos::ElementType* Arena::CreateMaybeMessage<::gtxilib::oopclasses::protos::ElementType>(Arena*);
+template<> ::gtxilib::oopclasses::protos::Point* Arena::CreateMaybeMessage<::gtxilib::oopclasses::protos::Point>(Arena*);
+template<> ::gtxilib::oopclasses::protos::Rect* Arena::CreateMaybeMessage<::gtxilib::oopclasses::protos::Rect>(Arena*);
+template<> ::gtxilib::oopclasses::protos::Size* Arena::CreateMaybeMessage<::gtxilib::oopclasses::protos::Size>(Arena*);
+template<> ::gtxilib::oopclasses::protos::UIElement* Arena::CreateMaybeMessage<::gtxilib::oopclasses::protos::UIElement>(Arena*);
+PROTOBUF_NAMESPACE_CLOSE
+namespace gtxilib {
+namespace oopclasses {
+namespace protos {
+
+enum ElementType_ElementTypeEnum : int {
+  ElementType_ElementTypeEnum_ANY = 0,
+  ElementType_ElementTypeEnum_OTHER = 1,
+  ElementType_ElementTypeEnum_APPLICATION = 2,
+  ElementType_ElementTypeEnum_GROUP = 3,
+  ElementType_ElementTypeEnum_WINDOW = 4,
+  ElementType_ElementTypeEnum_SHEET = 5,
+  ElementType_ElementTypeEnum_DRAWER = 6,
+  ElementType_ElementTypeEnum_ALERT = 7,
+  ElementType_ElementTypeEnum_DIALOG = 8,
+  ElementType_ElementTypeEnum_BUTTON = 9,
+  ElementType_ElementTypeEnum_RADIO_BUTTON = 10,
+  ElementType_ElementTypeEnum_RADIO_GROUP = 11,
+  ElementType_ElementTypeEnum_CHECK_BOX = 12,
+  ElementType_ElementTypeEnum_DISCLOSURE_TRIANGLE = 13,
+  ElementType_ElementTypeEnum_POP_UP_BUTTON = 14,
+  ElementType_ElementTypeEnum_COMBO_BOX = 15,
+  ElementType_ElementTypeEnum_MENU_BUTTON = 16,
+  ElementType_ElementTypeEnum_TOOLBAR_BUTTON = 17,
+  ElementType_ElementTypeEnum_POPOVER = 18,
+  ElementType_ElementTypeEnum_KEYBOARD = 19,
+  ElementType_ElementTypeEnum_KEY = 20,
+  ElementType_ElementTypeEnum_NAVIGATION_BAR = 21,
+  ElementType_ElementTypeEnum_TAB_BAR = 22,
+  ElementType_ElementTypeEnum_TAB_GROUP = 23,
+  ElementType_ElementTypeEnum_TOOLBAR = 24,
+  ElementType_ElementTypeEnum_STATUS_BAR = 25,
+  ElementType_ElementTypeEnum_TABLE = 26,
+  ElementType_ElementTypeEnum_TABLE_ROW = 27,
+  ElementType_ElementTypeEnum_TABLE_COLUMN = 28,
+  ElementType_ElementTypeEnum_OUTLINE = 29,
+  ElementType_ElementTypeEnum_OUTLINE_ROW = 30,
+  ElementType_ElementTypeEnum_BROWSER = 31,
+  ElementType_ElementTypeEnum_COLLECTION_VIEW = 32,
+  ElementType_ElementTypeEnum_SLIDER = 33,
+  ElementType_ElementTypeEnum_PAGE_INDICATOR = 34,
+  ElementType_ElementTypeEnum_PROGRESS_INDICATOR = 35,
+  ElementType_ElementTypeEnum_ACTIVITY_INDICATOR = 36,
+  ElementType_ElementTypeEnum_SEGMENTED_CONTROL = 37,
+  ElementType_ElementTypeEnum_PICKER = 38,
+  ElementType_ElementTypeEnum_PICKER_WHEEL = 39,
+  ElementType_ElementTypeEnum_SWITCH = 40,
+  ElementType_ElementTypeEnum_TOGGLE = 41,
+  ElementType_ElementTypeEnum_LINK = 42,
+  ElementType_ElementTypeEnum_IMAGE = 43,
+  ElementType_ElementTypeEnum_ICON = 44,
+  ElementType_ElementTypeEnum_SEARCH_FIELD = 45,
+  ElementType_ElementTypeEnum_SCROLL_VIEW = 46,
+  ElementType_ElementTypeEnum_SCROLL_BAR = 47,
+  ElementType_ElementTypeEnum_STATIC_TEXT = 48,
+  ElementType_ElementTypeEnum_TEXT_FIELD = 49,
+  ElementType_ElementTypeEnum_SECURE_TEXT_FIELD = 50,
+  ElementType_ElementTypeEnum_DATE_PICKER = 51,
+  ElementType_ElementTypeEnum_TEXT_VIEW = 52,
+  ElementType_ElementTypeEnum_MENU = 53,
+  ElementType_ElementTypeEnum_MENU_ITEM = 54,
+  ElementType_ElementTypeEnum_MENU_BAR = 55,
+  ElementType_ElementTypeEnum_MENU_BAR_ITEM = 56,
+  ElementType_ElementTypeEnum_MAP = 57,
+  ElementType_ElementTypeEnum_WEB_VIEW = 58,
+  ElementType_ElementTypeEnum_INCREMENT_ARROW = 59,
+  ElementType_ElementTypeEnum_DECREMENT_ARROW = 60,
+  ElementType_ElementTypeEnum_TIMELINE = 61,
+  ElementType_ElementTypeEnum_RATING_INDICATOR = 62,
+  ElementType_ElementTypeEnum_VALUE_INDICATOR = 63,
+  ElementType_ElementTypeEnum_SPLIT_GROUP = 64,
+  ElementType_ElementTypeEnum_SPLITTER = 65,
+  ElementType_ElementTypeEnum_RELEVANCE_INDICATOR = 66,
+  ElementType_ElementTypeEnum_COLOR_WELL = 67,
+  ElementType_ElementTypeEnum_HELP_TAG = 68,
+  ElementType_ElementTypeEnum_MATTE = 69,
+  ElementType_ElementTypeEnum_DOCK_ITEM = 70,
+  ElementType_ElementTypeEnum_RULER = 71,
+  ElementType_ElementTypeEnum_RULER_MARKER = 72,
+  ElementType_ElementTypeEnum_GRID = 73,
+  ElementType_ElementTypeEnum_LEVEL_INDICATOR = 74,
+  ElementType_ElementTypeEnum_CELL = 75,
+  ElementType_ElementTypeEnum_LAYOUT_AREA = 76,
+  ElementType_ElementTypeEnum_LAYOUT_ITEM = 77,
+  ElementType_ElementTypeEnum_HANDLE = 78,
+  ElementType_ElementTypeEnum_STEPPER = 79,
+  ElementType_ElementTypeEnum_TAB = 80,
+  ElementType_ElementTypeEnum_TOUCH_BAR = 81,
+  ElementType_ElementTypeEnum_STATUS_ITEM = 82,
+  ElementType_ElementTypeEnum_ElementType_ElementTypeEnum_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::min(),
+  ElementType_ElementTypeEnum_ElementType_ElementTypeEnum_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<::PROTOBUF_NAMESPACE_ID::int32>::max()
+};
+bool ElementType_ElementTypeEnum_IsValid(int value);
+constexpr ElementType_ElementTypeEnum ElementType_ElementTypeEnum_ElementTypeEnum_MIN = ElementType_ElementTypeEnum_ANY;
+constexpr ElementType_ElementTypeEnum ElementType_ElementTypeEnum_ElementTypeEnum_MAX = ElementType_ElementTypeEnum_STATUS_ITEM;
+constexpr int ElementType_ElementTypeEnum_ElementTypeEnum_ARRAYSIZE = ElementType_ElementTypeEnum_ElementTypeEnum_MAX + 1;
+
+const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* ElementType_ElementTypeEnum_descriptor();
+template<typename T>
+inline const std::string& ElementType_ElementTypeEnum_Name(T enum_t_value) {
+  static_assert(::std::is_same<T, ElementType_ElementTypeEnum>::value ||
+    ::std::is_integral<T>::value,
+    "Incorrect type passed to function ElementType_ElementTypeEnum_Name.");
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
+    ElementType_ElementTypeEnum_descriptor(), enum_t_value);
+}
+inline bool ElementType_ElementTypeEnum_Parse(
+    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, ElementType_ElementTypeEnum* value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<ElementType_ElementTypeEnum>(
+    ElementType_ElementTypeEnum_descriptor(), name, value);
+}
+// ===================================================================
+
+class Point PROTOBUF_FINAL :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:gtxilib.oopclasses.protos.Point) */ {
+ public:
+  inline Point() : Point(nullptr) {}
+  virtual ~Point();
+
+  Point(const Point& from);
+  Point(Point&& from) noexcept
+    : Point() {
+    *this = ::std::move(from);
+  }
+
+  inline Point& operator=(const Point& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline Point& operator=(Point&& from) noexcept {
+    if (GetArena() == from.GetArena()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return GetMetadataStatic().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return GetMetadataStatic().reflection;
+  }
+  static const Point& default_instance();
+
+  static inline const Point* internal_default_instance() {
+    return reinterpret_cast<const Point*>(
+               &_Point_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    0;
+
+  friend void swap(Point& a, Point& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(Point* other) {
+    if (other == this) return;
+    if (GetArena() == other->GetArena()) {
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(Point* other) {
+    if (other == this) return;
+    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Point* New() const final {
+    return CreateMaybeMessage<Point>(nullptr);
+  }
+
+  Point* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
+    return CreateMaybeMessage<Point>(arena);
+  }
+  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void CopyFrom(const Point& from);
+  void MergeFrom(const Point& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize(
+      ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  inline void SharedCtor();
+  inline void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Point* other);
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+    return "gtxilib.oopclasses.protos.Point";
+  }
+  protected:
+  explicit Point(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+  private:
+  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
+    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_gtx_2eproto);
+    return ::descriptor_table_gtx_2eproto.file_level_metadata[kIndexInFileMessages];
+  }
+
+  public:
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kXFieldNumber = 1,
+    kYFieldNumber = 2,
+  };
+  // float x = 1;
+  bool has_x() const;
+  private:
+  bool _internal_has_x() const;
+  public:
+  void clear_x();
+  float x() const;
+  void set_x(float value);
+  private:
+  float _internal_x() const;
+  void _internal_set_x(float value);
+  public:
+
+  // float y = 2;
+  bool has_y() const;
+  private:
+  bool _internal_has_y() const;
+  public:
+  void clear_y();
+  float y() const;
+  void set_y(float value);
+  private:
+  float _internal_y() const;
+  void _internal_set_y(float value);
+  public:
+
+  // @@protoc_insertion_point(class_scope:gtxilib.oopclasses.protos.Point)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  float x_;
+  float y_;
+  friend struct ::TableStruct_gtx_2eproto;
+};
+// -------------------------------------------------------------------
+
+class Size PROTOBUF_FINAL :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:gtxilib.oopclasses.protos.Size) */ {
+ public:
+  inline Size() : Size(nullptr) {}
+  virtual ~Size();
+
+  Size(const Size& from);
+  Size(Size&& from) noexcept
+    : Size() {
+    *this = ::std::move(from);
+  }
+
+  inline Size& operator=(const Size& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline Size& operator=(Size&& from) noexcept {
+    if (GetArena() == from.GetArena()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return GetMetadataStatic().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return GetMetadataStatic().reflection;
+  }
+  static const Size& default_instance();
+
+  static inline const Size* internal_default_instance() {
+    return reinterpret_cast<const Size*>(
+               &_Size_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    1;
+
+  friend void swap(Size& a, Size& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(Size* other) {
+    if (other == this) return;
+    if (GetArena() == other->GetArena()) {
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(Size* other) {
+    if (other == this) return;
+    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Size* New() const final {
+    return CreateMaybeMessage<Size>(nullptr);
+  }
+
+  Size* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
+    return CreateMaybeMessage<Size>(arena);
+  }
+  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void CopyFrom(const Size& from);
+  void MergeFrom(const Size& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize(
+      ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  inline void SharedCtor();
+  inline void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Size* other);
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+    return "gtxilib.oopclasses.protos.Size";
+  }
+  protected:
+  explicit Size(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+  private:
+  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
+    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_gtx_2eproto);
+    return ::descriptor_table_gtx_2eproto.file_level_metadata[kIndexInFileMessages];
+  }
+
+  public:
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kWidthFieldNumber = 1,
+    kHeightFieldNumber = 2,
+  };
+  // float width = 1;
+  bool has_width() const;
+  private:
+  bool _internal_has_width() const;
+  public:
+  void clear_width();
+  float width() const;
+  void set_width(float value);
+  private:
+  float _internal_width() const;
+  void _internal_set_width(float value);
+  public:
+
+  // float height = 2;
+  bool has_height() const;
+  private:
+  bool _internal_has_height() const;
+  public:
+  void clear_height();
+  float height() const;
+  void set_height(float value);
+  private:
+  float _internal_height() const;
+  void _internal_set_height(float value);
+  public:
+
+  // @@protoc_insertion_point(class_scope:gtxilib.oopclasses.protos.Size)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  float width_;
+  float height_;
+  friend struct ::TableStruct_gtx_2eproto;
+};
+// -------------------------------------------------------------------
+
+class Rect PROTOBUF_FINAL :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:gtxilib.oopclasses.protos.Rect) */ {
+ public:
+  inline Rect() : Rect(nullptr) {}
+  virtual ~Rect();
+
+  Rect(const Rect& from);
+  Rect(Rect&& from) noexcept
+    : Rect() {
+    *this = ::std::move(from);
+  }
+
+  inline Rect& operator=(const Rect& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline Rect& operator=(Rect&& from) noexcept {
+    if (GetArena() == from.GetArena()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return GetMetadataStatic().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return GetMetadataStatic().reflection;
+  }
+  static const Rect& default_instance();
+
+  static inline const Rect* internal_default_instance() {
+    return reinterpret_cast<const Rect*>(
+               &_Rect_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    2;
+
+  friend void swap(Rect& a, Rect& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(Rect* other) {
+    if (other == this) return;
+    if (GetArena() == other->GetArena()) {
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(Rect* other) {
+    if (other == this) return;
+    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline Rect* New() const final {
+    return CreateMaybeMessage<Rect>(nullptr);
+  }
+
+  Rect* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
+    return CreateMaybeMessage<Rect>(arena);
+  }
+  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void CopyFrom(const Rect& from);
+  void MergeFrom(const Rect& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize(
+      ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  inline void SharedCtor();
+  inline void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(Rect* other);
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+    return "gtxilib.oopclasses.protos.Rect";
+  }
+  protected:
+  explicit Rect(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+  private:
+  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
+    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_gtx_2eproto);
+    return ::descriptor_table_gtx_2eproto.file_level_metadata[kIndexInFileMessages];
+  }
+
+  public:
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kOriginFieldNumber = 1,
+    kSizeFieldNumber = 2,
+  };
+  // .gtxilib.oopclasses.protos.Point origin = 1;
+  bool has_origin() const;
+  private:
+  bool _internal_has_origin() const;
+  public:
+  void clear_origin();
+  const ::gtxilib::oopclasses::protos::Point& origin() const;
+  ::gtxilib::oopclasses::protos::Point* release_origin();
+  ::gtxilib::oopclasses::protos::Point* mutable_origin();
+  void set_allocated_origin(::gtxilib::oopclasses::protos::Point* origin);
+  private:
+  const ::gtxilib::oopclasses::protos::Point& _internal_origin() const;
+  ::gtxilib::oopclasses::protos::Point* _internal_mutable_origin();
+  public:
+  void unsafe_arena_set_allocated_origin(
+      ::gtxilib::oopclasses::protos::Point* origin);
+  ::gtxilib::oopclasses::protos::Point* unsafe_arena_release_origin();
+
+  // .gtxilib.oopclasses.protos.Size size = 2;
+  bool has_size() const;
+  private:
+  bool _internal_has_size() const;
+  public:
+  void clear_size();
+  const ::gtxilib::oopclasses::protos::Size& size() const;
+  ::gtxilib::oopclasses::protos::Size* release_size();
+  ::gtxilib::oopclasses::protos::Size* mutable_size();
+  void set_allocated_size(::gtxilib::oopclasses::protos::Size* size);
+  private:
+  const ::gtxilib::oopclasses::protos::Size& _internal_size() const;
+  ::gtxilib::oopclasses::protos::Size* _internal_mutable_size();
+  public:
+  void unsafe_arena_set_allocated_size(
+      ::gtxilib::oopclasses::protos::Size* size);
+  ::gtxilib::oopclasses::protos::Size* unsafe_arena_release_size();
+
+  // @@protoc_insertion_point(class_scope:gtxilib.oopclasses.protos.Rect)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  ::gtxilib::oopclasses::protos::Point* origin_;
+  ::gtxilib::oopclasses::protos::Size* size_;
+  friend struct ::TableStruct_gtx_2eproto;
+};
+// -------------------------------------------------------------------
+
+class ElementType PROTOBUF_FINAL :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:gtxilib.oopclasses.protos.ElementType) */ {
+ public:
+  inline ElementType() : ElementType(nullptr) {}
+  virtual ~ElementType();
+
+  ElementType(const ElementType& from);
+  ElementType(ElementType&& from) noexcept
+    : ElementType() {
+    *this = ::std::move(from);
+  }
+
+  inline ElementType& operator=(const ElementType& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline ElementType& operator=(ElementType&& from) noexcept {
+    if (GetArena() == from.GetArena()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return GetMetadataStatic().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return GetMetadataStatic().reflection;
+  }
+  static const ElementType& default_instance();
+
+  static inline const ElementType* internal_default_instance() {
+    return reinterpret_cast<const ElementType*>(
+               &_ElementType_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    3;
+
+  friend void swap(ElementType& a, ElementType& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(ElementType* other) {
+    if (other == this) return;
+    if (GetArena() == other->GetArena()) {
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(ElementType* other) {
+    if (other == this) return;
+    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline ElementType* New() const final {
+    return CreateMaybeMessage<ElementType>(nullptr);
+  }
+
+  ElementType* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
+    return CreateMaybeMessage<ElementType>(arena);
+  }
+  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void CopyFrom(const ElementType& from);
+  void MergeFrom(const ElementType& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize(
+      ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  inline void SharedCtor();
+  inline void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(ElementType* other);
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+    return "gtxilib.oopclasses.protos.ElementType";
+  }
+  protected:
+  explicit ElementType(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+  private:
+  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
+    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_gtx_2eproto);
+    return ::descriptor_table_gtx_2eproto.file_level_metadata[kIndexInFileMessages];
+  }
+
+  public:
+
+  // nested types ----------------------------------------------------
+
+  typedef ElementType_ElementTypeEnum ElementTypeEnum;
+  static constexpr ElementTypeEnum ANY =
+    ElementType_ElementTypeEnum_ANY;
+  static constexpr ElementTypeEnum OTHER =
+    ElementType_ElementTypeEnum_OTHER;
+  static constexpr ElementTypeEnum APPLICATION =
+    ElementType_ElementTypeEnum_APPLICATION;
+  static constexpr ElementTypeEnum GROUP =
+    ElementType_ElementTypeEnum_GROUP;
+  static constexpr ElementTypeEnum WINDOW =
+    ElementType_ElementTypeEnum_WINDOW;
+  static constexpr ElementTypeEnum SHEET =
+    ElementType_ElementTypeEnum_SHEET;
+  static constexpr ElementTypeEnum DRAWER =
+    ElementType_ElementTypeEnum_DRAWER;
+  static constexpr ElementTypeEnum ALERT =
+    ElementType_ElementTypeEnum_ALERT;
+  static constexpr ElementTypeEnum DIALOG =
+    ElementType_ElementTypeEnum_DIALOG;
+  static constexpr ElementTypeEnum BUTTON =
+    ElementType_ElementTypeEnum_BUTTON;
+  static constexpr ElementTypeEnum RADIO_BUTTON =
+    ElementType_ElementTypeEnum_RADIO_BUTTON;
+  static constexpr ElementTypeEnum RADIO_GROUP =
+    ElementType_ElementTypeEnum_RADIO_GROUP;
+  static constexpr ElementTypeEnum CHECK_BOX =
+    ElementType_ElementTypeEnum_CHECK_BOX;
+  static constexpr ElementTypeEnum DISCLOSURE_TRIANGLE =
+    ElementType_ElementTypeEnum_DISCLOSURE_TRIANGLE;
+  static constexpr ElementTypeEnum POP_UP_BUTTON =
+    ElementType_ElementTypeEnum_POP_UP_BUTTON;
+  static constexpr ElementTypeEnum COMBO_BOX =
+    ElementType_ElementTypeEnum_COMBO_BOX;
+  static constexpr ElementTypeEnum MENU_BUTTON =
+    ElementType_ElementTypeEnum_MENU_BUTTON;
+  static constexpr ElementTypeEnum TOOLBAR_BUTTON =
+    ElementType_ElementTypeEnum_TOOLBAR_BUTTON;
+  static constexpr ElementTypeEnum POPOVER =
+    ElementType_ElementTypeEnum_POPOVER;
+  static constexpr ElementTypeEnum KEYBOARD =
+    ElementType_ElementTypeEnum_KEYBOARD;
+  static constexpr ElementTypeEnum KEY =
+    ElementType_ElementTypeEnum_KEY;
+  static constexpr ElementTypeEnum NAVIGATION_BAR =
+    ElementType_ElementTypeEnum_NAVIGATION_BAR;
+  static constexpr ElementTypeEnum TAB_BAR =
+    ElementType_ElementTypeEnum_TAB_BAR;
+  static constexpr ElementTypeEnum TAB_GROUP =
+    ElementType_ElementTypeEnum_TAB_GROUP;
+  static constexpr ElementTypeEnum TOOLBAR =
+    ElementType_ElementTypeEnum_TOOLBAR;
+  static constexpr ElementTypeEnum STATUS_BAR =
+    ElementType_ElementTypeEnum_STATUS_BAR;
+  static constexpr ElementTypeEnum TABLE =
+    ElementType_ElementTypeEnum_TABLE;
+  static constexpr ElementTypeEnum TABLE_ROW =
+    ElementType_ElementTypeEnum_TABLE_ROW;
+  static constexpr ElementTypeEnum TABLE_COLUMN =
+    ElementType_ElementTypeEnum_TABLE_COLUMN;
+  static constexpr ElementTypeEnum OUTLINE =
+    ElementType_ElementTypeEnum_OUTLINE;
+  static constexpr ElementTypeEnum OUTLINE_ROW =
+    ElementType_ElementTypeEnum_OUTLINE_ROW;
+  static constexpr ElementTypeEnum BROWSER =
+    ElementType_ElementTypeEnum_BROWSER;
+  static constexpr ElementTypeEnum COLLECTION_VIEW =
+    ElementType_ElementTypeEnum_COLLECTION_VIEW;
+  static constexpr ElementTypeEnum SLIDER =
+    ElementType_ElementTypeEnum_SLIDER;
+  static constexpr ElementTypeEnum PAGE_INDICATOR =
+    ElementType_ElementTypeEnum_PAGE_INDICATOR;
+  static constexpr ElementTypeEnum PROGRESS_INDICATOR =
+    ElementType_ElementTypeEnum_PROGRESS_INDICATOR;
+  static constexpr ElementTypeEnum ACTIVITY_INDICATOR =
+    ElementType_ElementTypeEnum_ACTIVITY_INDICATOR;
+  static constexpr ElementTypeEnum SEGMENTED_CONTROL =
+    ElementType_ElementTypeEnum_SEGMENTED_CONTROL;
+  static constexpr ElementTypeEnum PICKER =
+    ElementType_ElementTypeEnum_PICKER;
+  static constexpr ElementTypeEnum PICKER_WHEEL =
+    ElementType_ElementTypeEnum_PICKER_WHEEL;
+  static constexpr ElementTypeEnum SWITCH =
+    ElementType_ElementTypeEnum_SWITCH;
+  static constexpr ElementTypeEnum TOGGLE =
+    ElementType_ElementTypeEnum_TOGGLE;
+  static constexpr ElementTypeEnum LINK =
+    ElementType_ElementTypeEnum_LINK;
+  static constexpr ElementTypeEnum IMAGE =
+    ElementType_ElementTypeEnum_IMAGE;
+  static constexpr ElementTypeEnum ICON =
+    ElementType_ElementTypeEnum_ICON;
+  static constexpr ElementTypeEnum SEARCH_FIELD =
+    ElementType_ElementTypeEnum_SEARCH_FIELD;
+  static constexpr ElementTypeEnum SCROLL_VIEW =
+    ElementType_ElementTypeEnum_SCROLL_VIEW;
+  static constexpr ElementTypeEnum SCROLL_BAR =
+    ElementType_ElementTypeEnum_SCROLL_BAR;
+  static constexpr ElementTypeEnum STATIC_TEXT =
+    ElementType_ElementTypeEnum_STATIC_TEXT;
+  static constexpr ElementTypeEnum TEXT_FIELD =
+    ElementType_ElementTypeEnum_TEXT_FIELD;
+  static constexpr ElementTypeEnum SECURE_TEXT_FIELD =
+    ElementType_ElementTypeEnum_SECURE_TEXT_FIELD;
+  static constexpr ElementTypeEnum DATE_PICKER =
+    ElementType_ElementTypeEnum_DATE_PICKER;
+  static constexpr ElementTypeEnum TEXT_VIEW =
+    ElementType_ElementTypeEnum_TEXT_VIEW;
+  static constexpr ElementTypeEnum MENU =
+    ElementType_ElementTypeEnum_MENU;
+  static constexpr ElementTypeEnum MENU_ITEM =
+    ElementType_ElementTypeEnum_MENU_ITEM;
+  static constexpr ElementTypeEnum MENU_BAR =
+    ElementType_ElementTypeEnum_MENU_BAR;
+  static constexpr ElementTypeEnum MENU_BAR_ITEM =
+    ElementType_ElementTypeEnum_MENU_BAR_ITEM;
+  static constexpr ElementTypeEnum MAP =
+    ElementType_ElementTypeEnum_MAP;
+  static constexpr ElementTypeEnum WEB_VIEW =
+    ElementType_ElementTypeEnum_WEB_VIEW;
+  static constexpr ElementTypeEnum INCREMENT_ARROW =
+    ElementType_ElementTypeEnum_INCREMENT_ARROW;
+  static constexpr ElementTypeEnum DECREMENT_ARROW =
+    ElementType_ElementTypeEnum_DECREMENT_ARROW;
+  static constexpr ElementTypeEnum TIMELINE =
+    ElementType_ElementTypeEnum_TIMELINE;
+  static constexpr ElementTypeEnum RATING_INDICATOR =
+    ElementType_ElementTypeEnum_RATING_INDICATOR;
+  static constexpr ElementTypeEnum VALUE_INDICATOR =
+    ElementType_ElementTypeEnum_VALUE_INDICATOR;
+  static constexpr ElementTypeEnum SPLIT_GROUP =
+    ElementType_ElementTypeEnum_SPLIT_GROUP;
+  static constexpr ElementTypeEnum SPLITTER =
+    ElementType_ElementTypeEnum_SPLITTER;
+  static constexpr ElementTypeEnum RELEVANCE_INDICATOR =
+    ElementType_ElementTypeEnum_RELEVANCE_INDICATOR;
+  static constexpr ElementTypeEnum COLOR_WELL =
+    ElementType_ElementTypeEnum_COLOR_WELL;
+  static constexpr ElementTypeEnum HELP_TAG =
+    ElementType_ElementTypeEnum_HELP_TAG;
+  static constexpr ElementTypeEnum MATTE =
+    ElementType_ElementTypeEnum_MATTE;
+  static constexpr ElementTypeEnum DOCK_ITEM =
+    ElementType_ElementTypeEnum_DOCK_ITEM;
+  static constexpr ElementTypeEnum RULER =
+    ElementType_ElementTypeEnum_RULER;
+  static constexpr ElementTypeEnum RULER_MARKER =
+    ElementType_ElementTypeEnum_RULER_MARKER;
+  static constexpr ElementTypeEnum GRID =
+    ElementType_ElementTypeEnum_GRID;
+  static constexpr ElementTypeEnum LEVEL_INDICATOR =
+    ElementType_ElementTypeEnum_LEVEL_INDICATOR;
+  static constexpr ElementTypeEnum CELL =
+    ElementType_ElementTypeEnum_CELL;
+  static constexpr ElementTypeEnum LAYOUT_AREA =
+    ElementType_ElementTypeEnum_LAYOUT_AREA;
+  static constexpr ElementTypeEnum LAYOUT_ITEM =
+    ElementType_ElementTypeEnum_LAYOUT_ITEM;
+  static constexpr ElementTypeEnum HANDLE =
+    ElementType_ElementTypeEnum_HANDLE;
+  static constexpr ElementTypeEnum STEPPER =
+    ElementType_ElementTypeEnum_STEPPER;
+  static constexpr ElementTypeEnum TAB =
+    ElementType_ElementTypeEnum_TAB;
+  static constexpr ElementTypeEnum TOUCH_BAR =
+    ElementType_ElementTypeEnum_TOUCH_BAR;
+  static constexpr ElementTypeEnum STATUS_ITEM =
+    ElementType_ElementTypeEnum_STATUS_ITEM;
+  static inline bool ElementTypeEnum_IsValid(int value) {
+    return ElementType_ElementTypeEnum_IsValid(value);
+  }
+  static constexpr ElementTypeEnum ElementTypeEnum_MIN =
+    ElementType_ElementTypeEnum_ElementTypeEnum_MIN;
+  static constexpr ElementTypeEnum ElementTypeEnum_MAX =
+    ElementType_ElementTypeEnum_ElementTypeEnum_MAX;
+  static constexpr int ElementTypeEnum_ARRAYSIZE =
+    ElementType_ElementTypeEnum_ElementTypeEnum_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+  ElementTypeEnum_descriptor() {
+    return ElementType_ElementTypeEnum_descriptor();
+  }
+  template<typename T>
+  static inline const std::string& ElementTypeEnum_Name(T enum_t_value) {
+    static_assert(::std::is_same<T, ElementTypeEnum>::value ||
+      ::std::is_integral<T>::value,
+      "Incorrect type passed to function ElementTypeEnum_Name.");
+    return ElementType_ElementTypeEnum_Name(enum_t_value);
+  }
+  static inline bool ElementTypeEnum_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
+      ElementTypeEnum* value) {
+    return ElementType_ElementTypeEnum_Parse(name, value);
+  }
+
+  // accessors -------------------------------------------------------
+
+  // @@protoc_insertion_point(class_scope:gtxilib.oopclasses.protos.ElementType)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  friend struct ::TableStruct_gtx_2eproto;
+};
+// -------------------------------------------------------------------
+
+class UIElement PROTOBUF_FINAL :
+    public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:gtxilib.oopclasses.protos.UIElement) */ {
+ public:
+  inline UIElement() : UIElement(nullptr) {}
+  virtual ~UIElement();
+
+  UIElement(const UIElement& from);
+  UIElement(UIElement&& from) noexcept
+    : UIElement() {
+    *this = ::std::move(from);
+  }
+
+  inline UIElement& operator=(const UIElement& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  inline UIElement& operator=(UIElement&& from) noexcept {
+    if (GetArena() == from.GetArena()) {
+      if (this != &from) InternalSwap(&from);
+    } else {
+      CopyFrom(from);
+    }
+    return *this;
+  }
+
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() {
+    return GetDescriptor();
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() {
+    return GetMetadataStatic().descriptor;
+  }
+  static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() {
+    return GetMetadataStatic().reflection;
+  }
+  static const UIElement& default_instance();
+
+  static inline const UIElement* internal_default_instance() {
+    return reinterpret_cast<const UIElement*>(
+               &_UIElement_default_instance_);
+  }
+  static constexpr int kIndexInFileMessages =
+    4;
+
+  friend void swap(UIElement& a, UIElement& b) {
+    a.Swap(&b);
+  }
+  inline void Swap(UIElement* other) {
+    if (other == this) return;
+    if (GetArena() == other->GetArena()) {
+      InternalSwap(other);
+    } else {
+      ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other);
+    }
+  }
+  void UnsafeArenaSwap(UIElement* other) {
+    if (other == this) return;
+    GOOGLE_DCHECK(GetArena() == other->GetArena());
+    InternalSwap(other);
+  }
+
+  // implements Message ----------------------------------------------
+
+  inline UIElement* New() const final {
+    return CreateMaybeMessage<UIElement>(nullptr);
+  }
+
+  UIElement* New(::PROTOBUF_NAMESPACE_ID::Arena* arena) const final {
+    return CreateMaybeMessage<UIElement>(arena);
+  }
+  void CopyFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void MergeFrom(const ::PROTOBUF_NAMESPACE_ID::Message& from) final;
+  void CopyFrom(const UIElement& from);
+  void MergeFrom(const UIElement& from);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
+  bool IsInitialized() const final;
+
+  size_t ByteSizeLong() const final;
+  const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
+  ::PROTOBUF_NAMESPACE_ID::uint8* _InternalSerialize(
+      ::PROTOBUF_NAMESPACE_ID::uint8* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  int GetCachedSize() const final { return _cached_size_.Get(); }
+
+  private:
+  inline void SharedCtor();
+  inline void SharedDtor();
+  void SetCachedSize(int size) const final;
+  void InternalSwap(UIElement* other);
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
+  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+    return "gtxilib.oopclasses.protos.UIElement";
+  }
+  protected:
+  explicit UIElement(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  private:
+  static void ArenaDtor(void* object);
+  inline void RegisterArenaDtor(::PROTOBUF_NAMESPACE_ID::Arena* arena);
+  public:
+
+  ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
+  private:
+  static ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadataStatic() {
+    ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&::descriptor_table_gtx_2eproto);
+    return ::descriptor_table_gtx_2eproto.file_level_metadata[kIndexInFileMessages];
+  }
+
+  public:
+
+  // nested types ----------------------------------------------------
+
+  // accessors -------------------------------------------------------
+
+  enum : int {
+    kAxLabelFieldNumber = 3,
+    kAxFrameFieldNumber = 4,
+    kAxTraitsFieldNumber = 2,
+    kIsAxElementFieldNumber = 1,
+    kAxElementTypeFieldNumber = 5,
+  };
+  // string ax_label = 3;
+  bool has_ax_label() const;
+  private:
+  bool _internal_has_ax_label() const;
+  public:
+  void clear_ax_label();
+  const std::string& ax_label() const;
+  void set_ax_label(const std::string& value);
+  void set_ax_label(std::string&& value);
+  void set_ax_label(const char* value);
+  void set_ax_label(const char* value, size_t size);
+  std::string* mutable_ax_label();
+  std::string* release_ax_label();
+  void set_allocated_ax_label(std::string* ax_label);
+  private:
+  const std::string& _internal_ax_label() const;
+  void _internal_set_ax_label(const std::string& value);
+  std::string* _internal_mutable_ax_label();
+  public:
+
+  // .gtxilib.oopclasses.protos.Rect ax_frame = 4;
+  bool has_ax_frame() const;
+  private:
+  bool _internal_has_ax_frame() const;
+  public:
+  void clear_ax_frame();
+  const ::gtxilib::oopclasses::protos::Rect& ax_frame() const;
+  ::gtxilib::oopclasses::protos::Rect* release_ax_frame();
+  ::gtxilib::oopclasses::protos::Rect* mutable_ax_frame();
+  void set_allocated_ax_frame(::gtxilib::oopclasses::protos::Rect* ax_frame);
+  private:
+  const ::gtxilib::oopclasses::protos::Rect& _internal_ax_frame() const;
+  ::gtxilib::oopclasses::protos::Rect* _internal_mutable_ax_frame();
+  public:
+  void unsafe_arena_set_allocated_ax_frame(
+      ::gtxilib::oopclasses::protos::Rect* ax_frame);
+  ::gtxilib::oopclasses::protos::Rect* unsafe_arena_release_ax_frame();
+
+  // uint64 ax_traits = 2;
+  bool has_ax_traits() const;
+  private:
+  bool _internal_has_ax_traits() const;
+  public:
+  void clear_ax_traits();
+  ::PROTOBUF_NAMESPACE_ID::uint64 ax_traits() const;
+  void set_ax_traits(::PROTOBUF_NAMESPACE_ID::uint64 value);
+  private:
+  ::PROTOBUF_NAMESPACE_ID::uint64 _internal_ax_traits() const;
+  void _internal_set_ax_traits(::PROTOBUF_NAMESPACE_ID::uint64 value);
+  public:
+
+  // bool is_ax_element = 1;
+  bool has_is_ax_element() const;
+  private:
+  bool _internal_has_is_ax_element() const;
+  public:
+  void clear_is_ax_element();
+  bool is_ax_element() const;
+  void set_is_ax_element(bool value);
+  private:
+  bool _internal_is_ax_element() const;
+  void _internal_set_is_ax_element(bool value);
+  public:
+
+  // .gtxilib.oopclasses.protos.ElementType.ElementTypeEnum ax_element_type = 5;
+  bool has_ax_element_type() const;
+  private:
+  bool _internal_has_ax_element_type() const;
+  public:
+  void clear_ax_element_type();
+  ::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum ax_element_type() const;
+  void set_ax_element_type(::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum value);
+  private:
+  ::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum _internal_ax_element_type() const;
+  void _internal_set_ax_element_type(::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum value);
+  public:
+
+  // @@protoc_insertion_point(class_scope:gtxilib.oopclasses.protos.UIElement)
+ private:
+  class _Internal;
+
+  template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
+  typedef void InternalArenaConstructable_;
+  typedef void DestructorSkippable_;
+  ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
+  mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr ax_label_;
+  ::gtxilib::oopclasses::protos::Rect* ax_frame_;
+  ::PROTOBUF_NAMESPACE_ID::uint64 ax_traits_;
+  bool is_ax_element_;
+  int ax_element_type_;
+  friend struct ::TableStruct_gtx_2eproto;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic push
+  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif  // __GNUC__
+// Point
+
+// float x = 1;
+inline bool Point::_internal_has_x() const {
+  bool value = (_has_bits_[0] & 0x00000001u) != 0;
+  return value;
+}
+inline bool Point::has_x() const {
+  return _internal_has_x();
+}
+inline void Point::clear_x() {
+  x_ = 0;
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline float Point::_internal_x() const {
+  return x_;
+}
+inline float Point::x() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.Point.x)
+  return _internal_x();
+}
+inline void Point::_internal_set_x(float value) {
+  _has_bits_[0] |= 0x00000001u;
+  x_ = value;
+}
+inline void Point::set_x(float value) {
+  _internal_set_x(value);
+  // @@protoc_insertion_point(field_set:gtxilib.oopclasses.protos.Point.x)
+}
+
+// float y = 2;
+inline bool Point::_internal_has_y() const {
+  bool value = (_has_bits_[0] & 0x00000002u) != 0;
+  return value;
+}
+inline bool Point::has_y() const {
+  return _internal_has_y();
+}
+inline void Point::clear_y() {
+  y_ = 0;
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline float Point::_internal_y() const {
+  return y_;
+}
+inline float Point::y() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.Point.y)
+  return _internal_y();
+}
+inline void Point::_internal_set_y(float value) {
+  _has_bits_[0] |= 0x00000002u;
+  y_ = value;
+}
+inline void Point::set_y(float value) {
+  _internal_set_y(value);
+  // @@protoc_insertion_point(field_set:gtxilib.oopclasses.protos.Point.y)
+}
+
+// -------------------------------------------------------------------
+
+// Size
+
+// float width = 1;
+inline bool Size::_internal_has_width() const {
+  bool value = (_has_bits_[0] & 0x00000001u) != 0;
+  return value;
+}
+inline bool Size::has_width() const {
+  return _internal_has_width();
+}
+inline void Size::clear_width() {
+  width_ = 0;
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline float Size::_internal_width() const {
+  return width_;
+}
+inline float Size::width() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.Size.width)
+  return _internal_width();
+}
+inline void Size::_internal_set_width(float value) {
+  _has_bits_[0] |= 0x00000001u;
+  width_ = value;
+}
+inline void Size::set_width(float value) {
+  _internal_set_width(value);
+  // @@protoc_insertion_point(field_set:gtxilib.oopclasses.protos.Size.width)
+}
+
+// float height = 2;
+inline bool Size::_internal_has_height() const {
+  bool value = (_has_bits_[0] & 0x00000002u) != 0;
+  return value;
+}
+inline bool Size::has_height() const {
+  return _internal_has_height();
+}
+inline void Size::clear_height() {
+  height_ = 0;
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline float Size::_internal_height() const {
+  return height_;
+}
+inline float Size::height() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.Size.height)
+  return _internal_height();
+}
+inline void Size::_internal_set_height(float value) {
+  _has_bits_[0] |= 0x00000002u;
+  height_ = value;
+}
+inline void Size::set_height(float value) {
+  _internal_set_height(value);
+  // @@protoc_insertion_point(field_set:gtxilib.oopclasses.protos.Size.height)
+}
+
+// -------------------------------------------------------------------
+
+// Rect
+
+// .gtxilib.oopclasses.protos.Point origin = 1;
+inline bool Rect::_internal_has_origin() const {
+  bool value = (_has_bits_[0] & 0x00000001u) != 0;
+  PROTOBUF_ASSUME(!value || origin_ != nullptr);
+  return value;
+}
+inline bool Rect::has_origin() const {
+  return _internal_has_origin();
+}
+inline void Rect::clear_origin() {
+  if (GetArena() == nullptr && origin_ != nullptr) {
+    delete origin_;
+  }
+  origin_ = nullptr;
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline const ::gtxilib::oopclasses::protos::Point& Rect::_internal_origin() const {
+  const ::gtxilib::oopclasses::protos::Point* p = origin_;
+  return p != nullptr ? *p : reinterpret_cast<const ::gtxilib::oopclasses::protos::Point&>(
+      ::gtxilib::oopclasses::protos::_Point_default_instance_);
+}
+inline const ::gtxilib::oopclasses::protos::Point& Rect::origin() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.Rect.origin)
+  return _internal_origin();
+}
+inline void Rect::unsafe_arena_set_allocated_origin(
+    ::gtxilib::oopclasses::protos::Point* origin) {
+  if (GetArena() == nullptr) {
+    delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(origin_);
+  }
+  origin_ = origin;
+  if (origin) {
+    _has_bits_[0] |= 0x00000001u;
+  } else {
+    _has_bits_[0] &= ~0x00000001u;
+  }
+  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:gtxilib.oopclasses.protos.Rect.origin)
+}
+inline ::gtxilib::oopclasses::protos::Point* Rect::release_origin() {
+  _has_bits_[0] &= ~0x00000001u;
+  ::gtxilib::oopclasses::protos::Point* temp = origin_;
+  origin_ = nullptr;
+  if (GetArena() != nullptr) {
+    temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  }
+  return temp;
+}
+inline ::gtxilib::oopclasses::protos::Point* Rect::unsafe_arena_release_origin() {
+  // @@protoc_insertion_point(field_release:gtxilib.oopclasses.protos.Rect.origin)
+  _has_bits_[0] &= ~0x00000001u;
+  ::gtxilib::oopclasses::protos::Point* temp = origin_;
+  origin_ = nullptr;
+  return temp;
+}
+inline ::gtxilib::oopclasses::protos::Point* Rect::_internal_mutable_origin() {
+  _has_bits_[0] |= 0x00000001u;
+  if (origin_ == nullptr) {
+    auto* p = CreateMaybeMessage<::gtxilib::oopclasses::protos::Point>(GetArena());
+    origin_ = p;
+  }
+  return origin_;
+}
+inline ::gtxilib::oopclasses::protos::Point* Rect::mutable_origin() {
+  // @@protoc_insertion_point(field_mutable:gtxilib.oopclasses.protos.Rect.origin)
+  return _internal_mutable_origin();
+}
+inline void Rect::set_allocated_origin(::gtxilib::oopclasses::protos::Point* origin) {
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  if (message_arena == nullptr) {
+    delete origin_;
+  }
+  if (origin) {
+    ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
+      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(origin);
+    if (message_arena != submessage_arena) {
+      origin = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
+          message_arena, origin, submessage_arena);
+    }
+    _has_bits_[0] |= 0x00000001u;
+  } else {
+    _has_bits_[0] &= ~0x00000001u;
+  }
+  origin_ = origin;
+  // @@protoc_insertion_point(field_set_allocated:gtxilib.oopclasses.protos.Rect.origin)
+}
+
+// .gtxilib.oopclasses.protos.Size size = 2;
+inline bool Rect::_internal_has_size() const {
+  bool value = (_has_bits_[0] & 0x00000002u) != 0;
+  PROTOBUF_ASSUME(!value || size_ != nullptr);
+  return value;
+}
+inline bool Rect::has_size() const {
+  return _internal_has_size();
+}
+inline void Rect::clear_size() {
+  if (GetArena() == nullptr && size_ != nullptr) {
+    delete size_;
+  }
+  size_ = nullptr;
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline const ::gtxilib::oopclasses::protos::Size& Rect::_internal_size() const {
+  const ::gtxilib::oopclasses::protos::Size* p = size_;
+  return p != nullptr ? *p : reinterpret_cast<const ::gtxilib::oopclasses::protos::Size&>(
+      ::gtxilib::oopclasses::protos::_Size_default_instance_);
+}
+inline const ::gtxilib::oopclasses::protos::Size& Rect::size() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.Rect.size)
+  return _internal_size();
+}
+inline void Rect::unsafe_arena_set_allocated_size(
+    ::gtxilib::oopclasses::protos::Size* size) {
+  if (GetArena() == nullptr) {
+    delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(size_);
+  }
+  size_ = size;
+  if (size) {
+    _has_bits_[0] |= 0x00000002u;
+  } else {
+    _has_bits_[0] &= ~0x00000002u;
+  }
+  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:gtxilib.oopclasses.protos.Rect.size)
+}
+inline ::gtxilib::oopclasses::protos::Size* Rect::release_size() {
+  _has_bits_[0] &= ~0x00000002u;
+  ::gtxilib::oopclasses::protos::Size* temp = size_;
+  size_ = nullptr;
+  if (GetArena() != nullptr) {
+    temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  }
+  return temp;
+}
+inline ::gtxilib::oopclasses::protos::Size* Rect::unsafe_arena_release_size() {
+  // @@protoc_insertion_point(field_release:gtxilib.oopclasses.protos.Rect.size)
+  _has_bits_[0] &= ~0x00000002u;
+  ::gtxilib::oopclasses::protos::Size* temp = size_;
+  size_ = nullptr;
+  return temp;
+}
+inline ::gtxilib::oopclasses::protos::Size* Rect::_internal_mutable_size() {
+  _has_bits_[0] |= 0x00000002u;
+  if (size_ == nullptr) {
+    auto* p = CreateMaybeMessage<::gtxilib::oopclasses::protos::Size>(GetArena());
+    size_ = p;
+  }
+  return size_;
+}
+inline ::gtxilib::oopclasses::protos::Size* Rect::mutable_size() {
+  // @@protoc_insertion_point(field_mutable:gtxilib.oopclasses.protos.Rect.size)
+  return _internal_mutable_size();
+}
+inline void Rect::set_allocated_size(::gtxilib::oopclasses::protos::Size* size) {
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  if (message_arena == nullptr) {
+    delete size_;
+  }
+  if (size) {
+    ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
+      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(size);
+    if (message_arena != submessage_arena) {
+      size = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
+          message_arena, size, submessage_arena);
+    }
+    _has_bits_[0] |= 0x00000002u;
+  } else {
+    _has_bits_[0] &= ~0x00000002u;
+  }
+  size_ = size;
+  // @@protoc_insertion_point(field_set_allocated:gtxilib.oopclasses.protos.Rect.size)
+}
+
+// -------------------------------------------------------------------
+
+// ElementType
+
+// -------------------------------------------------------------------
+
+// UIElement
+
+// bool is_ax_element = 1;
+inline bool UIElement::_internal_has_is_ax_element() const {
+  bool value = (_has_bits_[0] & 0x00000008u) != 0;
+  return value;
+}
+inline bool UIElement::has_is_ax_element() const {
+  return _internal_has_is_ax_element();
+}
+inline void UIElement::clear_is_ax_element() {
+  is_ax_element_ = false;
+  _has_bits_[0] &= ~0x00000008u;
+}
+inline bool UIElement::_internal_is_ax_element() const {
+  return is_ax_element_;
+}
+inline bool UIElement::is_ax_element() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.UIElement.is_ax_element)
+  return _internal_is_ax_element();
+}
+inline void UIElement::_internal_set_is_ax_element(bool value) {
+  _has_bits_[0] |= 0x00000008u;
+  is_ax_element_ = value;
+}
+inline void UIElement::set_is_ax_element(bool value) {
+  _internal_set_is_ax_element(value);
+  // @@protoc_insertion_point(field_set:gtxilib.oopclasses.protos.UIElement.is_ax_element)
+}
+
+// uint64 ax_traits = 2;
+inline bool UIElement::_internal_has_ax_traits() const {
+  bool value = (_has_bits_[0] & 0x00000004u) != 0;
+  return value;
+}
+inline bool UIElement::has_ax_traits() const {
+  return _internal_has_ax_traits();
+}
+inline void UIElement::clear_ax_traits() {
+  ax_traits_ = PROTOBUF_ULONGLONG(0);
+  _has_bits_[0] &= ~0x00000004u;
+}
+inline ::PROTOBUF_NAMESPACE_ID::uint64 UIElement::_internal_ax_traits() const {
+  return ax_traits_;
+}
+inline ::PROTOBUF_NAMESPACE_ID::uint64 UIElement::ax_traits() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.UIElement.ax_traits)
+  return _internal_ax_traits();
+}
+inline void UIElement::_internal_set_ax_traits(::PROTOBUF_NAMESPACE_ID::uint64 value) {
+  _has_bits_[0] |= 0x00000004u;
+  ax_traits_ = value;
+}
+inline void UIElement::set_ax_traits(::PROTOBUF_NAMESPACE_ID::uint64 value) {
+  _internal_set_ax_traits(value);
+  // @@protoc_insertion_point(field_set:gtxilib.oopclasses.protos.UIElement.ax_traits)
+}
+
+// string ax_label = 3;
+inline bool UIElement::_internal_has_ax_label() const {
+  bool value = (_has_bits_[0] & 0x00000001u) != 0;
+  return value;
+}
+inline bool UIElement::has_ax_label() const {
+  return _internal_has_ax_label();
+}
+inline void UIElement::clear_ax_label() {
+  ax_label_.ClearToEmpty();
+  _has_bits_[0] &= ~0x00000001u;
+}
+inline const std::string& UIElement::ax_label() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.UIElement.ax_label)
+  return _internal_ax_label();
+}
+inline void UIElement::set_ax_label(const std::string& value) {
+  _internal_set_ax_label(value);
+  // @@protoc_insertion_point(field_set:gtxilib.oopclasses.protos.UIElement.ax_label)
+}
+inline std::string* UIElement::mutable_ax_label() {
+  // @@protoc_insertion_point(field_mutable:gtxilib.oopclasses.protos.UIElement.ax_label)
+  return _internal_mutable_ax_label();
+}
+inline const std::string& UIElement::_internal_ax_label() const {
+  return ax_label_.Get();
+}
+inline void UIElement::_internal_set_ax_label(const std::string& value) {
+  _has_bits_[0] |= 0x00000001u;
+  ax_label_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, value, GetArena());
+}
+inline void UIElement::set_ax_label(std::string&& value) {
+  _has_bits_[0] |= 0x00000001u;
+  ax_label_.Set(
+    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::move(value), GetArena());
+  // @@protoc_insertion_point(field_set_rvalue:gtxilib.oopclasses.protos.UIElement.ax_label)
+}
+inline void UIElement::set_ax_label(const char* value) {
+  GOOGLE_DCHECK(value != nullptr);
+  _has_bits_[0] |= 0x00000001u;
+  ax_label_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(value), GetArena());
+  // @@protoc_insertion_point(field_set_char:gtxilib.oopclasses.protos.UIElement.ax_label)
+}
+inline void UIElement::set_ax_label(const char* value,
+    size_t size) {
+  _has_bits_[0] |= 0x00000001u;
+  ax_label_.Set(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, ::std::string(
+      reinterpret_cast<const char*>(value), size), GetArena());
+  // @@protoc_insertion_point(field_set_pointer:gtxilib.oopclasses.protos.UIElement.ax_label)
+}
+inline std::string* UIElement::_internal_mutable_ax_label() {
+  _has_bits_[0] |= 0x00000001u;
+  return ax_label_.Mutable(::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::EmptyDefault{}, GetArena());
+}
+inline std::string* UIElement::release_ax_label() {
+  // @@protoc_insertion_point(field_release:gtxilib.oopclasses.protos.UIElement.ax_label)
+  if (!_internal_has_ax_label()) {
+    return nullptr;
+  }
+  _has_bits_[0] &= ~0x00000001u;
+  return ax_label_.ReleaseNonDefault(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), GetArena());
+}
+inline void UIElement::set_allocated_ax_label(std::string* ax_label) {
+  if (ax_label != nullptr) {
+    _has_bits_[0] |= 0x00000001u;
+  } else {
+    _has_bits_[0] &= ~0x00000001u;
+  }
+  ax_label_.SetAllocated(&::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited(), ax_label,
+      GetArena());
+  // @@protoc_insertion_point(field_set_allocated:gtxilib.oopclasses.protos.UIElement.ax_label)
+}
+
+// .gtxilib.oopclasses.protos.Rect ax_frame = 4;
+inline bool UIElement::_internal_has_ax_frame() const {
+  bool value = (_has_bits_[0] & 0x00000002u) != 0;
+  PROTOBUF_ASSUME(!value || ax_frame_ != nullptr);
+  return value;
+}
+inline bool UIElement::has_ax_frame() const {
+  return _internal_has_ax_frame();
+}
+inline void UIElement::clear_ax_frame() {
+  if (GetArena() == nullptr && ax_frame_ != nullptr) {
+    delete ax_frame_;
+  }
+  ax_frame_ = nullptr;
+  _has_bits_[0] &= ~0x00000002u;
+}
+inline const ::gtxilib::oopclasses::protos::Rect& UIElement::_internal_ax_frame() const {
+  const ::gtxilib::oopclasses::protos::Rect* p = ax_frame_;
+  return p != nullptr ? *p : reinterpret_cast<const ::gtxilib::oopclasses::protos::Rect&>(
+      ::gtxilib::oopclasses::protos::_Rect_default_instance_);
+}
+inline const ::gtxilib::oopclasses::protos::Rect& UIElement::ax_frame() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.UIElement.ax_frame)
+  return _internal_ax_frame();
+}
+inline void UIElement::unsafe_arena_set_allocated_ax_frame(
+    ::gtxilib::oopclasses::protos::Rect* ax_frame) {
+  if (GetArena() == nullptr) {
+    delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(ax_frame_);
+  }
+  ax_frame_ = ax_frame;
+  if (ax_frame) {
+    _has_bits_[0] |= 0x00000002u;
+  } else {
+    _has_bits_[0] &= ~0x00000002u;
+  }
+  // @@protoc_insertion_point(field_unsafe_arena_set_allocated:gtxilib.oopclasses.protos.UIElement.ax_frame)
+}
+inline ::gtxilib::oopclasses::protos::Rect* UIElement::release_ax_frame() {
+  _has_bits_[0] &= ~0x00000002u;
+  ::gtxilib::oopclasses::protos::Rect* temp = ax_frame_;
+  ax_frame_ = nullptr;
+  if (GetArena() != nullptr) {
+    temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp);
+  }
+  return temp;
+}
+inline ::gtxilib::oopclasses::protos::Rect* UIElement::unsafe_arena_release_ax_frame() {
+  // @@protoc_insertion_point(field_release:gtxilib.oopclasses.protos.UIElement.ax_frame)
+  _has_bits_[0] &= ~0x00000002u;
+  ::gtxilib::oopclasses::protos::Rect* temp = ax_frame_;
+  ax_frame_ = nullptr;
+  return temp;
+}
+inline ::gtxilib::oopclasses::protos::Rect* UIElement::_internal_mutable_ax_frame() {
+  _has_bits_[0] |= 0x00000002u;
+  if (ax_frame_ == nullptr) {
+    auto* p = CreateMaybeMessage<::gtxilib::oopclasses::protos::Rect>(GetArena());
+    ax_frame_ = p;
+  }
+  return ax_frame_;
+}
+inline ::gtxilib::oopclasses::protos::Rect* UIElement::mutable_ax_frame() {
+  // @@protoc_insertion_point(field_mutable:gtxilib.oopclasses.protos.UIElement.ax_frame)
+  return _internal_mutable_ax_frame();
+}
+inline void UIElement::set_allocated_ax_frame(::gtxilib::oopclasses::protos::Rect* ax_frame) {
+  ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArena();
+  if (message_arena == nullptr) {
+    delete ax_frame_;
+  }
+  if (ax_frame) {
+    ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena =
+      ::PROTOBUF_NAMESPACE_ID::Arena::GetArena(ax_frame);
+    if (message_arena != submessage_arena) {
+      ax_frame = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
+          message_arena, ax_frame, submessage_arena);
+    }
+    _has_bits_[0] |= 0x00000002u;
+  } else {
+    _has_bits_[0] &= ~0x00000002u;
+  }
+  ax_frame_ = ax_frame;
+  // @@protoc_insertion_point(field_set_allocated:gtxilib.oopclasses.protos.UIElement.ax_frame)
+}
+
+// .gtxilib.oopclasses.protos.ElementType.ElementTypeEnum ax_element_type = 5;
+inline bool UIElement::_internal_has_ax_element_type() const {
+  bool value = (_has_bits_[0] & 0x00000010u) != 0;
+  return value;
+}
+inline bool UIElement::has_ax_element_type() const {
+  return _internal_has_ax_element_type();
+}
+inline void UIElement::clear_ax_element_type() {
+  ax_element_type_ = 0;
+  _has_bits_[0] &= ~0x00000010u;
+}
+inline ::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum UIElement::_internal_ax_element_type() const {
+  return static_cast< ::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum >(ax_element_type_);
+}
+inline ::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum UIElement::ax_element_type() const {
+  // @@protoc_insertion_point(field_get:gtxilib.oopclasses.protos.UIElement.ax_element_type)
+  return _internal_ax_element_type();
+}
+inline void UIElement::_internal_set_ax_element_type(::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum value) {
+  _has_bits_[0] |= 0x00000010u;
+  ax_element_type_ = value;
+}
+inline void UIElement::set_ax_element_type(::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum value) {
+  _internal_set_ax_element_type(value);
+  // @@protoc_insertion_point(field_set:gtxilib.oopclasses.protos.UIElement.ax_element_type)
+}
+
+#ifdef __GNUC__
+  #pragma GCC diagnostic pop
+#endif  // __GNUC__
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+// -------------------------------------------------------------------
+
+
+// @@protoc_insertion_point(namespace_scope)
+
+}  // namespace protos
+}  // namespace oopclasses
+}  // namespace gtxilib
+
+PROTOBUF_NAMESPACE_OPEN
+
+template <> struct is_proto_enum< ::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum> : ::std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum>() {
+  return ::gtxilib::oopclasses::protos::ElementType_ElementTypeEnum_descriptor();
+}
+
+PROTOBUF_NAMESPACE_CLOSE
+
+// @@protoc_insertion_point(global_scope)
+
+#include <google/protobuf/port_undef.inc>
+#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_gtx_2eproto
diff --git a/OOPClasses/Protos/gtx.proto b/OOPClasses/Protos/gtx.proto
new file mode 100644
index 0000000..e7bb7cb
--- /dev/null
+++ b/OOPClasses/Protos/gtx.proto
@@ -0,0 +1,135 @@
+// gtx.proto
+// Definitions for protobufs used by GTXiLib.
+
+syntax = "proto3";
+
+package gtxilib.oopclasses.protos;
+
+// Definition for Point data in 2D space.
+// Next index: 3
+message Point {
+  optional float x = 1;
+  optional float y = 2;
+}
+
+// Definition for 2D size data.
+// Next index: 3
+message Size {
+  optional float width = 1;
+  optional float height = 2;
+}
+
+// Definition for 2D rectangle data.
+// Next index: 3
+message Rect {
+  optional Point origin = 1;
+  optional Size size = 2;
+}
+
+// Protobuf equivalent for XCTest's XCUIElementType. Note that these enums are
+// named after
+// https://developer.apple.com/documentation/xctest/xcuielementtype?language=objc
+// Note: the enums are wrapped in messages to avoid name some collisions (for
+// ex: TAB_BAR).
+message ElementType {
+  enum ElementTypeEnum {
+    // Note that ANY is also the default element type for objects whose type was
+    // unknown/unspecified. For example when element is deserialized and type
+    // field was missing, the ElementType enum value will be ANY(=0).
+    ANY = 0;
+    OTHER = 1;
+    APPLICATION = 2;
+    GROUP = 3;
+    WINDOW = 4;
+    SHEET = 5;
+    DRAWER = 6;
+    ALERT = 7;
+    DIALOG = 8;
+    BUTTON = 9;
+    RADIO_BUTTON = 10;
+    RADIO_GROUP = 11;
+    CHECK_BOX = 12;
+    DISCLOSURE_TRIANGLE = 13;
+    POP_UP_BUTTON = 14;
+    COMBO_BOX = 15;
+    MENU_BUTTON = 16;
+    TOOLBAR_BUTTON = 17;
+    POPOVER = 18;
+    KEYBOARD = 19;
+    KEY = 20;
+    NAVIGATION_BAR = 21;
+    TAB_BAR = 22;
+    TAB_GROUP = 23;
+    TOOLBAR = 24;
+    STATUS_BAR = 25;
+    TABLE = 26;
+    TABLE_ROW = 27;
+    TABLE_COLUMN = 28;
+    OUTLINE = 29;
+    OUTLINE_ROW = 30;
+    BROWSER = 31;
+    COLLECTION_VIEW = 32;
+    SLIDER = 33;
+    PAGE_INDICATOR = 34;
+    PROGRESS_INDICATOR = 35;
+    ACTIVITY_INDICATOR = 36;
+    SEGMENTED_CONTROL = 37;
+    PICKER = 38;
+    PICKER_WHEEL = 39;
+    SWITCH = 40;
+    TOGGLE = 41;
+    LINK = 42;
+    IMAGE = 43;
+    ICON = 44;
+    SEARCH_FIELD = 45;
+    SCROLL_VIEW = 46;
+    SCROLL_BAR = 47;
+    STATIC_TEXT = 48;
+    TEXT_FIELD = 49;
+    SECURE_TEXT_FIELD = 50;
+    DATE_PICKER = 51;
+    TEXT_VIEW = 52;
+    MENU = 53;
+    MENU_ITEM = 54;
+    MENU_BAR = 55;
+    MENU_BAR_ITEM = 56;
+    MAP = 57;
+    WEB_VIEW = 58;
+    INCREMENT_ARROW = 59;
+    DECREMENT_ARROW = 60;
+    TIMELINE = 61;
+    RATING_INDICATOR = 62;
+    VALUE_INDICATOR = 63;
+    SPLIT_GROUP = 64;
+    SPLITTER = 65;
+    RELEVANCE_INDICATOR = 66;
+    COLOR_WELL = 67;
+    HELP_TAG = 68;
+    MATTE = 69;
+    DOCK_ITEM = 70;
+    RULER = 71;
+    RULER_MARKER = 72;
+    GRID = 73;
+    LEVEL_INDICATOR = 74;
+    CELL = 75;
+    LAYOUT_AREA = 76;
+    LAYOUT_ITEM = 77;
+    HANDLE = 78;
+    STEPPER = 79;
+    TAB = 80;
+    TOUCH_BAR = 81;
+    STATUS_ITEM = 82;
+  }
+}
+
+// Definition for UI element data. Note that the properties are intentionally
+// named to differ from UIAccessibility properties of NSObject to avoid
+// conflicts when proto is used in Objective-C.
+// Next index: 6
+message UIElement {
+  optional bool is_ax_element = 1;
+  optional uint64 ax_traits = 2;
+  optional string ax_label = 3;
+  optional Rect ax_frame = 4;
+  optional ElementType.ElementTypeEnum ax_element_type = 5;
+}
diff --git a/OOPClasses/accessibility_label_not_punctuated_check.cc b/OOPClasses/accessibility_label_not_punctuated_check.cc
new file mode 100644
index 0000000..ff59435
--- /dev/null
+++ b/OOPClasses/accessibility_label_not_punctuated_check.cc
@@ -0,0 +1,45 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "accessibility_label_not_punctuated_check.h"
+
+#include "string_utils.h"
+
+namespace gtx {
+
+bool AccessibilityLabelNotPunctuatedCheck::CheckElement(
+    const UIElement &element, const Parameters &params,
+    ErrorMessage *errorMessage) const {
+  if (element.is_text_displaying_element()) {
+    // This check is not applicable to text elements as accessibility labels can
+    // hold static text that can be punctuated and formatted like a string.
+    return true;
+  }
+  std::string accessibility_label = TrimWhitespace(element.ax_label());
+  // This check is not applicable for container elements that combine individual
+  // labels joined with commas.
+  if (accessibility_label.find(',') != std::string::npos) {
+    return true;
+  }
+  return !EndsWithInvalidPunctuation(accessibility_label);
+}
+
+bool AccessibilityLabelNotPunctuatedCheck::EndsWithInvalidPunctuation(
+    const std::string &str) const {
+  return !str.empty() && str.back() == '.';
+}
+
+}  // namespace gtx
diff --git a/OOPClasses/accessibility_label_not_punctuated_check.h b/OOPClasses/accessibility_label_not_punctuated_check.h
new file mode 100644
index 0000000..6f62cd7
--- /dev/null
+++ b/OOPClasses/accessibility_label_not_punctuated_check.h
@@ -0,0 +1,41 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_ACCESSIBILITY_LABEL_NOT_PUNCTUATED_CHECK_H_
+#define GTXILIB_OOPCLASSES_ACCESSIBILITY_LABEL_NOT_PUNCTUATED_CHECK_H_
+
+#include "check.h"
+#include "ui_element.h"
+
+namespace gtx {
+
+// Check for accessibility labels not ending with punctuation marks.
+class AccessibilityLabelNotPunctuatedCheck : public Check {
+ public:
+  AccessibilityLabelNotPunctuatedCheck(const std::string &name) : Check(name) {}
+
+  bool CheckElement(const UIElement &element, const Parameters &params,
+                    ErrorMessage *errorMessage) const override;
+
+ private:
+  // Returns true if str ends with a punctuation mark, false otherwise. Only '.'
+  // is currently recognized as a punctuation mark.
+  bool EndsWithInvalidPunctuation(const std::string &str) const;
+};
+
+}  // namespace gtx
+
+#endif
diff --git a/Tests/UnitTests/GTXBaseTestCase.h b/OOPClasses/check.cc
similarity index 62%
copy from Tests/UnitTests/GTXBaseTestCase.h
copy to OOPClasses/check.cc
index 0b4feb3..2343459 100644
--- a/Tests/UnitTests/GTXBaseTestCase.h
+++ b/OOPClasses/check.cc
@@ -1,5 +1,5 @@
 //
-// Copyright 2018 Google Inc.
+// Copyright 2020 Google Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,17 +14,12 @@
 // limitations under the License.
 //
 
-#import <UIKit/UIKit.h>
-#import <XCTest/XCTest.h>
+#include "check.h"
 
-#import "GTXCheckBlock.h"
+#include <string>
 
-extern GTXCheckHandlerBlock noOpCheckBlock;
+namespace gtx {
 
-@interface GTXBaseTestCase : XCTestCase
+Check::Check(const std::string &name) : name_(name) { assert(name.length()); }
 
-- (NSObject *)newAccessibleElement;
-- (NSObject *)newInaccessibleElement;
-- (void)createTreeFromPreOrderTraversal:(NSArray *)preOrderTraversal;
-
-@end
+}  // namespace gtx
diff --git a/OOPClasses/check.h b/OOPClasses/check.h
new file mode 100644
index 0000000..479817a
--- /dev/null
+++ b/OOPClasses/check.h
@@ -0,0 +1,51 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_CHECK_H_
+#define GTXILIB_OOPCLASSES_CHECK_H_
+
+#include <string>
+
+#include "error_message.h"
+#include "gtx_types.h"
+#include "parameters.h"
+
+namespace gtx {
+
+// Check can be used for encapsulating checking logic. To execute a check, it
+// must be registers with a @c gtx::Toolkit object and executed through it.
+class Check {
+ public:
+  // Creates a new check object, note that name must be unique, see comments for
+  // `name` property below for more details.
+  Check(const std::string &name);
+  virtual ~Check() {}
+
+  // Name of the check, must be unique in the toolkit that this check is being
+  // registered into as it will be used in logs and unique names help debug
+  // issues found by checks.
+  const std::string& name() const { return name_; }
+
+  virtual bool CheckElement(const UIElement &element, const Parameters &params,
+                            ErrorMessage *errorMessage) const = 0;
+
+ private:
+  std::string name_;
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_CHECK_H_
diff --git a/OOPClasses/check_result.cc b/OOPClasses/check_result.cc
new file mode 100644
index 0000000..0d9ca06
--- /dev/null
+++ b/OOPClasses/check_result.cc
@@ -0,0 +1,30 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "check_result.h"
+
+#include <string>
+
+namespace gtx {
+
+CheckResult::CheckResult(const ErrorMessage &error_message,
+                         const ElementRef element_ref,
+                         const std::string &check_name)
+    : error_message_(error_message),
+      element_ref_(element_ref),
+      check_name_(check_name) {}
+
+}  // namespace gtx
diff --git a/OOPClasses/check_result.h b/OOPClasses/check_result.h
new file mode 100644
index 0000000..6388ae4
--- /dev/null
+++ b/OOPClasses/check_result.h
@@ -0,0 +1,47 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_CHECK_RESULT_H_
+#define GTXILIB_OOPCLASSES_CHECK_RESULT_H_
+
+#include <string>
+
+#include "error_message.h"
+#include "gtx_types.h"
+
+namespace gtx {
+
+// Encapsulates data associated with result of performing a check.
+class CheckResult {
+ public:
+  CheckResult(const ErrorMessage &error_message, const ElementRef element_ref,
+              const std::string &check_name);
+
+  const ErrorMessage &error_message() const { return error_message_; }
+
+  const ElementRef element_ref() const { return element_ref_; }
+
+  const std::string &check_name() const { return check_name_; }
+
+ private:
+  ErrorMessage error_message_;
+  ElementRef element_ref_;
+  std::string check_name_;
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_CHECK_RESULT_H_
diff --git a/OOPClasses/contrast_check.cc b/OOPClasses/contrast_check.cc
new file mode 100644
index 0000000..582abd6
--- /dev/null
+++ b/OOPClasses/contrast_check.cc
@@ -0,0 +1,42 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "contrast_check.h"
+
+namespace gtx {
+
+/**
+ *  The minimum contrast ratio for given text to be considered accessible.
+ */
+static const float kMinContrastRatioForAccessibleText = 3.0;
+
+bool ContrastCheck::CheckElement(const UIElement &element,
+                                 const Parameters &params,
+                                 ErrorMessage *errorMessage) const {
+  if ((element.ax_traits() & ElementTrait::kStaticText) ==
+      ElementTrait::kNone) {
+    return true;
+  }
+  Rect frame(element.ax_frame());
+  Rect screenshot_bounds = params.ConvertRectToScreenshotSpace(frame);
+  ContrastSwatch swatch =
+      ContrastSwatch::Extract(params.screenshot(), screenshot_bounds);
+  float contrast_ratio = image_color_utils::ContrastRatio(
+      swatch.foreground().Luminance(), swatch.background().Luminance());
+  return contrast_ratio >= kMinContrastRatioForAccessibleText;
+}
+
+}  // namespace gtx
diff --git a/OOPClasses/contrast_check.h b/OOPClasses/contrast_check.h
new file mode 100644
index 0000000..f0e2112
--- /dev/null
+++ b/OOPClasses/contrast_check.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_CONTRAST_CHECK_H_
+#define GTXILIB_OOPCLASSES_CONTRAST_CHECK_H_
+
+#include "check.h"
+#include "contrast_swatch.h"
+#include "image_color_utils.h"
+#include "ui_element.h"
+
+namespace gtx {
+
+// Check for detecting low contrast text elements.
+class ContrastCheck : public Check {
+ public:
+  ContrastCheck(const std::string &name) : Check(name) {}
+
+  bool CheckElement(const UIElement &element, const Parameters &params,
+                    ErrorMessage *errorMessage) const override;
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_CONTRAST_CHECK_H_
diff --git a/OOPClasses/contrast_swatch.cc b/OOPClasses/contrast_swatch.cc
new file mode 100644
index 0000000..181c427
--- /dev/null
+++ b/OOPClasses/contrast_swatch.cc
@@ -0,0 +1,77 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "contrast_swatch.h"
+
+#include <unordered_map>
+
+namespace gtx {
+
+ContrastSwatch::ContrastSwatch(const Color &foreground,
+                               const Color &background) {
+  foreground_ = foreground;
+  background_ = background;
+}
+
+ContrastSwatch ContrastSwatch::Extract(const Image &image,
+                                       const Rect &sub_image_bounds) {
+  // Extract a histogram of the colors in the given image (in the given bounds).
+  // To determine the most dominant colors.
+  std::unordered_map<int32_t, int> color_histogram;
+  const int max_index = image.width * image.height;
+  for (int x = 0; x < sub_image_bounds.size.width; x++) {
+    for (int y = 0; y < sub_image_bounds.size.height; y++) {
+      int index = (x + sub_image_bounds.origin.x) +
+                  (y + sub_image_bounds.origin.y) * image.width;
+      if (index >= 0 && index < max_index) {
+        int32_t packed_color = image.pixels[index].PackedColor();
+        color_histogram[packed_color] += 1;
+      }
+    }
+  }
+
+  // The most dominant color is considered the background color. Note that the
+  // key 0 may not exist in the histogram, however for colors that dont exist
+  // the count will be zero causing tap_key to be replaced by an actual color in
+  // the histogram with count > zero.
+  int top_key = 0;
+  int penultimate_key = 0;
+  // Save the count of entires in histogram *before* processing it since
+  // accessing keys that dont exist may lead to creating the enties with count
+  // 0.
+  int64_t count = (int64_t)color_histogram.size();
+  for (auto const& [key, value] : color_histogram) {
+    if (value > color_histogram[top_key]) {
+      penultimate_key = top_key;
+      top_key = key;
+    } else if (value > color_histogram[penultimate_key]) {
+      penultimate_key = key;
+    }
+  }
+
+  Color background = Color::UnpackedColor(top_key);
+  Color foreground;
+  if (count < 2) {
+    // When image has a single color, background and foreground colors are
+    // assumed to be the same.
+    foreground = background;
+  } else {
+    foreground = Color::UnpackedColor(penultimate_key);
+  }
+  return ContrastSwatch(foreground, background);
+}
+
+}  // namespace gtx
diff --git a/OOPClasses/contrast_swatch.h b/OOPClasses/contrast_swatch.h
new file mode 100644
index 0000000..7e96363
--- /dev/null
+++ b/OOPClasses/contrast_swatch.h
@@ -0,0 +1,49 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_CONTRAST_SWATCH_H_
+#define GTXILIB_OOPCLASSES_CONTRAST_SWATCH_H_
+
+#include "gtx_types.h"
+
+namespace gtx {
+
+// Encapsulates contrast and color data associated with a section of the given
+// image data.
+class ContrastSwatch {
+ public:
+  ContrastSwatch(const Color &foreground, const Color &background);
+
+  // Extracts prominent colors (foreground and background) from the given
+  // sub-image.
+  static ContrastSwatch Extract(const Image &image,
+                                const Rect &sub_image_bounds);
+
+  // The background color in the image. Will be black if no background color
+  // could be identified.
+  const Color &background() { return background_; }
+
+  // The foreground color in the image. Will be black if no foreground color
+  // could be identified.
+  const Color &foreground() { return foreground_; }
+
+ private:
+  Color foreground_, background_;
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_CONTRAST_SWATCH_H_
diff --git a/OOPClasses/element_type.h b/OOPClasses/element_type.h
new file mode 100644
index 0000000..739079d
--- /dev/null
+++ b/OOPClasses/element_type.h
@@ -0,0 +1,30 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_ELEMENT_TYPE_H_
+#define GTXILIB_OOPCLASSES_ELEMENT_TYPE_H_
+
+#include "Protos/gtx.pb.h"
+
+namespace gtx {
+
+// Represents an XCUIElementType retrieved from an
+// XCUIElementAttributes-implementing object.
+typedef gtxilib::oopclasses::protos::ElementType
+    ElementType;
+
+}  // namespace gtx
+#endif  // GTXILIB_OOPCLASSES_ELEMENT_TYPE_H_
diff --git a/OOPClasses/error_message.cc b/OOPClasses/error_message.cc
new file mode 100644
index 0000000..2b1ac9e
--- /dev/null
+++ b/OOPClasses/error_message.cc
@@ -0,0 +1,32 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "error_message.h"
+
+#include <string>
+
+namespace gtx {
+
+typedef std::pair<LocalizedStringID, std::string> ErrorMessageDetailPair;
+
+ErrorMessage::ErrorMessage() {}
+
+void ErrorMessage::AddDetail(LocalizedStringID detail_id,
+                             const std::string &detail_value) {
+  details_.insert(ErrorMessageDetailPair(detail_id, detail_value));
+}
+
+}  // namespace gtx
diff --git a/OOPClasses/error_message.h b/OOPClasses/error_message.h
new file mode 100644
index 0000000..997fccf
--- /dev/null
+++ b/OOPClasses/error_message.h
@@ -0,0 +1,60 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_ERROR_MESSAGE_H_
+#define GTXILIB_OOPCLASSES_ERROR_MESSAGE_H_
+
+#include <map>
+#include <string>
+
+#include "gtx_types.h"
+#include "localized_strings_manager.h"
+
+namespace gtx {
+
+// ErrorMessage ecapsulates data associated with the error produced by checking
+// a single element against a single check. Data includes a localized error
+// description and a set of key value pairs that describe details associated
+// with the error.
+class ErrorMessage {
+ public:
+  ErrorMessage();
+
+  const LocalizedStringID description_id() const { return description_id_; }
+
+  void set_description_id(LocalizedStringID description_id) {
+    description_id_ = description_id;
+  }
+
+  const std::map<LocalizedStringID, std::string> &details() const {
+    return details_;
+  }
+
+  // Adds the given detail_value under the given detail_id for this error
+  // message.
+  void AddDetail(LocalizedStringID detail_id, const std::string &detail_value);
+
+ private:
+  // Localized string ID of the description for this error.
+  LocalizedStringID description_id_;
+  // Collection of key value pairs containing more details of the error (for
+  // example actual contrast ratio in a contrast check).
+  std::map<LocalizedStringID, std::string> details_;
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_ERROR_MESSAGE_H_
diff --git a/OOPClasses/gtx_types.cc b/OOPClasses/gtx_types.cc
new file mode 100644
index 0000000..e9c57d5
--- /dev/null
+++ b/OOPClasses/gtx_types.cc
@@ -0,0 +1,63 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "gtx_types.h"
+
+#include "image_color_utils.h"
+
+bool gtx::Color::operator==(const gtx::Color& other) const {
+  return (red == other.red && green == other.green && blue == other.blue &&
+          alpha == other.alpha);
+}
+
+int32_t gtx::Color::PackedColor() const {
+  int32_t red = this->red;
+  int32_t green = this->green;
+  int32_t blue = this->blue;
+  return (red << 16) | (green << 8) | (blue);
+}
+
+float gtx::Color::Luminance() const {
+  return gtx::image_color_utils::Luminance(red / 255.0, blue / 255.0,
+                                           green / 255.0);
+}
+
+gtx::Color gtx::Color::UnpackedColor(int32_t packed_color) {
+  Color unpacked_color;
+  unpacked_color.red =
+      static_cast<unsigned char>((packed_color & 0x00FF0000) >> 16);
+  unpacked_color.green =
+      static_cast<unsigned char>((packed_color & 0x0000FF00) >> 8);
+  unpacked_color.blue = static_cast<unsigned char>(packed_color & 0x000000FF);
+  unpacked_color.alpha = 255;
+  return unpacked_color;
+}
+
+gtx::Rect::Rect(
+    const gtxilib::oopclasses::protos::Rect &rect) {
+  origin.x = rect.origin().x();
+  origin.y = rect.origin().y();
+  size.width = rect.size().width();
+  size.height = rect.size().height();
+}
+
+gtx::Rect gtx::Rect::ScaledRect(float x_scale, float y_scale) const {
+  return Rect(this->origin.x * x_scale, this->origin.y * y_scale,
+              this->size.width * x_scale, this->size.height * y_scale);
+}
+
+gtx::Image::Image(gtx::Pixel *pixels, int width, int height)
+    : width(width), height(height), pixels(pixels) {}
diff --git a/OOPClasses/gtx_types.h b/OOPClasses/gtx_types.h
new file mode 100644
index 0000000..1a29ceb
--- /dev/null
+++ b/OOPClasses/gtx_types.h
@@ -0,0 +1,107 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_GTX_TYPES_H_
+#define GTXILIB_OOPCLASSES_GTX_TYPES_H_
+
+#include <math.h>
+
+#include <functional>
+#include <string>
+
+#include "Protos/gtx.pb.h"
+
+#pragma mark - Types
+
+namespace gtx {
+
+typedef gtxilib::oopclasses::protos::Rect RectData;
+
+// Forward declarations.
+class ErrorMessage;
+class UIElement;
+
+// Color is defined using rgba components for parity with pixels in @c
+// GTXImageRGBAData.
+struct Color {
+  unsigned char red, green, blue, alpha;
+
+  // Equality implementation for Colors.
+  bool operator==(const Color &other) const;
+
+  // Packs the given color into a single int32_t value. Note that the color is
+  // assumed to have alpha pre-multiplied, i.e. it is ignored.
+  int32_t PackedColor() const;
+
+  // Luminance of this color with alpha pre-multiplied, luminance is a measure
+  // of brightness, it is 0 for black color and 1 for white color.
+  float Luminance() const;
+
+  // Unpacks the color from the given packed color.
+  static Color UnpackedColor(int32_t packed_color);
+};
+typedef struct Color Pixel;
+
+// Structure to hold 2D point data, modelled after CGPoint.
+struct Point {
+  float x, y;
+  Point() : x(0), y(0){};
+  Point(float x, float y) : x(x), y(y) {}
+};
+
+// Structure to hold 2D size data, modelled after CGSize.
+struct Size {
+  float width, height;
+  Size() : width(0), height(0){};
+  Size(float width, float height) : width(width), height(height) {}
+};
+
+// Structure to hold 2D rectangle data, modelled after CGRect.
+struct Rect {
+  Point origin;
+  Size size;
+  Rect(const RectData &rect);
+  Rect() : origin(0, 0), size(0, 0) {}
+  Rect(float x, float y, float width, float height)
+      : origin(x, y), size(width, height) {}
+
+  float GetMaxX() const { return origin.x + fabs(size.width); }
+  float GetMaxY() const { return origin.y + fabs(size.height); }
+  Rect ScaledRect(float x_scale, float y_scale) const;
+};
+
+// Image is defined as a 2D block of pixels/color values.
+// TODO: Update this struct to use protobuf.
+struct Image {
+  // Dimensions of the image are in pixels.
+  int width, height;
+  Pixel *pixels;
+
+  // Constructs a new empty image.
+  Image() {}
+
+  // Constructs a new image with the given pixels and dimensions, note that
+  // pixel memory is not owned by this instance.
+  Image(Pixel *pixels, int width, int height);
+};
+
+// A reference to Objective-C element (UIView/UIAccessibilityElement) to be used
+// by checks that need to call into iOS environment when available.
+typedef void *ElementRef;
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_GTX_TYPES_H_
diff --git a/OOPClasses/image_color_utils.cc b/OOPClasses/image_color_utils.cc
new file mode 100644
index 0000000..6b27ca7
--- /dev/null
+++ b/OOPClasses/image_color_utils.cc
@@ -0,0 +1,63 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "image_color_utils.h"
+
+#include <math.h>
+
+#include <algorithm>
+
+#include "gtx_types.h"
+
+namespace gtx {
+
+namespace {
+
+// Returns color component in the appropriate range to calculate the luminance
+// of an RGB color.
+float AdjustColorComponentRangeForLuminance(float component) {
+  // Based on
+  // https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+  if (component < 0.03928f) {
+    return component / 12.92f;
+  } else {
+    return static_cast<float>(pow((component + 0.055f) / 1.055f, 2.4f));
+  }
+}
+
+}  // namespace
+
+namespace image_color_utils {
+
+float Luminance(float red, float blue, float green) {
+  // Based on
+  // https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
+  return (0.2126f * AdjustColorComponentRangeForLuminance(red) +
+          0.0722f * AdjustColorComponentRangeForLuminance(blue) +
+          0.7152f * AdjustColorComponentRangeForLuminance(green));
+}
+
+float ContrastRatio(float first_luminance, float second_luminance) {
+  assert(first_luminance >= 0);
+  assert(second_luminance >= 0);
+  float brighter_luminance = std::max(first_luminance, second_luminance);
+  float darker_luminance = std::min(first_luminance, second_luminance);
+  // Based on https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
+  return (brighter_luminance + 0.05f) / (darker_luminance + 0.05f);
+}
+
+}  // namespace image_color_utils
+}  // namespace gtx
diff --git a/OOPClasses/image_color_utils.h b/OOPClasses/image_color_utils.h
new file mode 100644
index 0000000..930300a
--- /dev/null
+++ b/OOPClasses/image_color_utils.h
@@ -0,0 +1,33 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_IMAGE_COLOR_UTILS_H_
+#define GTXILIB_OOPCLASSES_IMAGE_COLOR_UTILS_H_
+
+namespace gtx {
+namespace image_color_utils {
+
+// Returns the luminance value for the given color red, green and blue values.
+// The color values must be between 0 and 1.
+float Luminance(float red, float blue, float green);
+
+// Returns the contrast ratio for the given color luminance values.
+float ContrastRatio(float first_luminance, float second_luminance);
+
+}  // namespace image_color_utils
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_IMAGE_COLOR_UTILS_H_
diff --git a/OOPClasses/localized_strings_manager.cc b/OOPClasses/localized_strings_manager.cc
new file mode 100644
index 0000000..c46908c
--- /dev/null
+++ b/OOPClasses/localized_strings_manager.cc
@@ -0,0 +1,40 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "localized_strings_manager.h"
+
+#include <string>
+
+namespace gtx {
+
+typedef std::pair<LocalizedStringID, std::string> LocalizedStringPair;
+
+LocalizedStringsManager::LocalizedStringsManager() : localized_strings_() {
+  localized_strings_.insert(
+      LocalizedStringPair(LocalizedStringID::kEmptyString, ""));
+}
+
+const std::string &LocalizedStringsManager::LocalizedString(
+    LocalizedStringID stringID) {
+  auto string_iter = localized_strings_.find(stringID);
+  if (string_iter != localized_strings_.end()) {
+    return string_iter->second;
+  } else {
+    return localized_strings_[LocalizedStringID::kEmptyString];
+  }
+}
+
+}  // namespace gtx
diff --git a/OOPClasses/localized_strings_manager.h b/OOPClasses/localized_strings_manager.h
new file mode 100644
index 0000000..556a9ea
--- /dev/null
+++ b/OOPClasses/localized_strings_manager.h
@@ -0,0 +1,47 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_LOCALIZED_STRINGS_H_
+#define GTXILIB_OOPCLASSES_LOCALIZED_STRINGS_H_
+
+#include <map>
+#include <string>
+
+#include "gtx_types.h"
+
+namespace gtx {
+
+// List of IDs for localized strings available to GTXiLib.
+enum class LocalizedStringID {
+  // String representing an empty string.
+  kEmptyString,
+};
+
+// A collection of localized strings.
+class LocalizedStringsManager {
+ public:
+  LocalizedStringsManager();
+
+  // Returns localized string from the provided localized stringID.
+  const std::string &LocalizedString(LocalizedStringID stringID);
+
+ private:
+  std::map<LocalizedStringID, std::string> localized_strings_;
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_LOCALIZED_STRINGS_H_
diff --git a/OOPClasses/minimum_tappable_area_check.cc b/OOPClasses/minimum_tappable_area_check.cc
new file mode 100644
index 0000000..24c134a
--- /dev/null
+++ b/OOPClasses/minimum_tappable_area_check.cc
@@ -0,0 +1,39 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "minimum_tappable_area_check.h"
+
+namespace gtx {
+
+// The minimum size (width or height) for a given element to be easily
+// accessible. Please read Material design guidelines for more on touch targets:
+// https://material.io/design/layout/spacing-methods.html#touch-click-targets
+static const float kMinSizeForAccessibleElements = 44.0;
+
+bool MinimumTappableAreaCheck::CheckElement(const UIElement &element,
+                                            const Parameters &params,
+                                            ErrorMessage *errorMessage) const {
+  if ((element.ax_traits() & ElementTrait::kButton) == ElementTrait::kNone) {
+    return true;
+  }
+  if (element.ax_frame().size().width() < kMinSizeForAccessibleElements ||
+      element.ax_frame().size().height() < kMinSizeForAccessibleElements) {
+    return false;
+  }
+  return true;
+}
+
+}  // namespace gtx
diff --git a/OOPClasses/minimum_tappable_area_check.h b/OOPClasses/minimum_tappable_area_check.h
new file mode 100644
index 0000000..9a6c80a
--- /dev/null
+++ b/OOPClasses/minimum_tappable_area_check.h
@@ -0,0 +1,36 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_MINIMUM_TAPPABLE_AREA_CHECK_H_
+#define GTXILIB_OOPCLASSES_MINIMUM_TAPPABLE_AREA_CHECK_H_
+
+#include "check.h"
+#include "ui_element.h"
+
+namespace gtx {
+
+// Check for detecting small tappable areas.
+class MinimumTappableAreaCheck : public Check {
+ public:
+  MinimumTappableAreaCheck(const std::string &name) : Check(name) {}
+
+  bool CheckElement(const UIElement &element, const Parameters &params,
+                    ErrorMessage *errorMessage) const override;
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_MINIMUM_TAPPABLE_AREA_CHECK_H_
diff --git a/OOPClasses/no_label_check.h b/OOPClasses/no_label_check.h
new file mode 100644
index 0000000..f36106a
--- /dev/null
+++ b/OOPClasses/no_label_check.h
@@ -0,0 +1,38 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_NO_LABEL_CHECK_H_
+#define GTXILIB_OOPCLASSES_NO_LABEL_CHECK_H_
+
+#include "check.h"
+#include "ui_element.h"
+
+namespace gtx {
+
+// Check for detecting missing accessibility labels.
+class NoLabelCheck : public Check {
+ public:
+  NoLabelCheck(const std::string &name) : Check(name) {}
+
+  bool CheckElement(const UIElement &element, const Parameters &params,
+                    ErrorMessage *errorMessage) const override {
+    return !element.ax_label().empty();
+  }
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_NO_LABEL_CHECK_H_
diff --git a/OOPClasses/parameters.cc b/OOPClasses/parameters.cc
new file mode 100644
index 0000000..1ffcee3
--- /dev/null
+++ b/OOPClasses/parameters.cc
@@ -0,0 +1,31 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "parameters.h"
+
+namespace gtx {
+
+Rect Parameters::ConvertRectToScreenshotSpace(
+    const Rect &device_space_rect) const {
+  float x_scale =
+      static_cast<float>(screenshot_.width / device_bounds_.size.width);
+  float y_scale =
+      static_cast<float>(screenshot_.height / device_bounds_.size.height);
+  Rect converted_rect = device_space_rect.ScaledRect(x_scale, y_scale);
+  return converted_rect;
+}
+
+}  // namespace gtx
diff --git a/OOPClasses/parameters.h b/OOPClasses/parameters.h
new file mode 100644
index 0000000..664a9d9
--- /dev/null
+++ b/OOPClasses/parameters.h
@@ -0,0 +1,33 @@
+#ifndef GTXILIB_OOPCLASSES_PARAMETERS_H_
+#define GTXILIB_OOPCLASSES_PARAMETERS_H_
+
+#include "gtx_types.h"
+
+namespace gtx {
+
+// Parameters encapsulates check agnostic data such as screenshot data.
+class Parameters {
+ public:
+  // Creates a new Parameter object.
+  Parameters() {}
+
+  // Screenshot of the entire screen.
+  const Image& screenshot() const { return screenshot_; }
+  void set_screenshot(const Image& screenshot) { screenshot_ = screenshot; }
+
+  // Bounds of the device in points.
+  const Rect& device_bounds() const { return device_bounds_; }
+  void set_device_bounds(const Rect& device_bounds) {
+    device_bounds_ = device_bounds;
+  }
+
+  Rect ConvertRectToScreenshotSpace(const Rect& device_space_rect) const;
+
+ private:
+  Image screenshot_;
+  Rect device_bounds_;
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_PARAMETERS_H_
diff --git a/OOPClasses/string_utils.cc b/OOPClasses/string_utils.cc
new file mode 100644
index 0000000..be422fb
--- /dev/null
+++ b/OOPClasses/string_utils.cc
@@ -0,0 +1,32 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "string_utils.h"
+
+namespace gtx {
+
+std::string TrimWhitespace(std::string str) {
+  auto first_nonwhitespace_iter =
+      std::find_if_not(str.begin(), str.end(), std::isspace);
+  auto trimmed_leading = str.substr(first_nonwhitespace_iter - str.begin(),
+                                    str.end() - first_nonwhitespace_iter);
+  auto last_nonwhitespace_iter = std::find_if_not(
+      trimmed_leading.rbegin(), trimmed_leading.rend(), std::isspace);
+  return trimmed_leading.substr(
+      0, trimmed_leading.rend() - last_nonwhitespace_iter);
+}
+
+}  // namespace gtx
diff --git a/Tests/UnitTests/GTXBaseTestCase.h b/OOPClasses/string_utils.h
similarity index 61%
copy from Tests/UnitTests/GTXBaseTestCase.h
copy to OOPClasses/string_utils.h
index 0b4feb3..07c8399 100644
--- a/Tests/UnitTests/GTXBaseTestCase.h
+++ b/OOPClasses/string_utils.h
@@ -1,5 +1,5 @@
 //
-// Copyright 2018 Google Inc.
+// Copyright 2020 Google Inc.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -14,17 +14,11 @@
 // limitations under the License.
 //
 
-#import <UIKit/UIKit.h>
-#import <XCTest/XCTest.h>
+#import <string>
 
-#import "GTXCheckBlock.h"
+namespace gtx {
 
-extern GTXCheckHandlerBlock noOpCheckBlock;
+// Returns the given string with all leading and trailing whitespace removed.
+std::string TrimWhitespace(std::string str);
 
-@interface GTXBaseTestCase : XCTestCase
-
-- (NSObject *)newAccessibleElement;
-- (NSObject *)newInaccessibleElement;
-- (void)createTreeFromPreOrderTraversal:(NSArray *)preOrderTraversal;
-
-@end
+}  // namespace gtx
diff --git a/OOPClasses/toolkit.cc b/OOPClasses/toolkit.cc
new file mode 100644
index 0000000..0dd06e1
--- /dev/null
+++ b/OOPClasses/toolkit.cc
@@ -0,0 +1,99 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "toolkit.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "accessibility_label_not_punctuated_check.h"
+#include "contrast_check.h"
+#include "minimum_tappable_area_check.h"
+#include "no_label_check.h"
+
+namespace gtx {
+
+std::unique_ptr<Toolkit> Toolkit::ToolkitWithAllDefaultChecks() {
+  auto toolkit = std::make_unique<Toolkit>();
+  std::unique_ptr<Check> no_label_check(new NoLabelCheck("NoLabelCheck"));
+  toolkit->RegisterCheck(no_label_check);
+  std::unique_ptr<Check> minimum_tappable_area_check(
+      new MinimumTappableAreaCheck("MinimumTappableAreaCheck"));
+  toolkit->RegisterCheck(minimum_tappable_area_check);
+  std::unique_ptr<Check> contrast_check(new ContrastCheck("ContrastCheck"));
+  toolkit->RegisterCheck(contrast_check);
+  std::unique_ptr<Check> accessibility_label_not_punctuated(
+      new AccessibilityLabelNotPunctuatedCheck(
+          "AccessibilityLabelNotPunctuatedCheck"));
+  toolkit->RegisterCheck(accessibility_label_not_punctuated);
+  return toolkit;
+}
+
+void Toolkit::RegisterCheck(std::unique_ptr<Check> &check) {
+  // Look for duplicate checks before adding a new check.
+  const std::string &check_name = check->name();
+  for (const auto &registered_check : registered_checks_) {
+    const std::string &registered_check_name = registered_check->name();
+    assert(check_name != registered_check_name);
+  }
+
+  registered_checks_.push_back(std::move(check));
+}
+
+const gtx::Check &Toolkit::GetRegisteredCheckNamed(
+    const std::string &check_name) const {
+  for (auto &check : registered_checks_) {
+    if (check->name() == check_name) {
+      return *check;
+    }
+  }
+  assert(false);
+  Check *null_check = nullptr;
+  return *null_check;
+}
+
+std::vector<CheckResult> Toolkit::CheckElement(const UIElement &element,
+                                               const Parameters &params) {
+  std::vector<CheckResult> result;
+  if (!element.is_ax_element()) {
+    // Currently all checks are only applicable to accessibility elements.
+    return result;
+  }
+
+  for (const auto &check : registered_checks_) {
+    ErrorMessage single_check_result;
+    if (!check->CheckElement(element, params, &single_check_result)) {
+      result.push_back(
+          CheckResult(single_check_result, nullptr, check->name()));
+    }
+  }
+  return result;
+}
+
+std::vector<CheckResult> Toolkit::CheckElements(
+    const std::vector<UIElement> &elements, const Parameters &params) {
+  std::vector<CheckResult> result;
+  for (const auto &element : elements) {
+    auto errors = CheckElement(element, params);
+    if (!errors.empty()) {
+      result.insert(result.end(), errors.begin(), errors.end());
+    }
+  }
+  return result;
+}
+
+}  // namespace gtx
diff --git a/OOPClasses/toolkit.h b/OOPClasses/toolkit.h
new file mode 100644
index 0000000..9ef6981
--- /dev/null
+++ b/OOPClasses/toolkit.h
@@ -0,0 +1,66 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_TOOLKIT_H_
+#define GTXILIB_OOPCLASSES_TOOLKIT_H_
+
+#include <vector>
+
+#include "check.h"
+#include "check_result.h"
+#include "parameters.h"
+#include "ui_element.h"
+
+namespace gtx {
+
+// Toolkit can be used for custom implementation of a checking mechanism, @class
+// GTXiLib uses Toolkit for performing the checks on provided elements.
+class Toolkit {
+ public:
+  Toolkit() {}
+
+  // Creates a new toolkit object with all the default checks registered.
+  static std::unique_ptr<Toolkit> ToolkitWithAllDefaultChecks();
+
+  // Registers the given check to be executed on all elements this instance is
+  // used on, registering checks with the same name throws an assertion.
+  void RegisterCheck(std::unique_ptr<Check> &check);
+
+  // Returns a const reference to check that has been registered under the given
+  // @c name, behavior is undefined if no such check exists.
+  const gtx::Check &GetRegisteredCheckNamed(
+      const std::string &check_name) const;
+
+  // Applies all the registered checks on the given element and returns an
+  // (unique pointer to) array of CheckResult objects, if no errors were found
+  // nullptr will be returned.
+  std::vector<CheckResult> CheckElement(const UIElement &element,
+                                        const Parameters &params);
+
+  // Applies all the registered checks on all the given list of elements and
+  // returns an (unique pointer to) array of CheckResult objects, if no errors
+  // were found nullptr will be returned.
+  std::vector<CheckResult> CheckElements(const std::vector<UIElement> &elements,
+                                         const Parameters &params);
+
+ private:
+  // Collection of all the registered checks.
+  std::vector<std::unique_ptr<Check>> registered_checks_;
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_TOOLKIT_H_
diff --git a/OOPClasses/ui_element.cc b/OOPClasses/ui_element.cc
new file mode 100644
index 0000000..7d09abf
--- /dev/null
+++ b/OOPClasses/ui_element.cc
@@ -0,0 +1,74 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ui_element.h"
+
+namespace gtx {
+
+void UIElement::set_is_ax_element(bool is_ax_element) {
+  ax_data_.set_is_ax_element(is_ax_element);
+}
+
+bool UIElement::is_ax_element() const { return ax_data_.is_ax_element(); }
+
+const std::string &UIElement::ax_label() const { return ax_data_.ax_label(); }
+
+void UIElement::set_ax_label(const std::string &ax_label) {
+  ax_data_.set_ax_label(ax_label);
+}
+
+void UIElement::set_ax_traits(gtx::ElementTrait ax_traits) {
+  ax_data_.set_ax_traits((int64_t)ax_traits);
+}
+
+gtx::ElementTrait UIElement::ax_traits() const {
+  return (gtx::ElementTrait)ax_data_.ax_traits();
+}
+
+const RectData &UIElement::ax_frame() const { return ax_data_.ax_frame(); }
+
+void UIElement::set_ax_frame(const RectData &ax_frame) {
+  ax_data_.mutable_ax_frame()->CopyFrom(ax_frame);
+}
+
+ElementType::ElementTypeEnum UIElement::element_type() const {
+  return ax_data_.ax_element_type();
+}
+
+void UIElement::set_element_type(ElementType::ElementTypeEnum element_type) {
+  ax_data_.set_ax_element_type(element_type);
+}
+
+bool UIElement::is_text_displaying_element() const {
+  gtx::ElementTrait ax_traits = this->ax_traits();
+  if ((ax_traits & ElementTrait::kStaticText) != ElementTrait::kNone ||
+      (ax_traits & ElementTrait::kLink) != ElementTrait::kNone ||
+      (ax_traits & ElementTrait::kSearchField) != ElementTrait::kNone ||
+      (ax_traits & ElementTrait::kKeyboardKey) != ElementTrait::kNone) {
+    return true;
+  }
+  ElementType::ElementTypeEnum element_type = this->element_type();
+  if (element_type == ElementType::STATIC_TEXT ||
+      element_type == ElementType::TEXT_FIELD ||
+      element_type == ElementType::TEXT_VIEW) {
+    return true;
+  }
+  // TODO: Account for elements representing accessibility elements
+  // in a container which is a text field.
+  return false;
+}
+
+}  // namespace gtx
diff --git a/OOPClasses/ui_element.h b/OOPClasses/ui_element.h
new file mode 100644
index 0000000..fab1678
--- /dev/null
+++ b/OOPClasses/ui_element.h
@@ -0,0 +1,115 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef GTXILIB_OOPCLASSES_UI_ELEMENT_H_
+#define GTXILIB_OOPCLASSES_UI_ELEMENT_H_
+
+#include <optional>
+#include <string>
+
+#include "Protos/gtx.pb.h"
+#include "element_type.h"
+#include "gtx_types.h"
+
+namespace gtx {
+
+typedef gtxilib::oopclasses::protos::UIElement
+    UIElementData;
+using gtxilib::oopclasses::protos::ElementType;
+
+// An enum representing a traits (cpp equivalent for UIAccessibilityTraits).
+enum class ElementTrait {
+  // UIAccessibilityTraitNone equivalent.
+  kNone = 0,
+  // UIAccessibilityTraitButton equivalent.
+  kButton = 1 << 0,
+  // UIAccessibilityTraitLink equivalent.
+  kLink = 1 << 1,
+  // UIAccessibilityTraitSearchField equivalent.
+  kSearchField = 1 << 2,
+  // UIAccessibilityTraitImage equivalent.
+  kImage = 1 << 3,
+  // UIAccessibilityTraitSelected equivalent.
+  kSelected = 1 << 4,
+  // UIAccessibilityTraitPlaysSound equivalent.
+  kPlaysSound = 1 << 5,
+  // UIAccessibilityTraitKeyboardKey equivalent.
+  kKeyboardKey = 1 << 6,
+  // UIAccessibilityTraitStaticText equivalent.
+  kStaticText = 1 << 7,
+  // UIAccessibilityTraitSummaryElement equivalent.
+  kSummaryElement = 1 << 8,
+  // UIAccessibilityTraitNotEnabled equivalent.
+  kNotEnabled = 1 << 9,
+  // UIAccessibilityTraitUpdatesFrequently equivalent.
+  kUpdatesFrequently = 1 << 10,
+  // UIAccessibilityTraitStartsMediaSession equivalent.
+  kStartsMediaSession = 1 << 11,
+  // UIAccessibilityTraitAdjustable equivalent.
+  kAdjustable = 1 << 12,
+  // UIAccessibilityTraitAllowsDirectInteraction equivalent.
+  kAllowsDirectInteraction = 1 << 13,
+  // UIAccessibilityTraitCausesPageTurn equivalent.
+  kCausesPageTurn = 1 << 14,
+  // UIAccessibilityTraitHeader equivalent.
+  kHeader = 1 << 15,
+};
+
+// Bitwise 'or' operators for ElementTrait enum.
+constexpr ElementTrait operator|(ElementTrait a, ElementTrait b) {
+  return static_cast<ElementTrait>(static_cast<int>(a) | static_cast<int>(b));
+}
+
+// Bitwise 'and' operators for ElementTrait enum.
+constexpr ElementTrait operator&(ElementTrait a, ElementTrait b) {
+  return static_cast<ElementTrait>(static_cast<int>(a) & static_cast<int>(b));
+}
+
+// UIElement encapsulates all the information associated wth a single element on
+// the screen that is needed for checks to run. Note that this means that
+// UIElement can inclue info from any of: UIView, UIAccessibilityElement,
+// XCUIElement etc.
+class UIElement {
+ public:
+  UIElement() {}
+
+  void set_is_ax_element(bool is_ax_element);
+  bool is_ax_element() const;
+
+  const std::string &ax_label() const;
+  void set_ax_label(const std::string &ax_label);
+
+  void set_ax_traits(ElementTrait ax_traits);
+  ElementTrait ax_traits() const;
+
+  const RectData &ax_frame() const;
+  void set_ax_frame(const RectData &ax_frame);
+  // TODO: Add all the properties needed for all of the default
+  // accessibility checks to run.
+
+  ElementType::ElementTypeEnum element_type() const;
+  void set_element_type(ElementType::ElementTypeEnum element_type);
+
+  // Returns true if the element displays visible text, false otherwise.
+  bool is_text_displaying_element() const;
+
+ private:
+  UIElementData ax_data_;
+};
+
+}  // namespace gtx
+
+#endif  // GTXILIB_OOPCLASSES_UI_ELEMENT_H_
diff --git a/README.md b/README.md
index d24bbb0..c5c541e 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,7 @@
   // Install GTX on all tests in *this* test class.
   [GTXiLib installOnTestSuite:[GTXTestSuite suiteWithAllTestsInClass:self]
                        checks:checksToBeInstalled
-            elementBlacklists:@[]];
+          elementExcludeLists:@[]];
 }
 ```
 
@@ -66,7 +66,7 @@
 // Install GTX on all tests in *this* test class.
 [GTXiLib installOnTestSuite:[GTXTestSuite suiteWithAllTestsInClass:self]
                      checks:checksToBeInstalled
-          elementBlacklists:@[]];
+        elementExcludeLists:@[]];
 ```
 
 Note that GTX is being added to `+setUp` method, not the instance method
@@ -85,7 +85,7 @@
 
 + Use the above snippet to add GTXiLib to all test cases but fix errors in a small
   subset of them.
-  + Blacklist elements that you don't control using GTXiLib's blacklist APIs.
+  + Exclude elements that you don't control using GTXiLib's excludeList APIs.
 + Then use `GTXTestSuite's` `suiteWithClass:andTests:` method to
   create a test suite with only the tests cases that have been fixed and add
   GTXiLib only to that suite.
@@ -121,9 +121,9 @@
 it. But due to various team priorities it may not be possible to do so right
 away in which case you have the following options at your disposal:
 
-+ Temporarily blacklist the test case by using
++ Temporarily exclude the test case by using
   `suiteWithAllTestsInClass:exceptTests:`.
-+ Temporarily blacklist the offending element using element blacklist APIs.
++ Temporarily exclude the offending element using element excludeList APIs.
 
 But if you believe GTXiLib has caught a bug that is not an accessibility issue
 please let us know by [filing a bug](https://github.com/google/GTXiLib/issues)
diff --git a/Tests/Common/OOPTestLib/GTXUITestBaseTest.h b/Tests/Common/OOPTestLib/GTXUITestBaseTest.h
new file mode 100644
index 0000000..cf15502
--- /dev/null
+++ b/Tests/Common/OOPTestLib/GTXUITestBaseTest.h
@@ -0,0 +1,48 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <UIKit/UIKit.h>
+#import <XCTest/XCTest.h>
+
+#import "GTXTestViewController.h"
+
+/**
+ Base test for all GTXiLib functional/integration tests used to setup GTXiLib and capture check
+ failures.
+ */
+@interface GTXUITestBaseTest : XCTestCase
+
+/**
+ Clears the test area in teardown if @c YES, default value is @c YES.
+ */
+@property(nonatomic, assign, getter=shouldClearTestAreaOnTeardown) BOOL clearTestAreaOnTeardown;
+
+/**
+ Performs the action named @c actionName by scrolling to the appropriate action.
+ */
+- (void)performTestActionNamed:(NSString *)actionName;
+
+/**
+ Clears the test area.
+ */
+- (void)clearTestArea;
+
+/**
+ Runs all the GTX checks on the test element.
+ */
+- (BOOL)runAllGTXChecksOnTestElement;
+
+@end
diff --git a/Tests/Common/OOPTestLib/GTXUITestBaseTest.mm b/Tests/Common/OOPTestLib/GTXUITestBaseTest.mm
new file mode 100644
index 0000000..e186fca
--- /dev/null
+++ b/Tests/Common/OOPTestLib/GTXUITestBaseTest.mm
@@ -0,0 +1,109 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXUITestBaseTest.h"
+
+#import "GTXImageRGBAData+GTXOOPAdditions.h"
+#import "NSObject+GTXAdditions.h"
+#import "NSString+GTXAdditions.h"
+#include "toolkit.h"
+
+#import "XCUIElement+GTXTestAdditions.h"
+#import "GTXTestViewController.h"
+
+/**
+ *  Max time to wait for the app to start (come to foreground) for testing.
+ */
+static const NSTimeInterval kGTXTestAppStartTimeout = 3.0;
+
+/**
+ *  Max time to wait for the test to finish search action (for example scroll up/down to find an
+ *  element).
+ */
+static const NSTimeInterval kGTXTestSearchActionTimeout = 5.0;
+
+@implementation GTXUITestBaseTest {
+  XCUIApplication *_app;
+}
+
+- (void)setUp {
+  [super setUp];
+
+  _app = [[XCUIApplication alloc] init];
+  static dispatch_once_t onceToken;
+  dispatch_once(&onceToken, ^{
+    [_app launch];
+    XCTAssertTrue([_app waitForState:XCUIApplicationStateRunningForeground
+                             timeout:kGTXTestAppStartTimeout]);
+  });
+  self.clearTestAreaOnTeardown = YES;
+}
+
+- (void)tearDown {
+  if (self.shouldClearTestAreaOnTeardown) {
+    [self clearTestArea];
+  }
+
+  [super tearDown];
+}
+
+- (void)clearTestArea {
+  [_app.buttons[kGTXTestAppClearTestAreaID] tap];
+}
+
+- (void)performTestActionNamed:(NSString *)actionName {
+  if (_app.buttons[actionName].isHittable) {
+    [_app.buttons[actionName] tap];
+  } else {
+    [_app.buttons[kGTXTestAppScrollToTopID] tap];
+  }
+  XCUIElement *scrollView = _app.scrollViews[kGTXTestAppActionsContainerID];
+  NSTimeInterval timeoutTime =
+      [NSDate timeIntervalSinceReferenceDate] + kGTXTestSearchActionTimeout;
+  while (!_app.buttons[actionName].isHittable &&
+         [NSDate timeIntervalSinceReferenceDate] < timeoutTime) {
+    XCUICoordinate *start = [scrollView coordinateWithNormalizedOffset:CGVectorMake(0.5, 0.5)];
+    XCUICoordinate *end =
+        [start coordinateWithOffset:CGVectorMake(0, -scrollView.frame.size.height)];
+    [start pressForDuration:0.01 thenDragToCoordinate:end];
+  }
+  [_app.buttons[actionName] tap];
+}
+
+- (BOOL)runAllGTXChecksOnTestElement {
+  NSArray<XCUIElement *> *otherElements = [[[_app descendantsMatchingType:XCUIElementTypeAny]
+      matchingIdentifier:kGTXTestTestingElementID] allElementsBoundByIndex];
+  UIAccessibilityElement *testElement =
+      [otherElements.firstObject gtxtest_accessibilityElementWithContainer:_app];
+  if (!testElement) {
+    return YES;
+  }
+  auto toolkit = gtx::Toolkit::ToolkitWithAllDefaultChecks();
+  gtx::Parameters params;
+  XCUIScreenshot *screenshot = XCUIScreen.mainScreen.screenshot;
+  GTXImageRGBAData *rgbaData = [[GTXImageRGBAData alloc] initWithUIImage:screenshot.image];
+  auto gtxImage = [rgbaData gtxImage];
+  params.set_screenshot(*gtxImage);
+  // Use screenshot to infer device size since UIScreen.mainScreen.bounds may not work from test
+  // process.
+  // TODO: Add radar ref once filed.
+  gtx::Rect gtxDeviceBounds = gtx::Rect(0, 0, rgbaData.width, rgbaData.height);
+  float scale = 1.0 / UIScreen.mainScreen.scale;
+  params.set_device_bounds(gtxDeviceBounds.ScaledRect(scale, scale));
+  return toolkit->CheckElement(*[testElement gtx_UIElement], params).empty();
+}
+
+@end
diff --git a/Tests/Common/OOPTestLib/XCUIElement+GTXTestAdditions.h b/Tests/Common/OOPTestLib/XCUIElement+GTXTestAdditions.h
new file mode 100644
index 0000000..97cb37d
--- /dev/null
+++ b/Tests/Common/OOPTestLib/XCUIElement+GTXTestAdditions.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import <XCTest/XCTest.h>
+
+#include "element_type.h"
+#include "ui_element.h"
+
+@interface XCUIElement (GTXTestAdditions)
+
+- (UIAccessibilityElement *)gtxtest_accessibilityElementWithContainer:(id)container;
+
+/**
+ * @return A @c gtx::UIElement representing this element.
+ */
+- (std::unique_ptr<gtx::UIElement>)gtxtest_UIElement;
+
+/**
+ * Converts an @c XCUIElementType to its corresponding @c gtx::ElementType value.
+ * @param elementType The @c XCUIElementType to convert.
+ * @return A @c gtx::ElementType::ElementTypeEnum value corresponding to @c elementType.
+ */
++ (gtx::ElementType::ElementTypeEnum)gtxtest_elementTypeFromXCUIElementType:
+    (XCUIElementType)elementType;
+
+@end
diff --git a/Tests/Common/OOPTestLib/XCUIElement+GTXTestAdditions.mm b/Tests/Common/OOPTestLib/XCUIElement+GTXTestAdditions.mm
new file mode 100644
index 0000000..bfb7aa7
--- /dev/null
+++ b/Tests/Common/OOPTestLib/XCUIElement+GTXTestAdditions.mm
@@ -0,0 +1,246 @@
+//
+// Copyright 2020 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "XCUIElement+GTXTestAdditions.h"
+
+#import "NSString+GTXAdditions.h"
+
+@implementation XCUIElement (GTXTestAdditions)
+
+// TODO: Update this code to accurately capture the hierarchy, sometimes we seem to be
+// getting duplicate entries.
+- (UIAccessibilityElement *)gtxtest_accessibilityElementWithContainer:(id)container {
+  UIAccessibilityElement *element =
+      [[UIAccessibilityElement alloc] initWithAccessibilityContainer:container];
+  element.accessibilityLabel = [self label];
+  element.accessibilityFrame = [self frame];
+  element.accessibilityIdentifier = [self identifier];
+  element.accessibilityTraits = [self gtxtest_accessibilityTraits];
+  NSMutableArray<UIAccessibilityElement *> *children;
+  NSArray<XCUIElement *> *decendents =
+      [[self descendantsMatchingType:XCUIElementTypeAny] allElementsBoundByIndex];
+  for (XCUIElement *element in decendents) {
+    if (!children) {
+      children = [[NSMutableArray alloc] init];
+    }
+    UIAccessibilityElement *child = [element gtxtest_accessibilityElementWithContainer:element];
+    [children addObject:child];
+  }
+  element.accessibilityElements = children;
+  element.isAccessibilityElement = children.count ? NO : YES;
+  return element;
+}
+
+- (UIAccessibilityTraits)gtxtest_accessibilityTraits {
+  UIAccessibilityTraits traits = 0;
+  if (self.elementType == XCUIElementTypeStaticText) {
+    traits |= UIAccessibilityTraitStaticText;
+  }
+  if (self.elementType == XCUIElementTypeButton) {
+    traits |= UIAccessibilityTraitButton;
+  }
+  return traits;
+}
+
+- (std::unique_ptr<gtx::UIElement>)gtxtest_UIElement {
+  BOOL hasChildren = [[self childrenMatchingType:XCUIElementTypeAny] count];
+  auto element = std::make_unique<gtx::UIElement>();
+  element->set_is_ax_element(hasChildren ? true : false);
+  element->set_ax_label([[self label] gtx_stdString]);
+  gtx::RectData rectData;
+  rectData.mutable_size()->set_width(self.frame.size.width);
+  rectData.mutable_size()->set_height(self.frame.size.height);
+  rectData.mutable_origin()->set_x(self.frame.origin.x);
+  rectData.mutable_origin()->set_y(self.frame.origin.y);
+  element->set_ax_frame(rectData);
+  element->set_element_type([XCUIElement gtxtest_elementTypeFromXCUIElementType:self.elementType]);
+  return element;
+}
+
++ (gtx::ElementType::ElementTypeEnum)gtxtest_elementTypeFromXCUIElementType:
+    (XCUIElementType)elementType {
+  if (elementType == XCUIElementTypeAny) {
+    return gtx::ElementType::ANY;
+  } else if (elementType == XCUIElementTypeOther) {
+    return gtx::ElementType::OTHER;
+  } else if (elementType == XCUIElementTypeApplication) {
+    return gtx::ElementType::APPLICATION;
+  } else if (elementType == XCUIElementTypeGroup) {
+    return gtx::ElementType::GROUP;
+  } else if (elementType == XCUIElementTypeWindow) {
+    return gtx::ElementType::WINDOW;
+  } else if (elementType == XCUIElementTypeSheet) {
+    return gtx::ElementType::SHEET;
+  } else if (elementType == XCUIElementTypeDrawer) {
+    return gtx::ElementType::DRAWER;
+  } else if (elementType == XCUIElementTypeAlert) {
+    return gtx::ElementType::ALERT;
+  } else if (elementType == XCUIElementTypeDialog) {
+    return gtx::ElementType::DIALOG;
+  } else if (elementType == XCUIElementTypeButton) {
+    return gtx::ElementType::BUTTON;
+  } else if (elementType == XCUIElementTypeRadioButton) {
+    return gtx::ElementType::RADIO_BUTTON;
+  } else if (elementType == XCUIElementTypeRadioGroup) {
+    return gtx::ElementType::RADIO_GROUP;
+  } else if (elementType == XCUIElementTypeCheckBox) {
+    return gtx::ElementType::CHECK_BOX;
+  } else if (elementType == XCUIElementTypeDisclosureTriangle) {
+    return gtx::ElementType::DISCLOSURE_TRIANGLE;
+  } else if (elementType == XCUIElementTypePopUpButton) {
+    return gtx::ElementType::POP_UP_BUTTON;
+  } else if (elementType == XCUIElementTypeComboBox) {
+    return gtx::ElementType::COMBO_BOX;
+  } else if (elementType == XCUIElementTypeMenuButton) {
+    return gtx::ElementType::MENU_BUTTON;
+  } else if (elementType == XCUIElementTypeToolbarButton) {
+    return gtx::ElementType::TOOLBAR_BUTTON;
+  } else if (elementType == XCUIElementTypePopover) {
+    return gtx::ElementType::POPOVER;
+  } else if (elementType == XCUIElementTypeKeyboard) {
+    return gtx::ElementType::KEYBOARD;
+  } else if (elementType == XCUIElementTypeKey) {
+    return gtx::ElementType::KEY;
+  } else if (elementType == XCUIElementTypeNavigationBar) {
+    return gtx::ElementType::NAVIGATION_BAR;
+  } else if (elementType == XCUIElementTypeTabBar) {
+    return gtx::ElementType::TAB_BAR;
+  } else if (elementType == XCUIElementTypeTabGroup) {
+    return gtx::ElementType::TAB_GROUP;
+  } else if (elementType == XCUIElementTypeToolbar) {
+    return gtx::ElementType::TOOLBAR;
+  } else if (elementType == XCUIElementTypeStatusBar) {
+    return gtx::ElementType::STATUS_BAR;
+  } else if (elementType == XCUIElementTypeTable) {
+    return gtx::ElementType::TABLE;
+  } else if (elementType == XCUIElementTypeTableRow) {
+    return gtx::ElementType::TABLE_ROW;
+  } else if (elementType == XCUIElementTypeTableColumn) {
+    return gtx::ElementType::TABLE_COLUMN;
+  } else if (elementType == XCUIElementTypeOutline) {
+    return gtx::ElementType::OUTLINE;
+  } else if (elementType == XCUIElementTypeOutlineRow) {
+    return gtx::ElementType::OUTLINE_ROW;
+  } else if (elementType == XCUIElementTypeBrowser) {
+    return gtx::ElementType::BROWSER;
+  } else if (elementType == XCUIElementTypeCollectionView) {
+    return gtx::ElementType::COLLECTION_VIEW;
+  } else if (elementType == XCUIElementTypeSlider) {
+    return gtx::ElementType::SLIDER;
+  } else if (elementType == XCUIElementTypePageIndicator) {
+    return gtx::ElementType::PAGE_INDICATOR;
+  } else if (elementType == XCUIElementTypeProgressIndicator) {
+    return gtx::ElementType::PROGRESS_INDICATOR;
+  } else if (elementType == XCUIElementTypeActivityIndicator) {
+    return gtx::ElementType::ACTIVITY_INDICATOR;
+  } else if (elementType == XCUIElementTypeSegmentedControl) {
+    return gtx::ElementType::SEGMENTED_CONTROL;
+  } else if (elementType == XCUIElementTypePicker) {
+    return gtx::ElementType::PICKER;
+  } else if (elementType == XCUIElementTypePickerWheel) {
+    return gtx::ElementType::PICKER_WHEEL;
+  } else if (elementType == XCUIElementTypeSwitch) {
+    return gtx::ElementType::SWITCH;
+  } else if (elementType == XCUIElementTypeToggle) {
+    return gtx::ElementType::TOGGLE;
+  } else if (elementType == XCUIElementTypeLink) {
+    return gtx::ElementType::LINK;
+  } else if (elementType == XCUIElementTypeImage) {
+    return gtx::ElementType::IMAGE;
+  } else if (elementType == XCUIElementTypeIcon) {
+    return gtx::ElementType::ICON;
+  } else if (elementType == XCUIElementTypeSearchField) {
+    return gtx::ElementType::SEARCH_FIELD;
+  } else if (elementType == XCUIElementTypeScrollView) {
+    return gtx::ElementType::SCROLL_VIEW;
+  } else if (elementType == XCUIElementTypeScrollBar) {
+    return gtx::ElementType::SCROLL_BAR;
+  } else if (elementType == XCUIElementTypeStaticText) {
+    return gtx::ElementType::STATIC_TEXT;
+  } else if (elementType == XCUIElementTypeTextField) {
+    return gtx::ElementType::TEXT_FIELD;
+  } else if (elementType == XCUIElementTypeSecureTextField) {
+    return gtx::ElementType::SECURE_TEXT_FIELD;
+  } else if (elementType == XCUIElementTypeDatePicker) {
+    return gtx::ElementType::DATE_PICKER;
+  } else if (elementType == XCUIElementTypeTextView) {
+    return gtx::ElementType::TEXT_VIEW;
+  } else if (elementType == XCUIElementTypeMenu) {
+    return gtx::ElementType::MENU;
+  } else if (elementType == XCUIElementTypeMenuItem) {
+    return gtx::ElementType::MENU_ITEM;
+  } else if (elementType == XCUIElementTypeMenuBar) {
+    return gtx::ElementType::MENU_BAR;
+  } else if (elementType == XCUIElementTypeMenuBarItem) {
+    return gtx::ElementType::MENU_BAR_ITEM;
+  } else if (elementType == XCUIElementTypeMap) {
+    return gtx::ElementType::MAP;
+  } else if (elementType == XCUIElementTypeWebView) {
+    return gtx::ElementType::WEB_VIEW;
+  } else if (elementType == XCUIElementTypeIncrementArrow) {
+    return gtx::ElementType::INCREMENT_ARROW;
+  } else if (elementType == XCUIElementTypeDecrementArrow) {
+    return gtx::ElementType::DECREMENT_ARROW;
+  } else if (elementType == XCUIElementTypeTimeline) {
+    return gtx::ElementType::TIMELINE;
+  } else if (elementType == XCUIElementTypeRatingIndicator) {
+    return gtx::ElementType::RATING_INDICATOR;
+  } else if (elementType == XCUIElementTypeValueIndicator) {
+    return gtx::ElementType::VALUE_INDICATOR;
+  } else if (elementType == XCUIElementTypeSplitGroup) {
+    return gtx::ElementType::SPLIT_GROUP;
+  } else if (elementType == XCUIElementTypeSplitter) {
+    return gtx::ElementType::SPLITTER;
+  } else if (elementType == XCUIElementTypeRelevanceIndicator) {
+    return gtx::ElementType::RELEVANCE_INDICATOR;
+  } else if (elementType == XCUIElementTypeColorWell) {
+    return gtx::ElementType::COLOR_WELL;
+  } else if (elementType == XCUIElementTypeHelpTag) {
+    return gtx::ElementType::HELP_TAG;
+  } else if (elementType == XCUIElementTypeMatte) {
+    return gtx::ElementType::MATTE;
+  } else if (elementType == XCUIElementTypeDockItem) {
+    return gtx::ElementType::DOCK_ITEM;
+  } else if (elementType == XCUIElementTypeRuler) {
+    return gtx::ElementType::RULER;
+  } else if (elementType == XCUIElementTypeRulerMarker) {
+    return gtx::ElementType::RULER_MARKER;
+  } else if (elementType == XCUIElementTypeGrid) {
+    return gtx::ElementType::GRID;
+  } else if (elementType == XCUIElementTypeLevelIndicator) {
+    return gtx::ElementType::LEVEL_INDICATOR;
+  } else if (elementType == XCUIElementTypeCell) {
+    return gtx::ElementType::CELL;
+  } else if (elementType == XCUIElementTypeLayoutArea) {
+    return gtx::ElementType::LAYOUT_AREA;
+  } else if (elementType == XCUIElementTypeLayoutItem) {
+    return gtx::ElementType::LAYOUT_ITEM;
+  } else if (elementType == XCUIElementTypeHandle) {
+    return gtx::ElementType::HANDLE;
+  } else if (elementType == XCUIElementTypeStepper) {
+    return gtx::ElementType::STEPPER;
+  } else if (elementType == XCUIElementTypeTab) {
+    return gtx::ElementType::TAB;
+  } else if (elementType == XCUIElementTypeTouchBar) {
+    return gtx::ElementType::TOUCH_BAR;
+  } else if (elementType == XCUIElementTypeStatusItem) {
+    return gtx::ElementType::STATUS_ITEM;
+  }
+  NSAssert(NO, @"Invalid XCUIElementType: %lu", (unsigned long)elementType);
+  return gtx::ElementType::ANY;
+}
+
+@end
diff --git a/Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist b/Tests/Common/TestApp/GTXTestApp-Info.plist
similarity index 100%
rename from Tests/FunctionalTests/TestApp/GTXTestApp-Info.plist
rename to Tests/Common/TestApp/GTXTestApp-Info.plist
diff --git a/Tests/Common/TestApp/LaunchScreen.storyboard b/Tests/Common/TestApp/LaunchScreen.storyboard
new file mode 100644
index 0000000..d1462f5
--- /dev/null
+++ b/Tests/Common/TestApp/LaunchScreen.storyboard
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
+    <device id="retina6_1" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <scenes>
+        <!--View Controller-->
+        <scene sceneID="EHf-IW-A2E">
+            <objects>
+                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
+                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
+                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd">
+                                <rect key="frame" x="0.0" y="876" width="414" height="0.0"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="GTX Test App" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
+                                <rect key="frame" x="0.0" y="278" width="414" height="43"/>
+                                <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
+                                <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                        </subviews>
+                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                        <constraints>
+                            <constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/>
+                            <constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
+                            <constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="SfN-ll-jLj"/>
+                            <constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/>
+                            <constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
+                            <constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" symbolic="YES" id="x7j-FC-K8j"/>
+                        </constraints>
+                        <viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
+                    </view>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="53" y="375"/>
+        </scene>
+    </scenes>
+</document>
\ No newline at end of file
diff --git a/Tests/FunctionalTests/TestApp/Sources/GTXTestApp.m b/Tests/Common/TestApp/Sources/GTXTestApp.m
similarity index 100%
rename from Tests/FunctionalTests/TestApp/Sources/GTXTestApp.m
rename to Tests/Common/TestApp/Sources/GTXTestApp.m
diff --git a/Tests/FunctionalTests/TestApp/Sources/GTXTestAppDelegate.h b/Tests/Common/TestApp/Sources/GTXTestAppDelegate.h
similarity index 100%
rename from Tests/FunctionalTests/TestApp/Sources/GTXTestAppDelegate.h
rename to Tests/Common/TestApp/Sources/GTXTestAppDelegate.h
diff --git a/Tests/FunctionalTests/TestApp/Sources/GTXTestAppDelegate.m b/Tests/Common/TestApp/Sources/GTXTestAppDelegate.m
similarity index 100%
rename from Tests/FunctionalTests/TestApp/Sources/GTXTestAppDelegate.m
rename to Tests/Common/TestApp/Sources/GTXTestAppDelegate.m
diff --git a/Tests/FunctionalTests/TestApp/Sources/GTXTestStepperButton.h b/Tests/Common/TestApp/Sources/GTXTestStepperButton.h
similarity index 100%
rename from Tests/FunctionalTests/TestApp/Sources/GTXTestStepperButton.h
rename to Tests/Common/TestApp/Sources/GTXTestStepperButton.h
diff --git a/Tests/FunctionalTests/TestApp/Sources/GTXTestStepperButton.m b/Tests/Common/TestApp/Sources/GTXTestStepperButton.m
similarity index 100%
rename from Tests/FunctionalTests/TestApp/Sources/GTXTestStepperButton.m
rename to Tests/Common/TestApp/Sources/GTXTestStepperButton.m
diff --git a/Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.h b/Tests/Common/TestApp/Sources/GTXTestViewController.h
similarity index 64%
rename from Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.h
rename to Tests/Common/TestApp/Sources/GTXTestViewController.h
index 735e6f8..d461c58 100644
--- a/Tests/FunctionalTests/TestApp/Sources/GTXTestViewController.h
+++ b/Tests/Common/TestApp/Sources/GTXTestViewController.h
@@ -22,6 +22,11 @@
 FOUNDATION_EXTERN NSString *const kAddNoLabelElementActionName;
 
 /**
+ *  Name of the action that adds an element whose accessibility label does not end with punctuation.
+ */
+FOUNDATION_EXTERN NSString *const kAddNonpunctuatedLabelElementActionName;
+
+/**
  *  Name of the action that adds an element whose accessibility label has been punctuated.
  */
 FOUNDATION_EXTERN NSString *const kAddPunctuatedLabelElementActionName;
@@ -103,10 +108,69 @@
 FOUNDATION_EXTERN NSString *const kAddStandardUIKitTextView;
 
 /**
+ *  Name of the action that adds a label with a font constructed with fontWithName.
+ */
+FOUNDATION_EXTERN NSString *const kAddLabelWithFontWithName;
+
+/**
+ *  Name of the action that adds a label with a font constructed with preferredFontForTextStyle.
+ */
+FOUNDATION_EXTERN NSString *const kAddLabelWithPreferredFontForTextStyle;
+
+/**
+ *  Name of the action that adds a label with a font constructed with UIFontMetrics
+ *  scaledFontForFont. This event is a no-op before iOS 11, when UIFontMetrics had not been
+ *  introduced.
+ */
+FOUNDATION_EXTERN NSString *const kAddLabelWithFontMetrics;
+
+/**
+ *  Name of the action that adds a text view with a font constructed with fontWithName.
+ */
+FOUNDATION_EXTERN NSString *const kAddTextViewWithFontWithName;
+
+/**
+ *  Name of the action that adds a text view with a font constructed with preferredFontForTextStyle.
+ */
+FOUNDATION_EXTERN NSString *const kAddTextViewWithPreferredFontForTextStyle;
+
+/**
+ *  Name of the action that adds a text view with a font constructed with UIFontMetrics
+ *  scaledFontForFont. This event is a no-op before iOS 11, when UIFontMetrics had not been
+ *  introduced.
+ */
+FOUNDATION_EXTERN NSString *const kAddTextViewWithFontMetrics;
+
+/**
  *  Name of the action that adds a high contrast background.
  */
 FOUNDATION_EXTERN NSString *const kAddHighContrastBackground;
 
+/**
+ * Accessibility identifier for "clear test area" button.
+ */
+FOUNDATION_EXTERN NSString *const kGTXTestAppClearTestAreaID;
+
+/**
+ * Accessibility identifier for "Scroll to top" button.
+ */
+FOUNDATION_EXTERN NSString *const kGTXTestAppScrollToTopID;
+
+/**
+ * Accessibility identifier for the actions container view.
+ */
+FOUNDATION_EXTERN NSString *const kGTXTestAppActionsContainerID;
+
+/**
+ * Accessibility identifier for the testing area.
+ */
+FOUNDATION_EXTERN NSString *const kGTXTestTestingAreaID;
+
+/**
+ * Accessibility identifier for the added test element.
+ */
+FOUNDATION_EXTERN NSString *const kGTXTestTestingElementID;
+
 // The view controller for testing GTXiLib's Accessibility Checker.
 @interface GTXTestViewController : UIViewController
 
diff --git a/Tests/Common/TestApp/Sources/GTXTestViewController.m b/Tests/Common/TestApp/Sources/GTXTestViewController.m
new file mode 100644
index 0000000..1e82408
--- /dev/null
+++ b/Tests/Common/TestApp/Sources/GTXTestViewController.m
@@ -0,0 +1,463 @@
+//
+// Copyright 2018 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#import "GTXTestViewController.h"
+
+#import "GTXTestStepperButton.h"
+
+NSString *const kAddNoLabelElementActionName = @"Add no-label Element";
+NSString *const kAddNonpunctuatedLabelElementActionName = @"Add non-punctuated-label Element";
+NSString *const kAddPunctuatedLabelElementActionName = @"Add punctuated-label Element";
+NSString *const kAddConcatenatedLabelElementActionName = @"Add concatenated-label Element";
+NSString *const kShowKeyboardActionName = @"Show Keyboard";
+NSString *const kHideKeyboardActionName = @"Hide Keyboard";
+NSString *const kAddInaccessibleButton = @"Add InAccessible button";
+NSString *const kAddAccessibleButtonInContainer = @"Add Accessible button in subview";
+NSString *const kAddTinyTappableElement = @"Add tiny element";
+NSString *const kAddVeryHighContrastLabel = @"Add very high contrast label";
+NSString *const kAddVeryLowContrastLabel = @"Add very low contrast label";
+NSString *const kAddBarelyHighContrastLabel = @"Add barely High contrast label";
+NSString *const kAddBarelyLowContrastLabel = @"Add barely Low contrast label";
+NSString *const kAddNoContrastLabel = @"Add no contrast label";
+NSString *const kAddTransparentHighContrastLabel = @"Add transparent high contrast label";
+NSString *const kAddTransparentLowContrastLabel = @"Add transparent low contrast label";
+NSString *const kAddLowContrastTextView = @"Add low contrast text view";
+NSString *const kAddStandardUIKitTextView = @"Add standard UIKit text view";
+NSString *const kAddLabelWithFontWithName = @"Add label with fontWithName";
+NSString *const kAddLabelWithPreferredFontForTextStyle =
+    @"Add label with preferredFontForTextStyle";
+NSString *const kAddLabelWithFontMetrics = @"Add label with metricsWithTextStyle";
+NSString *const kAddTextViewWithFontWithName = @"Add text view with fontWithName";
+NSString *const kAddTextViewWithPreferredFontForTextStyle =
+    @"Add text view with preferredFontForTextStyle";
+NSString *const kAddTextViewWithFontMetrics = @"Add text view with metricsWithTextStyle";
+NSString *const kAddLowContrastBackground = @"Add Low contrast background";
+NSString *const kAddHighContrastBackground = @"Add High contrast backgorund";
+
+#pragma mark - Accessibility Identifiers
+
+NSString *const kGTXTestAppClearTestAreaID = @"kGTXTestAppClearTestAreaID";
+NSString *const kGTXTestAppScrollToTopID = @"kGTXTestAppScrollToTopID";
+NSString *const kGTXTestAppActionsContainerID = @"kGTXTestAppActionsContainerID";
+NSString *const kGTXTestTestingAreaID = @"kGTXTestTestingAreaID";
+NSString *const kGTXTestTestingElementID = @"kGTXTestTestingElementID";
+
+/**
+ *  The minimum size required to make UIElements accessible.
+ */
+static const CGFloat kMinimumElementSize = 48.0;
+
+/**
+ *  The margin used in the test app.
+ */
+static const CGFloat kMargin = 10.0;
+
+/**
+ *  The red component to get a red color thats barely (low contrast) distinguishable from complete
+ *  red color.
+ */
+static const CGFloat kAlmostRedColorValue = 0.5;
+
+/**
+ *  The font name for fonts constructed with @c fontWithName.
+ */
+static NSString *const kDefaultFontName = @"Arial";
+
+/**
+ *  The font size for fonts constructed with @c fontWithName.
+ */
+static const CGFloat kDefaultFontSize = 48.0;
+
+static __weak GTXTestViewController *gViewController;
+
+typedef void(^ActionHandler)(GTXTestViewController *sSelf);
+
+@interface GTXTestViewController ()<UITextFieldDelegate>
+
+@property(weak, nonatomic) IBOutlet UIScrollView *actionsContainerView;
+@property(weak, nonatomic) IBOutlet UIView *testArea;
+
+@end
+
+@implementation GTXTestViewController {
+  NSMutableDictionary *actionsToHandlers;
+}
+
+- (instancetype)init {
+  self = [super initWithNibName:@"GTXTestViewController" bundle:nil];
+  return self;
+}
+
+- (void)viewDidLoad {
+  [super viewDidLoad];
+  gViewController = self;
+  self.testArea.accessibilityIdentifier = kGTXTestTestingAreaID;
+  self.actionsContainerView.accessibilityIdentifier = kGTXTestAppActionsContainerID;
+  actionsToHandlers = [[NSMutableDictionary alloc] init];
+  [self.navigationController setNavigationBarHidden:YES animated:NO];
+
+  [self gtxtest_addActionNamed:kAddNoLabelElementActionName
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addElementWithLabel:@""];
+                       }];
+  [self gtxtest_addActionNamed:kAddNonpunctuatedLabelElementActionName
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addElementWithLabel:@"Foo"];
+                       }];
+  [self gtxtest_addActionNamed:kAddPunctuatedLabelElementActionName
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addElementWithLabel:@"Foo."];
+                       }];
+  [self gtxtest_addActionNamed:kAddConcatenatedLabelElementActionName
+                       handler:^(GTXTestViewController *sSelf) {
+                         // Add an element with concatenated labels: foo and bar.
+                         [sSelf gtxtest_addElementWithLabel:@"foo,bar."];
+                       }];
+  [self gtxtest_addActionNamed:kShowKeyboardActionName
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addShowKeyboard];
+                       }];
+  [self gtxtest_addActionNamed:kHideKeyboardActionName
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf.testArea.subviews[0] resignFirstResponder];
+                       }];
+  [self gtxtest_addActionNamed:kAddInaccessibleButton
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addInaccessibleButton];
+                       }];
+  [self gtxtest_addActionNamed:kAddAccessibleButtonInContainer
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addInaccessibleButtonInSubview];
+                       }];
+  [self gtxtest_addActionNamed:kAddTinyTappableElement
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addTinyTappableElement];
+                       }];
+  [self gtxtest_addActionNamed:kAddVeryHighContrastLabel
+                       handler:^(GTXTestViewController *sSelf) {
+                         // Add a high contrast label: black text on white background.
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor blackColor]
+                                                   backgroundColor:[UIColor whiteColor]
+                                                              font:nil];
+                       }];
+  [self gtxtest_addActionNamed:kAddVeryLowContrastLabel
+                       handler:^(GTXTestViewController *sSelf) {
+                         // Add a low contrast label: black text on very dark grey background.
+                         UIColor *veryDarkGreyColor = [UIColor colorWithWhite:0.2f alpha:1.0f];
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor blackColor]
+                                                   backgroundColor:veryDarkGreyColor
+                                                              font:nil];
+                       }];
+
+  UIColor *kAlmostRed = [UIColor colorWithRed:kAlmostRedColorValue green:0 blue:0 alpha:1];
+  UIColor *kAlmostRedButDarker = [UIColor colorWithRed:kAlmostRedColorValue - 0.15f
+                                                 green:0
+                                                  blue:0
+                                                 alpha:1];
+  [self gtxtest_addActionNamed:kAddBarelyLowContrastLabel
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor redColor]
+                                                   backgroundColor:kAlmostRed
+                                                              font:nil];
+                       }];
+  [self gtxtest_addActionNamed:kAddBarelyHighContrastLabel
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor redColor]
+                                                   backgroundColor:kAlmostRedButDarker
+                                                              font:nil];
+                       }];
+  [self gtxtest_addActionNamed:kAddNoContrastLabel
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor redColor]
+                                                   backgroundColor:[UIColor redColor]
+                                                              font:nil];
+                       }];
+  [self gtxtest_addActionNamed:kAddTransparentHighContrastLabel
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor colorWithWhite:1.0
+                                                                                     alpha:0.5]
+                                                   backgroundColor:[UIColor blackColor]
+                                                              font:nil];
+                       }];
+  [self gtxtest_addActionNamed:kAddTransparentLowContrastLabel
+                       handler:^(GTXTestViewController *sSelf) {
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor colorWithWhite:0.0
+                                                                                     alpha:0.5]
+                                                   backgroundColor:[UIColor redColor]
+                                                              font:nil];
+                       }];
+  [self gtxtest_addActionNamed:kAddLabelWithFontWithName
+                       handler:^(GTXTestViewController *sSelf) {
+                         UIFont *font = [UIFont fontWithName:kDefaultFontName
+                                                        size:kDefaultFontSize];
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor blackColor]
+                                                   backgroundColor:[UIColor whiteColor]
+                                                              font:font];
+                       }];
+  [self gtxtest_addActionNamed:kAddLabelWithPreferredFontForTextStyle
+                       handler:^(GTXTestViewController *sSelf) {
+                         UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor blackColor]
+                                                   backgroundColor:[UIColor whiteColor]
+                                                              font:font];
+                       }];
+  [self gtxtest_addActionNamed:kAddLabelWithFontMetrics
+                       handler:^(GTXTestViewController *sSelf) {
+                         // UIFontMetrics did not exist before iOS 11 so the event is a no-op.
+                         if (@available(iOS 11.0, *)) {
+                           UIFont *nonscalingFont = [UIFont fontWithName:kDefaultFontName
+                                                                    size:kDefaultFontSize];
+                           UIFont *font = [[UIFontMetrics metricsForTextStyle:UIFontTextStyleBody]
+                               scaledFontForFont:nonscalingFont];
+                           [sSelf gtxtest_addTextViewWithForgroundColor:[UIColor blackColor]
+                                                        backgroundColor:[UIColor whiteColor]
+                                                                   font:font];
+                         }
+                       }];
+  [self gtxtest_addActionNamed:kAddTextViewWithFontWithName
+                       handler:^(GTXTestViewController *sSelf) {
+                         UIFont *font = [UIFont fontWithName:kDefaultFontName
+                                                        size:kDefaultFontSize];
+                         [sSelf gtxtest_addTextViewWithForgroundColor:[UIColor blackColor]
+                                                      backgroundColor:[UIColor whiteColor]
+                                                                 font:font];
+                       }];
+  [self gtxtest_addActionNamed:kAddTextViewWithPreferredFontForTextStyle
+                       handler:^(GTXTestViewController *sSelf) {
+                         UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+                         [sSelf gtxtest_addTextViewWithForgroundColor:[UIColor blackColor]
+                                                      backgroundColor:[UIColor whiteColor]
+                                                                 font:font];
+                       }];
+  [self gtxtest_addActionNamed:kAddTextViewWithFontMetrics
+                       handler:^(GTXTestViewController *sSelf) {
+                         // UIFontMetrics did not exist before iOS 11 so the event is a no-op.
+                         if (@available(iOS 11.0, *)) {
+                           UIFont *nonscalingFont = [UIFont fontWithName:kDefaultFontName
+                                                                    size:kDefaultFontSize];
+                           UIFont *font = [[UIFontMetrics metricsForTextStyle:UIFontTextStyleBody]
+                               scaledFontForFont:nonscalingFont];
+                           [sSelf gtxtest_addTextViewWithForgroundColor:[UIColor blackColor]
+                                                        backgroundColor:[UIColor whiteColor]
+                                                                   font:font];
+                         }
+                       }];
+  [self gtxtest_addActionNamed:kAddLowContrastBackground
+                       handler:^(GTXTestViewController *sSelf) {
+                         // Add a low contrast background with respect to text added on top of it.
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor redColor]
+                                                   backgroundColor:[UIColor clearColor]
+                                                              font:nil];
+                         [sSelf.testArea setBackgroundColor:kAlmostRed];
+                       }];
+  [self gtxtest_addActionNamed:kAddHighContrastBackground
+                       handler:^(GTXTestViewController *sSelf) {
+                         // Add a high contrast background with respect to text added on top of it.
+                         [sSelf gtxtest_addLabelWithForgroundColor:[UIColor redColor]
+                                                   backgroundColor:[UIColor clearColor]
+                                                              font:nil];
+                         [sSelf.testArea setBackgroundColor:kAlmostRedButDarker];
+                       }];
+  [self gtxtest_addActionNamed:kAddStandardUIKitTextView
+                       handler:^(GTXTestViewController *sSelf) {
+                         // Add a standard contrast text view: black text on white background.
+                         [sSelf gtxtest_addTextViewWithForgroundColor:nil
+                                                      backgroundColor:nil
+                                                                 font:nil];
+                       }];
+  [self gtxtest_addActionNamed:kAddLowContrastTextView
+                       handler:^(GTXTestViewController *sSelf) {
+                         // Add a low contrast text view: black text on very dark grey background.
+                         UIColor *veryDarkGreyColor = [UIColor colorWithWhite:0.2f alpha:1.0f];
+                         [sSelf gtxtest_addTextViewWithForgroundColor:[UIColor blackColor]
+                                                      backgroundColor:veryDarkGreyColor
+                                                                 font:nil];
+                       }];
+}
+
+- (void)gtxtest_addActionNamed:(NSString *)name handler:(ActionHandler)handler {
+  UIButton *newButton = [[UIButton alloc] initWithFrame:CGRectZero];
+  [newButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
+  [newButton addTarget:self
+                action:@selector(gtxtest_userTappedActionButton:)
+      forControlEvents:UIControlEventTouchUpInside];
+  [newButton setTitle:name forState:UIControlStateNormal];
+  [newButton sizeToFit];
+  CGRect buttonFrame = newButton.frame;
+  buttonFrame.size.height = kMinimumElementSize;
+  newButton.frame = buttonFrame;
+  newButton.accessibilityIdentifier = name;
+
+  CGSize contentSize = self.actionsContainerView.contentSize;
+  buttonFrame.origin.y = contentSize.height + kMargin;
+  contentSize.height += newButton.frame.size.height + kMargin;
+  newButton.frame = buttonFrame;
+  self.actionsContainerView.contentSize = contentSize;
+  [self.actionsContainerView addSubview:newButton];
+  NSAssert(!actionsToHandlers[name], @"Action %@ was already added.", name);
+  actionsToHandlers[name] = handler;
+}
+
++ (void)performTestActionNamed:(NSString *)actionName {
+  GTXTestViewController *controller = gViewController;
+  NSAssert(controller, @"View controller has not loaded yet.");
+  ActionHandler handler = controller->actionsToHandlers[actionName];
+  NSAssert(handler, @"Action named %@ does not exist", actionName);
+  handler(controller);
+}
+
+- (void)gtxtest_userTappedActionButton:(UIButton *)sender {
+  [[self class] performTestActionNamed:sender.titleLabel.text];
+}
+
+- (void)gtxtest_addElementWithLabel:(NSString *)label {
+  UIView *newElement = [[UIView alloc] initWithFrame:CGRectMake(kMargin, kMargin,
+                                                                kMinimumElementSize,
+                                                                kMinimumElementSize)];
+  newElement.isAccessibilityElement = YES;
+  newElement.accessibilityLabel = label;
+  newElement.backgroundColor = [UIColor whiteColor];
+  [self gtxtest_addTestElement:newElement];
+}
+
+- (void)gtxtest_addShowKeyboard {
+  UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(kMargin, kMargin,
+                                                                      kMinimumElementSize * 2,
+                                                                      kMinimumElementSize)];
+  textView.font = [UIFont preferredFontForTextStyle:UIFontTextStyleTitle1];
+  textView.adjustsFontForContentSizeCategory = YES;
+  [self gtxtest_addTestElement:textView];
+  [textView becomeFirstResponder];
+}
+
+- (void)gtxtest_addInaccessibleButton {
+  GTXTestStepperButton *stepperButton =
+      [[GTXTestStepperButton alloc] initWithFrame:CGRectMake(kMargin, kMargin,
+                                                             kMinimumElementSize,
+                                                             kMinimumElementSize)];
+  [self gtxtest_addTestElement:stepperButton];
+}
+
+- (void)gtxtest_addInaccessibleButtonInSubview {
+  CGRect frame = CGRectMake(kMargin, kMargin, kMinimumElementSize,