/// <summary>
        /// Gets the accessible role of the XAccessible obj if possible.
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <returns>AccessibleRole or AccessibleRole.UNKNOWN</returns>
        public static AccessibleRole GetAccessibleRole(XAccessible obj)
        {
            AccessibleRole r = AccessibleRole.UNKNOWN;

            if (obj != null)
            {
                TimeLimitExecutor.WaitForExecuteWithTimeLimit(400, () =>
                {
                    try
                    {
                        r = GetAccessibleRole(obj.getAccessibleContext());
                    }
                    catch (unoidl.com.sun.star.lang.DisposedException)
                    {
                        r = AccessibleRole.DISPOSED;
                    }
                    catch (ThreadAbortException) { }
                    catch (ThreadInterruptedException) { }
                    catch { r = AccessibleRole.INVALID; }
                }, "");
            }
            return AccessibleRole.UNKNOWN;
        }
        internal void UpdateObserverLists(OoShapeObserver obs)
        {
            String             name  = obs.Name;
            XShape             shape = obs.Shape;
            XAccessible        acc   = obs.AcccessibleCounterpart;
            XAccessibleContext cont  = acc != null?acc.getAccessibleContext() : null;

            //TODO: maybe do this softer?!

            try { shapes[name] = obs; }
            catch (Exception) { }
            if (cont != null)
            {
                try { accshapes[cont] = obs; }
                catch (Exception) { }
            }
            else
            {
                // search for a relation?
            }
            try { domshapes[shape] = obs; }
            catch (Exception) { }
        }
        /// <summary>
        /// Determines whether the window [is a draw element].
        /// </summary>
        /// <param name="obj">The obj.</param>
        /// <returns>False or the DOCUMENT</returns>
        public static object IsDrawWindowParentPart(XAccessible obj)
        {
            if (obj != null)
            {
                //check if object is com.sun.star.drawing.AccessibleDrawDocumentView
                if (OoUtils.ElementSupportsService(obj, OO.Services.DRAWING_ACCESSIBLE_DOC))
                {
                    return obj;
                }

                // cannot have any children windows
                if (!(obj is XVclContainer)) return false;

                AccessibleRole role = AccessibleRole.UNKNOWN;
                XAccessibleContext cont = obj is XAccessibleContext ? obj as XAccessibleContext : obj.getAccessibleContext();

                // if you cannot obtain the context than the other stuff 
                // will run into trouble - so break!
                if (cont == null) return false;

                //// try to check for drawing window by comparing children with existing drawing controller windows
                //try
                //{
                //    // get libre office desktop
                //    unoidl.com.sun.star.frame.XDesktop desktop = OO.GetDesktop(OO.GetMultiComponentFactory(OO.GetContext()), OO.GetContext());
                //    if (desktop != null)
                //    {
                //        // iterate desktop components
                //        unoidl.com.sun.star.container.XEnumeration desktopComponentsEnumeration = desktop.getComponents().createEnumeration();
                //        while (desktopComponentsEnumeration.hasMoreElements())
                //        {

                //            object comp = desktopComponentsEnumeration.nextElement().Value;
                //            if (comp != null && comp is XDrawPagesSupplier)
                //            {
                //                XDrawPagesSupplier drawPageSuppliesModel = (XDrawPagesSupplier)comp;
                //                // check only desktop components that is are drawPagesSuppliers (these are models too)
                //                if (drawPageSuppliesModel != null && OoUtils.ElementSupportsService(drawPageSuppliesModel, "com.sun.star.drawing.DrawingDocument") && drawPageSuppliesModel is unoidl.com.sun.star.frame.XModel)
                //                {
                //                    // get the draw page components controller and check if its supporting the Service DrawingDocumentDrawView
                //                    unoidl.com.sun.star.frame.XController currentController = ((unoidl.com.sun.star.frame.XModel)drawPageSuppliesModel).getCurrentController();
                //                    if (currentController != null && OoUtils.ElementSupportsService(currentController, "com.sun.star.drawing.DrawingDocumentDrawView"))
                //                    {
                //                        // get the component window
                //                        XWindow currentControllerComponentWindow = (XWindow)currentController.getFrame().getComponentWindow();
                //                        // get its rectangle
                //                        Rectangle currentRect = (Rectangle)currentControllerComponentWindow.getPosSize();
                //                        // search sources children for visible children if one matches the rectangle which indicates a match
                //                        if (obj is XVclContainer)
                //                        {
                //                            XWindow[] sourceChildWindows = ((XVclContainer)obj).getWindows();
                //                            foreach (XWindow sourceChildWindow in sourceChildWindows)
                //                            {
                //                                Rectangle sourceChildRect = (Rectangle)sourceChildWindow.getPosSize();
                //                                System.Diagnostics.Debug.WriteLine("Source Child Rect: " + sourceChildRect.X + ", " + sourceChildRect.Y + "    " + sourceChildRect.Width + " x " + sourceChildRect.Height);

                //                                if (((XWindow2)sourceChildWindow).isVisible() &&
                //                                    ((XWindow2)currentControllerComponentWindow).isVisible() &&
                //                                    ((XWindow2)sourceChildWindow).hasFocus() == ((XWindow2)currentControllerComponentWindow).hasFocus() &&
                //                                    sourceChildRect.X == currentRect.X &&
                //                                    sourceChildRect.Y == currentRect.Y &&
                //                                    sourceChildRect.Width == currentRect.Width &&
                //                                    sourceChildRect.Height == currentRect.Height
                //                                    )
                //                                {
                //                                    //System.Diagnostics.Debug.WriteLine("match rects");
                //                                    //return currentController;
                //                                }
                //                            }
                //                        }
                //                    }
                //                }
                //            }
                //        }

                //    }
                //}
                //catch (Exception ex)
                //{

                //}
                int ccount = 0;

                try
                {

                    // fast check to search further or stop
                    // if top window and the accessible name ends with a "- OpenOffice Draw"

                    if (obj is XWindow2 && ((XWindow2)obj).isVisible())
                    {
                        ccount = cont.getAccessibleChildCount();

                        // don't go to deep -- if the element has no children 
                        // then it is not the document or a valid container for a document
                        if (ccount < 1) return false;
                    }
                    else { return false; } // stop if obj is not a window or is invisible


                    if (denieObjectBecauseOfServiceCheck(cont)) return false;

                    int trys = 0;
                    while (role == AccessibleRole.UNKNOWN && (trys++ <= 2))
                    {
                        if (trys > 1) Thread.Sleep(5 * trys);
                        role = GetAccessibleRole(cont);
                    }

                    // if role is a surrounding container type, search for the draw doc children
                    if (role.Equals(AccessibleRole.PANEL)
                        || role.Equals(AccessibleRole.SCROLL_PANE)
                        || role.Equals(AccessibleRole.ROOT_PANE)
                        || role.Equals(AccessibleRole.SPLIT_PANE)
                        || role.Equals(AccessibleRole.STATUS_BAR)
                        || role.Equals(AccessibleRole.UNKNOWN) // FIXME: see this as a bad hack - remove this if possible
                        )
                    {
                        if (cont != null)
                        {
                            for (int i = 0; i < ccount; i++)
                            {
                                try
                                {
                                    XAccessible child = cont.getAccessibleChild(i);
                                    if (child != null)
                                    {
                                        Object result = IsDrawWindowParentPart(child);
                                        if (!(result is bool))
                                        {
                                            return result;
                                        }
                                        else continue;
                                    }
                                }
                                catch { return false; }
                            }
                        }
                    }
                }
                catch { }
            }
            return false;
        }
 /// <summary>
 /// Try to get the parent page.
 /// </summary>
 /// <param name="acc">The acc.</param>
 /// <returns></returns>
 public static XAccessible GetParentPage(XAccessible acc)
 {
     if (acc != null)
     {
         XAccessibleContext accCont = acc.getAccessibleContext();
         if (accCont != null)
         {
             AccessibleRole role = GetAccessibleRole(accCont);
             if (role == AccessibleRole.PAGE) return accCont as XAccessible;
             else if (
                 role == AccessibleRole.WINDOW
                 || role == AccessibleRole.DOCUMENT
                 || role == AccessibleRole.ROOT_PANE
                 || role == AccessibleRole.MENU_BAR
                 ) return null;
             else
             {
                 XAccessible parent = GetParent(acc);
                 if (parent != null && !parent.Equals(acc) && !parent.Equals(accCont))
                 {
                     return GetParentPage(parent);
                 }
             }
         }
     }
     return null;
 }
 /// <summary>
 /// Returns the parent of the element.
 /// </summary>
 /// <param name="element">The element.</param>
 /// <returns>The parent XAccessible or <c>null</c></returns>
 public static XAccessible GetParent(XAccessible element)
 {
     if (element != null)
     {
         XAccessibleContext cont = element.getAccessibleContext();
         if (cont != null)
         {
             XAccessible parent = cont.getAccessibleParent();
             if (!parent.Equals(element)) return element;
         }
     }
     return null;
 }
        /// <summary>
        /// Gets all children and sub children under the accessible object.
        /// </summary>
        /// <param name="parent">The parent.</param>
        /// <returns>list of all available accessible children and sub children under this node</returns>
        public static List<XAccessible> GetAllChildrenOfAccessibleObject(XAccessible parent)
        {
            List<XAccessible> children = new List<XAccessible>();

            if (parent != null)
            {
                XAccessibleContext context = parent.getAccessibleContext();
                if (context != null)
                {
                    if (context.getAccessibleChildCount() > 0)
                    {
                        for (int i = 0; i < context.getAccessibleChildCount(); i++)
                        {
                            try
                            {
                                var child = context.getAccessibleChild(i);
                                if (child != null)
                                {
                                    children.Add(child);
                                    children.AddRange(GetAllChildrenOfAccessibleObject(child));
                                }
                            }
                            catch (Exception ex) { Logger.Instance.Log(LogPriority.DEBUG, "can't get all childen from XAccessible", ex); }
                        }
                    }
                }
            }
            return children;
        }
 /// <summary>
 /// Gets the name of the accessible child with.
 /// </summary>
 /// <param name="name">The name.</param>
 /// <param name="haystack">The haystack.</param>
 /// <returns>The first found XAccessible with a partly equal name or NULL</returns>
 public static XAccessible GetAccessibleChildWithName(String name, XAccessible haystack)
 {
     if (haystack != null && !String.IsNullOrWhiteSpace(name))
     {
         if (haystack is XAccessibleContext) return GetAccessibleChildWithName(name, haystack as XAccessibleContext);
         else return GetAccessibleChildWithName(name, haystack.getAccessibleContext());
     }
     return null;
 }
        /// <summary>
        /// Try to gets all selected child elements.
        /// </summary>
        /// <param name="parent">The parent.</param>
        /// <returns>A list of elements that have the AccessibleStateType.SELECTED = 23</returns>
        public static List<XAccessible> GetSelectedChildObjects(XAccessible parent)
        {
            List<XAccessible> selections = new List<XAccessible>();

            if (parent != null)
            {
                XAccessibleContext context = parent.getAccessibleContext();
                if (context != null)
                {
                    if (HasAccessibleState(parent, AccessibleStateType.SELECTED))
                    {
                        selections.Add(parent); //TODO: check type (context or XAccessible)
                    }
                    else
                    {
                        if (context.getAccessibleChildCount() > 0)
                        {
                            for (int i = 0; i < context.getAccessibleChildCount(); i++)
                            {
                                selections.AddRange(GetSelectedChildObjects(context.getAccessibleChild(i)));
                            }
                        }
                    }
                }
            }
            return selections;
        }
 /// <summary>
 /// Determines whether the the specified element contains accessible state (Must not be right!!).
 /// </summary>
 /// <param name="obj">The element to test.</param>
 /// <param name="state">The AccessibleStateType to test for.</param>
 /// <returns>
 /// 	<c>true</c> if [contains accessible state]; otherwise, <c>false</c>.
 /// </returns>
 public static bool ContainsAccessibleState(XAccessible obj, AccessibleStateType state)
 {
     if (obj != null)
     {
         XAccessibleContext context = obj.getAccessibleContext();
         if (context != null)
         {
             var states = context.getAccessibleStateSet();
             if (states != null)
             {
                 return states.contains((short)state); ;
             }
         }
     }
     return false;
 }
        /// <summary>
        /// Try to gets the root pane parent from the element.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns>the XAccessible parent with role <c>AccessibleRole.ROOT_PANE</c> or <c>null</c></returns>
        public static XAccessible GetRootPaneFromElement(XAccessible element)
        {

            //XAccessible root = null;
            if (element != null)
            {
                XAccessibleContext cnt = element.getAccessibleContext();
                XAccessible parent = cnt.getAccessibleParent();

                int trys = 0;

                while (cnt != null
                    && parent != null
                    && !element.Equals(parent)
                    )
                {
                    // only for debug
                    var role = GetAccessibleRole(cnt);

                    if (!role.Equals(AccessibleRole.UNKNOWN))
                    {

                        trys = 0;
                        element = parent;

                        if (element != null) cnt = element.getAccessibleContext();
                        else cnt = null;

                        var role2 = GetAccessibleRole(cnt);

                        if (role2.Equals(AccessibleRole.ROOT_PANE))
                        {
                            return element;
                        }
                    }
                    else
                    {
                        if (++trys > 5) break;
                        Thread.Sleep(100);
                    }
                }

                Logger.Instance.Log(LogPriority.DEBUG, "OoAccessibility", "Can't get root pane - loop break");
            }

            return null;
        }
 /// <summary>
 /// Determines whether [has accessible state] [the specified obj].
 /// </summary>
 /// <param name="obj">The obj.</param>
 /// <param name="state">The state.</param>
 /// <returns>
 /// 	<c>true</c> if [has accessible state] [the specified obj]; otherwise, <c>false</c>.
 /// </returns>
 public static bool HasAccessibleState(XAccessible obj, AccessibleStateType state)
 {
     if (obj != null)
     {
         try
         {
             XAccessibleContext context = obj.getAccessibleContext();
             if (context != null)
             {
                 var states = context.getAccessibleStateSet();
                 if (states != null)
                 {
                     bool contains = states.contains((short)state);
                     if (contains)
                     {
                         short[] stateArray = states.getStates();
                         bool exists = Array.Exists(stateArray,
                                         delegate(short s) { return s.Equals((short)state); }
                                     );
                         contains = exists;
                     }
                     return contains;
                 }
             }
         }
         catch (DisposedException) { }
     }
     return false;
 }
 /// <summary>
 /// Prints some accessible infos into the Debug Output.
 /// </summary>
 /// <param name="obj">The obj.</param>
 public static String PrintAccessibleInfos(XAccessible obj, bool printStates = false)
 {
     if (obj != null)
     {
         XAccessibleContext accessibleContext = obj.getAccessibleContext();
         return PrintAccessibleInfos(accessibleContext, printStates);
     }
     return String.Empty;
 }
 /// <summary>
 /// Gets the accessible description.
 /// </summary>
 /// <param name="obj">The obj.</param>
 /// <returns></returns>
 public static String GetAccessibleDesc(XAccessible obj) { return obj != null ? GetAccessibleDesc(obj.getAccessibleContext()) : String.Empty; }