context: // (c) Copyright Microsoft, 2012.
  // This source is subject to the Microsoft Permissive License.
  // See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
  // All other rights reserved.
  
  
  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Diagnostics;
  using UIAComWrapperInternal;
  
  namespace System.Windows.Automation
  {
      public enum AutomationElementMode
      {
          None,
          Full
      }
  
      public sealed class AutomationElement
      {
          
          private UIAutomationClient.IUIAutomationElement _obj;
          public static readonly AutomationProperty AcceleratorKeyProperty = AutomationElementIdentifiers.AcceleratorKeyProperty;
          public static readonly AutomationProperty AccessKeyProperty = AutomationElementIdentifiers.AccessKeyProperty;
          public static readonly AutomationEvent AsyncContentLoadedEvent = AutomationElementIdentifiers.AsyncContentLoadedEvent;
          public static readonly AutomationEvent AutomationFocusChangedEvent = AutomationElementIdentifiers.AutomationFocusChangedEvent;
          public static readonly AutomationProperty AutomationIdProperty = AutomationElementIdentifiers.AutomationIdProperty;
          public static readonly AutomationEvent AutomationPropertyChangedEvent = AutomationElementIdentifiers.AutomationPropertyChangedEvent;
          public static readonly AutomationProperty BoundingRectangleProperty = AutomationElementIdentifiers.BoundingRectangleProperty;
          public static readonly AutomationProperty ClassNameProperty = AutomationElementIdentifiers.ClassNameProperty;
          public static readonly AutomationProperty ClickablePointProperty = AutomationElementIdentifiers.ClickablePointProperty;
          public static readonly AutomationProperty ControlTypeProperty = AutomationElementIdentifiers.ControlTypeProperty;
          public static readonly AutomationProperty CultureProperty = AutomationElementIdentifiers.CultureProperty;
          public static readonly AutomationProperty FrameworkIdProperty = AutomationElementIdentifiers.FrameworkIdProperty;
          public static readonly AutomationProperty HasKeyboardFocusProperty = AutomationElementIdentifiers.HasKeyboardFocusProperty;
          public static readonly AutomationProperty HelpTextProperty = AutomationElementIdentifiers.HelpTextProperty;
          public static readonly AutomationProperty IsContentElementProperty = AutomationElementIdentifiers.IsContentElementProperty;
          public static readonly AutomationProperty IsControlElementProperty = AutomationElementIdentifiers.IsControlElementProperty;
          public static readonly AutomationProperty IsDockPatternAvailableProperty = AutomationElementIdentifiers.IsDockPatternAvailableProperty;
          public static readonly AutomationProperty IsEnabledProperty = AutomationElementIdentifiers.IsEnabledProperty;
          public static readonly AutomationProperty IsExpandCollapsePatternAvailableProperty = AutomationElementIdentifiers.IsExpandCollapsePatternAvailableProperty;
          public static readonly AutomationProperty IsGridItemPatternAvailableProperty = AutomationElementIdentifiers.IsGridItemPatternAvailableProperty;
          public static readonly AutomationProperty IsGridPatternAvailableProperty = AutomationElementIdentifiers.IsGridPatternAvailableProperty;
          public static readonly AutomationProperty IsInvokePatternAvailableProperty = AutomationElementIdentifiers.IsInvokePatternAvailableProperty;
          public static readonly AutomationProperty IsKeyboardFocusableProperty = AutomationElementIdentifiers.IsKeyboardFocusableProperty;
          public static readonly AutomationProperty IsMultipleViewPatternAvailableProperty = AutomationElementIdentifiers.IsMultipleViewPatternAvailableProperty;
          public static readonly AutomationProperty IsOffscreenProperty = AutomationElementIdentifiers.IsOffscreenProperty;
          public static readonly AutomationProperty IsPasswordProperty = AutomationElementIdentifiers.IsPasswordProperty;
          public static readonly AutomationProperty IsRangeValuePatternAvailableProperty = AutomationElementIdentifiers.IsRangeValuePatternAvailableProperty;
          public static readonly AutomationProperty IsRequiredForFormProperty = AutomationElementIdentifiers.IsRequiredForFormProperty;
          public static readonly AutomationProperty IsScrollItemPatternAvailableProperty = AutomationElementIdentifiers.IsScrollItemPatternAvailableProperty;
          public static readonly AutomationProperty IsScrollPatternAvailableProperty = AutomationElementIdentifiers.IsScrollPatternAvailableProperty;
          public static readonly AutomationProperty IsSelectionItemPatternAvailableProperty = AutomationElementIdentifiers.IsSelectionItemPatternAvailableProperty;
          public static readonly AutomationProperty IsSelectionPatternAvailableProperty = AutomationElementIdentifiers.IsSelectionPatternAvailableProperty;
          public static readonly AutomationProperty IsTableItemPatternAvailableProperty = AutomationElementIdentifiers.IsTableItemPatternAvailableProperty;
          public static readonly AutomationProperty IsTablePatternAvailableProperty = AutomationElementIdentifiers.IsTablePatternAvailableProperty;
          public static readonly AutomationProperty IsTextPatternAvailableProperty = AutomationElementIdentifiers.IsTextPatternAvailableProperty;
          public static readonly AutomationProperty IsTogglePatternAvailableProperty = AutomationElementIdentifiers.IsTogglePatternAvailableProperty;
          public static readonly AutomationProperty IsTransformPatternAvailableProperty = AutomationElementIdentifiers.IsTransformPatternAvailableProperty;
          public static readonly AutomationProperty IsValuePatternAvailableProperty = AutomationElementIdentifiers.IsValuePatternAvailableProperty;
          public static readonly AutomationProperty IsWindowPatternAvailableProperty = AutomationElementIdentifiers.IsWindowPatternAvailableProperty;
          public static readonly AutomationProperty ItemStatusProperty = AutomationElementIdentifiers.ItemStatusProperty;
          public static readonly AutomationProperty ItemTypeProperty = AutomationElementIdentifiers.ItemTypeProperty;
          public static readonly AutomationProperty LabeledByProperty = AutomationElementIdentifiers.LabeledByProperty;
          public static readonly AutomationEvent LayoutInvalidatedEvent = AutomationElementIdentifiers.LayoutInvalidatedEvent;
          public static readonly AutomationProperty LocalizedControlTypeProperty = AutomationElementIdentifiers.LocalizedControlTypeProperty;
          public static readonly AutomationEvent MenuClosedEvent = AutomationElementIdentifiers.MenuClosedEvent;
          public static readonly AutomationEvent MenuOpenedEvent = AutomationElementIdentifiers.MenuOpenedEvent;
          public static readonly AutomationProperty NameProperty = AutomationElementIdentifiers.NameProperty;
          public static readonly AutomationProperty NativeWindowHandleProperty = AutomationElementIdentifiers.NativeWindowHandleProperty;
          public static readonly object NotSupported = AutomationElementIdentifiers.NotSupported;
          public static readonly AutomationProperty OrientationProperty = AutomationElementIdentifiers.OrientationProperty;
          public static readonly AutomationProperty ProcessIdProperty = AutomationElementIdentifiers.ProcessIdProperty;
          public static readonly AutomationProperty RuntimeIdProperty = AutomationElementIdentifiers.RuntimeIdProperty;
          public static readonly AutomationEvent StructureChangedEvent = AutomationElementIdentifiers.StructureChangedEvent;
          public static readonly AutomationEvent ToolTipClosedEvent = AutomationElementIdentifiers.ToolTipClosedEvent;
          public static readonly AutomationEvent ToolTipOpenedEvent = AutomationElementIdentifiers.ToolTipOpenedEvent;
  
          public static readonly AutomationProperty IsLegacyIAccessiblePatternAvailableProperty = AutomationElementIdentifiers.IsLegacyIAccessiblePatternAvailableProperty;
          public static readonly AutomationProperty IsItemContainerPatternAvailableProperty = AutomationElementIdentifiers.IsItemContainerPatternAvailableProperty;
          public static readonly AutomationProperty IsVirtualizedItemPatternAvailableProperty = AutomationElementIdentifiers.IsVirtualizedItemPatternAvailableProperty;
          public static readonly AutomationProperty IsSynchronizedInputPatternAvailableProperty = AutomationElementIdentifiers.IsSynchronizedInputPatternAvailableProperty;
  
          public static readonly AutomationProperty AriaRoleProperty = AutomationElementIdentifiers.AriaRoleProperty;
          public static readonly AutomationProperty AriaPropertiesProperty = AutomationElementIdentifiers.AriaPropertiesProperty;
          public static readonly AutomationProperty IsDataValidForFormProperty = AutomationElementIdentifiers.IsDataValidForFormProperty;
          public static readonly AutomationProperty ControllerForProperty = AutomationElementIdentifiers.ControllerForProperty;
          public static readonly AutomationProperty DescribedByProperty = AutomationElementIdentifiers.DescribedByProperty;
          public static readonly AutomationProperty FlowsToProperty = AutomationElementIdentifiers.FlowsToProperty;
          public static readonly AutomationProperty ProviderDescriptionProperty = AutomationElementIdentifiers.ProviderDescriptionProperty;
  
          public static readonly AutomationEvent MenuModeStartEvent = AutomationElementIdentifiers.MenuModeStartEvent;
          public static readonly AutomationEvent MenuModeEndEvent = AutomationElementIdentifiers.MenuModeEndEvent;
  
          // New for Windows 8
          public static readonly AutomationProperty IsObjectModelPatternAvailableProperty = AutomationElementIdentifiers.IsObjectModelPatternAvailableProperty;
          public static readonly AutomationProperty IsAnnotationPatternAvailableProperty = AutomationElementIdentifiers.IsAnnotationPatternAvailableProperty;
          public static readonly AutomationProperty IsTextPattern2AvailableProperty = AutomationElementIdentifiers.IsTextPattern2AvailableProperty;
          public static readonly AutomationProperty IsStylesPatternAvailableProperty = AutomationElementIdentifiers.IsStylesPatternAvailableProperty;
          public static readonly AutomationProperty IsSpreadsheetPatternAvailableProperty = AutomationElementIdentifiers.IsSpreadsheetPatternAvailableProperty;
          public static readonly AutomationProperty IsSpreadsheetItemPatternAvailableProperty = AutomationElementIdentifiers.IsSpreadsheetItemPatternAvailableProperty;
          public static readonly AutomationProperty IsTransformPattern2AvailableProperty = AutomationElementIdentifiers.IsTransformPattern2AvailableProperty;
          public static readonly AutomationProperty IsTextChildPatternAvailableProperty = AutomationElementIdentifiers.IsTextChildPatternAvailableProperty;
          public static readonly AutomationProperty IsDragPatternAvailableProperty = AutomationElementIdentifiers.IsDragPatternAvailableProperty;
          public static readonly AutomationProperty IsDropTargetPatternAvailableProperty = AutomationElementIdentifiers.IsDropTargetPatternAvailableProperty;
  
          public static readonly AutomationProperty OptimizeForVisualContentProperty = AutomationElementIdentifiers.OptimizeForVisualContentProperty;
          public static readonly AutomationProperty LiveSettingProperty = AutomationElementIdentifiers.LiveSettingProperty;
  
          public static readonly AutomationEvent SystemAlertEvent = AutomationElementIdentifiers.SystemAlertEvent;
          public static readonly AutomationEvent LiveRegionChangedEvent = AutomationElementIdentifiers.LiveRegionChangedEvent;
          public static readonly AutomationEvent HostedFragmentRootsInvalidatedEvent = AutomationElementIdentifiers.HostedFragmentRootsInvalidatedEvent;
  
          
          internal AutomationElement(UIAutomationClient.IUIAutomationElement obj)
          {
              Debug.Assert(obj != null);
              this._obj = obj;
          }
  
          internal static AutomationElement Wrap(UIAutomationClient.IUIAutomationElement obj)
          {
              return (obj == null) ? null : new AutomationElement(obj);
          }
  
          public override bool Equals(object obj)
          {
              AutomationElement element = obj as AutomationElement;
              return (((obj != null) && (element != null)) && (Automation.Factory.CompareElements(this._obj, element._obj) != 0));
          }
  
          ~AutomationElement()
          {
          }
  
          public AutomationElementCollection FindAll(TreeScope scope, Condition condition)
          {
              Utility.ValidateArgumentNonNull(condition, "condition");
  
              try
              {
                  UIAutomationClient.IUIAutomationElementArray elemArray =
                      this._obj.FindAllBuildCache(
                          (UIAutomationClient.TreeScope)scope,
                          condition.NativeCondition,
                          CacheRequest.CurrentNativeCacheRequest);
                  return AutomationElementCollection.Wrap(elemArray);
              }
              catch (System.Runtime.InteropServices.COMException e)
              {
                  Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; }
              }
          }
  
          public AutomationElement FindFirst(TreeScope scope, Condition condition)
          {
              Utility.ValidateArgumentNonNull(condition, "condition");
              try
              {
                  UIAutomationClient.IUIAutomationElement elem =
                      this._obj.FindFirstBuildCache(
                          (UIAutomationClient.TreeScope)scope,
                          condition.NativeCondition,
                          CacheRequest.CurrentNativeCacheRequest);
                  return AutomationElement.Wrap(elem);
              }
              catch (System.Runtime.InteropServices.COMException e)
              {
                  Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; }
              }
          }
  
          public static AutomationElement FromHandle(IntPtr hwnd)
          {
              Utility.ValidateArgument(hwnd != IntPtr.Zero, "Hwnd cannot be null");
              try
              {
                  UIAutomationClient.IUIAutomationElement element =
                      Automation.Factory.ElementFromHandleBuildCache(hwnd, CacheRequest.CurrentNativeCacheRequest);
                  return AutomationElement.Wrap(element);
              }
              catch (System.Runtime.InteropServices.COMException e)
              {
                  Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; }
              }
          }
  
          public static AutomationElement FromIAccessible(Accessibility.IAccessible acc, int childId)
          {
              Utility.ValidateArgumentNonNull(acc, "acc");
  
              try
              {
                  UIAutomationClient.IUIAutomationElement element =
                      Automation.Factory.ElementFromIAccessibleBuildCache(
                          (UIAutomationClient.IAccessible)acc, 
                          childId,
                          CacheRequest.CurrentNativeCacheRequest);
                  return AutomationElement.Wrap(element);
              }
              catch (System.Runtime.InteropServices.COMException e)
              {
                  Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; }
              }
          }
  
          public static AutomationElement FromLocalProvider(object /* IRawElementProviderSimple */ localImpl)
          {
              Utility.ValidateArgumentNonNull(localImpl, "localImpl");
  
              // It's not clear how you'd do this -- COM API doesn't give you
              // the chance to wrap a provider like this.
              throw new NotImplementedException();
          }
  
          public static AutomationElement FromPoint(Point pt)
          {
              try
              {
                  UIAutomationClient.IUIAutomationElement element =
                      Automation.Factory.ElementFromPointBuildCache(
                          Utility.PointManagedToNative(pt),
                          CacheRequest.CurrentNativeCacheRequest);
                  return AutomationElement.Wrap(element);
              }
              catch (System.Runtime.InteropServices.COMException e)
              {
                  Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; }
              }
          }
  
          public object GetCachedPattern(AutomationPattern pattern)
          {
              object patternObj;
              if (!this.TryGetCachedPattern(pattern, out patternObj))
              {
                  throw new InvalidOperationException("Unsupported pattern");
              }
              return patternObj;
          }
  
          public object GetCachedPropertyValue(AutomationProperty property)
          {
              return this.GetCachedPropertyValue(property, false);
          }
  
          public object GetCachedPropertyValue(AutomationProperty property, bool ignoreDefaultValue)
          {
              Utility.ValidateArgumentNonNull(property, "property");
  
              try
              {
                  object obj = this._obj.GetCachedPropertyValueEx(property.Id, (ignoreDefaultValue) ? 1 : 0);
                  return Utility.WrapObjectAsProperty(property, obj);
              }
              catch (System.Runtime.InteropServices.COMException e)
              {
                  Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; }
              }
          }
  
          public Point GetClickablePoint()
          {
              Point point;
              if (!this.TryGetClickablePoint(out point))
              {
                  throw new NoClickablePointException();
              }
              return point;
          }
  
          public object GetCurrentPattern(AutomationPattern pattern)
          {
              object patternObj;
              if (!this.TryGetCurrentPattern(pattern, out patternObj))
              {
                  throw new InvalidOperationException("Unsupported pattern");
              }
              return patternObj;
          }
  
          public object GetCurrentPropertyValue(AutomationProperty property)
          {
              return this.GetCurrentPropertyValue(property, false);
          }
  
          public object GetCurrentPropertyValue(AutomationProperty property, bool ignoreDefaultValue)
          {
              Utility.ValidateArgumentNonNull(property, "property");
              try
              {
                  object obj = this._obj.GetCurrentPropertyValueEx(property.Id, (ignoreDefaultValue) ? 1 : 0);
                  return Utility.WrapObjectAsProperty(property, obj);
              }
              catch (System.Runtime.InteropServices.COMException e)
              {
                  Exception newEx; if (Utility.ConvertException(e, out newEx)) { throw newEx; } else { throw; }
              }
  
          }
  
          internal object GetPropertyValue(AutomationProperty property, bool cached)
          {
              if (cached)
              {
                  return GetCachedPropertyValue(property);
              }
              else
              {
                  return GetCurrentPropertyValue(property);
              }
          }
  
          public override int GetHashCode()
          {
              int[] runtimeId = GetRuntimeId();
              int num = 0;
  
gt:             if (runtimeId == null)