/// <summary> /// Tries to get the parent of an XShape. /// </summary> /// <param name="parent">The parent. /// Can be <c>NULL</c> if no parent is available - could bee the case when the /// shape was deleted but not disposed for keeping it in undo/history</param> /// <param name="shape">The shape.</param> /// <returns><c>true</c> if the parent could been get, otherwise <c>false</c></returns> /// <remarks>This function is time limited to 200 ms.</remarks> bool tryGetParentByXShape(out XShapes parent, XShape shape = null) { bool success = false; XShapes par = null; TimeLimitExecutor.WaitForExecuteWithTimeLimit(200, () => { if (shape == null) { shape = Shape; } if (shape != null && shape is XChild) { var Parent = ((XChild)shape).getParent(); if (Parent != null) { par = Parent as XShapes; success = true; } } }, "GetParent"); parent = par; return(success); }
/// <summary> /// Tries to the get current selection. /// </summary> /// <param name="doc">The document window.</param> /// <param name="selectedShapesList">The list of currently selected shapes.</param> /// <returns><c>true</c> if the selection could be achieved; otherwise <c>false</c> (e.g. because it was aborted by time limit)</returns> /// <remarks>This request is time limited to 300 ms.</remarks> public bool TryGetSelection(OoAccessibleDocWnd doc, out OoAccessibilitySelection selection) { selection = null; List <OoShapeObserver> selectedShapesList2 = new List <OoShapeObserver>(); bool innerSuccess = false; bool success = false; if (doc != null) { try { if (_cachedSelection.ContainsKey(doc)) { int i = 0; while (!_cachedSelection.TryGetValue(doc, out selection) && i++ < 3) { Thread.Sleep(5); } if (i < 3) { if (selection != null && DateTime.Now - selection.SelectionCreationTime < new TimeSpan(0, 1, 0)) { //System.Diagnostics.Debug.WriteLine("******* GET Cached Selection for WND: " + doc + " result in " + selection.Count + " selected Items."); return(true); } } } success = TimeLimitExecutor.WaitForExecuteWithTimeLimit(300, () => { try { lock (doc.SynchLock) { innerSuccess = tryGetSelection(doc, out selectedShapesList2); } } catch { innerSuccess = false; } }, "HandleSelectionChanged"); var selection2 = new OoAccessibilitySelection(doc, selectedShapesList2); if (success & innerSuccess) { //System.Diagnostics.Debug.WriteLine("++++++ ADD to cached Selection for WND: " + doc + " result in " + selection2.Count + " selected Items."); _cachedSelection.AddOrUpdate(doc, selection2, (key, oldValue) => selection2); selection = selection2; } //else resetSelectionCache(); } catch (ThreadInterruptedException) { } catch (ThreadAbortException) { } } //System.Diagnostics.Debug.WriteLine(".... Selection Return: " + (selection != null ? selection.Count.ToString() : " invalid selection")); return(success & innerSuccess); }
/// <summary> /// Gets the page number. /// </summary> /// <returns>The current number of this page (Numbers are starting with 1)</returns> /// <remarks>This function is time limited to 100 ms.</remarks> public int GetPageNum() { TimeLimitExecutor.WaitForExecuteWithTimeLimit( 100, new Action(() => { CachedPageNum = OoUtils.GetIntProperty(DrawPage, "Number"); }) , "PageObserver-GetPageNum"); return(CachedPageNum); }
/// <summary> /// tries to calculate the absolute on screen bounding box in px of some given rectangle or if none is provided, based on the shape observer dom position, openoffice zoom etc. /// the accessibility interface is used for getting the controller main window position on the screen /// </summary> /// <param name="relativeBounds">the given relative bounds are used for transformation into absolute px coordinates. /// if the given value is null, getRelativeScreenBoundsByDom() of this shape observer will be called /// </param> /// <returns>Bounding box in pixels as absolute screen position.</returns> /// <remarks>Parts of this function are time limited to 100 ms.</remarks> virtual public System.Drawing.Rectangle GetAbsoluteScreenBoundsByDom(System.Drawing.Rectangle relativeBounds) { if (_updatingBounds) { return(_lastBounds); } _updatingBounds = true; System.Drawing.Rectangle result = new System.Drawing.Rectangle(); try { result = (relativeBounds.Height * relativeBounds.Width <= 0) ? GetRelativeScreenBoundsByDom() : relativeBounds; //XModel docModel = (XModel)GetDocument(); if (result.Width * result.Height > 0 //&& docModel != null ) { // get page properties like zoom and offset //docModel.lockControllers(); try { TimeLimitExecutor.WaitForExecuteWithTimeLimit(100, () => { try { // add offset for draw view XAccessibleComponent xaCmp = (XAccessibleComponent)Page.PagesObserver.DocWnd.Document.getAccessibleContext(); Point drawViewWindowPos = (xaCmp != null) ? xaCmp.getLocationOnScreen() : new Point(0, 0); result.X = result.X + drawViewWindowPos.X; result.Y = result.Y + drawViewWindowPos.Y; } catch (System.Threading.ThreadAbortException) { } }, "GetAbsoluteScreenBoundsByDom [" + Name + "]"); } catch (System.Threading.ThreadAbortException) { } catch (Exception ex) { Logger.Instance.Log(LogPriority.DEBUG, this, ex); } finally { // docModel.unlockControllers(); } } else { Logger.Instance.Log(LogPriority.DEBUG, this, "[NOTICE] can't get relative screen bounds from shape "); } _lastBounds = result; } finally { _updatingBounds = false; } return(result); }
/// <summary> /// Gets the first child of the current page. /// </summary> /// <returns></returns> public OoShapeObserver GetFirstChild() { OoShapeObserver shapeObs = null; if (DrawPage != null && PagesObserver != null) { if (DrawPage is XDrawPage) { TimeLimitExecutor.WaitForExecuteWithTimeLimit(500, () => { try { int childCount = ((XDrawPage)DrawPage).getCount(); if (childCount > 0) { var anyFirstChild = ((XDrawPage)DrawPage).getByIndex(0); if (anyFirstChild.hasValue()) { var firstChild = anyFirstChild.Value; if (firstChild is XShape) { shapeObs = PagesObserver.GetRegisteredShapeObserver(firstChild as XShape, this); if (shapeObs != null) { if (shapeObs.AcccessibleCounterpart == null) { shapeObs.Update(); } } else { //TODO: register this shape OoShapeObserver newShapeObserver = OoShapeObserverFactory.BuildShapeObserver(firstChild, this); //new OoShapeObserver(firstChild as XShape, this); PagesObserver.RegisterUniqueShape(newShapeObserver); shapeObs = newShapeObserver; } } else { //util.Debug.GetAllInterfacesOfObject(firstChild); Logger.Instance.Log(LogPriority.DEBUG, this, "[UNEXPECTED] The first child of a page is not a shape!: "); } } } } catch (System.Exception ex) { Logger.Instance.Log(LogPriority.IMPORTANT, this, "[ERROR] Can't get first child: " + ex); } }, "GetFirstChild"); } } return(shapeObs); }
/// <summary> /// Updates the page properties. /// </summary> /// <param name="forceUpdate">if set to <c>true</c> to force an update even if the page is currently not the active one.</param> /// <returns> /// <c>true</c> if the update was successfully fulfilled. /// </returns> /// <remarks>This function is time limited to 200 ms.</remarks> public bool updatePageProperties(bool forceUpdate = false) { if (!forceUpdate && !IsActive()) { return(true); } DateTime now = DateTime.Now; if (now - _lastPagePropertyUpdate < _propertyUpdateTimespan) { return(false); } //System.Diagnostics.Debug.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + " +++++++++ Update page properties REQUEST ["+this.GetHashCode()+"] +++++++++"); bool successs = false; lock (this.PagesObserver.DocWnd.SynchLock) { try { if (!_propertyUpdating && DrawPage != null) { _propertyUpdating = true; try { successs = TimeLimitExecutor.WaitForExecuteWithTimeLimit(200, new Action(() => { Width = OoUtils.GetIntProperty(DrawPage, "Width"); Height = OoUtils.GetIntProperty(DrawPage, "Height"); BorderBottom = OoUtils.GetIntProperty(DrawPage, "BorderBottom"); BorderLeft = OoUtils.GetIntProperty(DrawPage, "BorderLeft"); BorderRight = OoUtils.GetIntProperty(DrawPage, "BorderRight"); BorderTop = OoUtils.GetIntProperty(DrawPage, "BorderTop"); Orientation = (tud.mci.tangram.util.OO.PaperOrientation)OoUtils.GetProperty(DrawPage, "Orientation"); }), "UpdatePageProperties"); } catch (NullReferenceException) { ((IDisposable)this).Dispose(); } catch (DisposedException) { ((IDisposable)this).Dispose(); } _lastPagePropertyUpdate = now; return(successs); } } catch { } finally { _propertyUpdating = false; } } return(successs); }
private void updateBounds(bool throwEvent = false) { var success = TimeLimitExecutor.WaitForExecuteWithTimeLimit(500, () => { System.Drawing.Rectangle bounds = new System.Drawing.Rectangle(); System.Drawing.Rectangle screenBounds = new System.Drawing.Rectangle(); if (SelectedItems != null && SelectedItems.Count > 0) { foreach (OoShapeObserver item in SelectedItems) { System.Drawing.Rectangle tempSbRel = item.GetRelativeScreenBoundsByDom(); System.Drawing.Rectangle tempSbAbs = item.GetAbsoluteScreenBoundsByDom(tempSbRel); if (tempSbRel.Height > 0 || tempSbRel.Width > 0) { if (bounds.Width == 0 && bounds.Height == 0) //initial set { bounds = tempSbRel; screenBounds = tempSbAbs; } else { int right = Math.Max(bounds.Right, tempSbRel.Right); int bottom = Math.Max(bounds.Bottom, tempSbRel.Bottom); bounds.X = Math.Min(bounds.X, tempSbRel.X); bounds.Y = Math.Min(bounds.Y, tempSbRel.Y); screenBounds.X = Math.Min(screenBounds.X, tempSbAbs.X); screenBounds.Y = Math.Min(screenBounds.Y, tempSbAbs.Y); bounds.Width = right - bounds.X; bounds.Height = bottom - bounds.Y; screenBounds.Size = bounds.Size; } } } } this.SelectionBounds = bounds; this.SelectionScreenBounds = screenBounds; }, "updateBoundsOfShapes"); if (success == throwEvent) { OoDrawAccessibilityObserver.Instance.SelectionChanged(Source, null); } }
/// <summary> /// Saves this instance to the given file path and name. /// /// Behavior for UI's export feature. This method accepts all kinds of export filters, /// not only combined import/export filters because it implements an exporting capability, /// not a persistence capability. /// </summary> /// <returns><c>true if the save call was sent without errors.</c></returns> /// <remarks>a <c>true</c> as return value does not mean, that the file was saved successfully.</remarks> public bool SaveTo(String path, string fileType = "draw8") { bool success = false; if (DrawPageSupplier != null && DrawPageSupplier is XModifiable && !IsReadonly && !String.IsNullOrWhiteSpace(path)) { var dir = Path.GetDirectoryName(path); if (!String.IsNullOrWhiteSpace(dir)) { if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } if (Directory.Exists(dir) && !String.IsNullOrWhiteSpace(Path.GetFileName(path))) { TimeLimitExecutor.WaitForExecuteWithTimeLimit(2000, () => { try { var overwrite = new PropertyValue(); overwrite.Name = "Overwrite"; overwrite.Value = Any.Get(true); var filter = new PropertyValue(); filter.Name = "FilterName"; filter.Value = Any.Get(fileType); PropertyValue[] arguments = new PropertyValue[2] { overwrite, filter }; path = path.Replace("\\", "/"); ((XStorable)DrawPageSupplier).storeToURL(@"file:///" + path, arguments); success = true; } catch (Exception ex) { Logger.Instance.Log(LogPriority.ALWAYS, this, "[FATAL ERROR] Can't store file:", ex); } }, "Store file"); } } } return(success); }
/// <summary> /// Returns the Accessible child that is rendered under the given point. /// The test point's coordinates are defined relative to the coordinate system /// of the object. That means that when the object is an opaque rectangle then /// both the points (0,0) and (with-1,height-1) would yield a true value. /// </summary> /// <param name="p"> /// Coordinates of the test point for which to find the Accessible child. The /// origin of the coordinate system is the upper left corner of the object's /// bounding box as returned by the getBounds. The scale of the coordinate /// system is identical to that of the screen coordinate system. /// </param> /// <returns> /// If there is one child which is rendered so that its bounding box contains /// the test point then a reference to that object is returned. If there is /// more than one child which satisfies that condition then a reference to /// that one is returned that is painted on top of the others. If no there /// is no child which is rendered at the test point an empty reference is /// returned. /// </returns> public XAccessible GetAccessibleFromPoint(System.Drawing.Point p) { XAccessible result = null; if (this.AccComp != null) { TimeLimitExecutor.WaitForExecuteWithTimeLimit(500, () => { try { result = this.AccComp.getAccessibleAtPoint(new unoidl.com.sun.star.awt.Point(p.X, p.Y)); } catch { } }, "GetAccessibleATPoint"); } return(result); }
/// <summary> /// Gets the preview image bitmap data for the page. /// </summary> /// <param name="bitmapData">The bitmap data.</param> /// <remarks>This function is time limited to 100 ms.</remarks> public void GetPreview(out byte[] bitmapData) { byte[] bitmapDataResult = new byte[0]; XPropertySet pageProperties = DrawPage as XPropertySet; if (pageProperties != null) { TimeLimitExecutor.WaitForExecuteWithTimeLimit(100, () => { try { bitmapDataResult = (byte[])pageProperties.getPropertyValue("Preview").Value; } catch (ThreadAbortException) { } } , "GetPrieviewBitmap"); } bitmapData = bitmapDataResult; }
/// <summary> /// Gets the last child on the current. /// </summary> /// <returns></returns> public OoShapeObserver GetLastChild() { OoShapeObserver child = null; if (DrawPage != null && PagesObserver != null) { if (DrawPage is XDrawPage) { TimeLimitExecutor.WaitForExecuteWithTimeLimit(500, () => { try { int childCount = ((XDrawPage)DrawPage).getCount(); if (childCount > 0) { var anyLastChild = ((XDrawPage)DrawPage).getByIndex(childCount - 1); if (anyLastChild.hasValue()) { var lastChild = anyLastChild.Value; //util.Debug.GetAllInterfacesOfObject(lastChild); if (lastChild is XShape) { child = PagesObserver.GetRegisteredShapeObserver(lastChild as XShape, this); } else { Logger.Instance.Log(LogPriority.DEBUG, this, "[UNEXPECTED] The first child of a page is not a shape!"); } } } } catch (System.Exception ex) { Logger.Instance.Log(LogPriority.IMPORTANT, this, "[ERROR] Can't get last child: " + ex); } }, "GetLastChild"); } } return(child); }
/// <summary> /// Determines whether this instance is visible (has positive bounds). /// </summary> /// <returns> /// <c>true</c> if this instance is visible; otherwise, <c>false</c>. /// </returns> /// <remarks>Parts of this function are time limited to 100 ms.</remarks> public bool IsVisible() { if (IsValid()) { System.Drawing.Rectangle b = new System.Drawing.Rectangle(); var bT = TimeLimitExecutor.ExecuteWithTimeLimit(100, () => { b = Bounds; }); while (bT != null && bT.IsAlive && bT.ThreadState == ThreadState.Running) { Thread.Sleep(1); } if (b != null && b.Height > 0 && b.Width > 0) { //TODO: test the states for visible?! return(true); } } return(false); }
/// <summary> /// Determines whether this instance is valid. /// </summary> /// <returns> /// <c>true</c> if this instance is valid; otherwise, <c>false</c>. /// </returns> /// <remarks>This function is time limited to 100 ms.</remarks> public bool IsValid() { if (AccComp != null && AccCont != null) { try { int c = -1; bool success = TimeLimitExecutor.WaitForExecuteWithTimeLimit(100, () => { c = AccCont.getAccessibleChildCount(); }); if (c >= 0) { return(true); } return(false); } catch { return(false); } } return(false); }
//static readonly Object _selectionLock = new Object(); /// <summary> /// Get the current selection. /// </summary> /// <param name="selectionSupplier">The selection supplier.</param> /// <returns><c>false</c> if no selection could be achieved; otherwise and [XShapes] collection</returns> /// <remarks>This request is locked and time limited to 100 ms.</remarks> public static Object GetSelection(XSelectionSupplier selectionSupplier) { Object selection = false; if (selectionSupplier != null) { //FIXME: you cannot do this in a time limited execution this will lead to an hang on -- why?????? try { lock (selectionSupplier) { TimeLimitExecutor.WaitForExecuteWithTimeLimit(100, () => { Thread.BeginCriticalRegion(); var anySelection = selectionSupplier.getSelection(); Thread.EndCriticalRegion(); if (anySelection.hasValue()) { selection = anySelection.Value; } else { selection = null; } }, "GetSelection"); } } catch (DisposedException) { Logger.Instance.Log(LogPriority.DEBUG, "OoSelectionObserver", "Selection supplier disposed"); OO.CheckConnection(); } catch (ThreadAbortException) { } catch (ThreadInterruptedException) { } } return(selection); }
/// <summary> /// Saves this instance. /// /// Stores the data to the URL from which it was loaded. /// Only objects which know their locations can be stored. /// </summary> /// <returns><c>true if the save call was sent without errors.</c></returns> /// <remarks>a <c>true</c> as return value does not mean, that the file was saved successfully.</remarks> public bool Save() { bool success = false; if (DrawPageSupplier != null && DrawPageSupplier is XModifiable && !IsReadonly) { TimeLimitExecutor.WaitForExecuteWithTimeLimit(2000, () => { try { if (((XStorable)DrawPageSupplier).hasLocation()) { ((XStorable)DrawPageSupplier).store(); success = true; } } catch (Exception ex) { Logger.Instance.Log(LogPriority.ALWAYS, this, "[FATAL ERROR] Can't store file:", ex); } }, "Store file"); } return(success); }
void XSelectionChangeListener.selectionChanged(unoidl.com.sun.star.lang.EventObject aEvent) { TimeLimitExecutor.ExecuteWithTimeLimit(500, () => { fireSelectionEvent(aEvent); }, "SelectionChanged"); }
/// <summary> /// Handles accessible events. /// </summary> /// <param name="aEvent">a event.</param> /// <remarks>This Event handler it time limited to 15,000 ms.</remarks> void XAccessibleEventListener.notifyEvent(AccessibleEventObject aEvent) { TimeLimitExecutor.ExecuteWithTimeLimit(15000, delegate() { fireSelectionEvent(aEvent); }, "AccEvntFrwd_NotifyEvent"); }
/// <summary> /// Determines whether this instance is valid. /// </summary> /// <param name="force">forces a revalidation; otherwise a revalidation is only applied every ~5 sec. to save performance - in such a case the last validation value will be returned. </param> /// <returns> /// <c>true</c> if this instance is valid; otherwise, <c>false</c>. /// </returns> /// <remarks>Parts of this function are time limited to 100 ms.</remarks> virtual public bool IsValid(bool force = true) { if (!_valid) { return(false); } if (LockValidation) { return(_valid); } long ts = DateTime.UtcNow.Ticks; if (!force && (ts - _lastValidation < _validationTreshold)) { return(_valid); } _valid = true; lock (SynchLock) { try { if (!Disposed && Shape != null && Page != null) { TimeLimitExecutor.WaitForExecuteWithTimeLimit(100, () => { try { var test1 = Shape.GetHashCode(); string uiName = UINameSingular; if (test1 == 0 || String.IsNullOrEmpty(uiName)) { _valid = false; Dispose(); return; } if (AcccessibleCounterpart != null) { AcccessibleCounterpart.GetHashCode(); } else { Update(); } if (!OoUtils.ElementSupportsService(Shape, OO.Services.DRAW_SHAPE)) { _valid = false; return; } //var services = util.Debug.GetAllServicesOfObject(Shape, false); //if (services.Length == 0) //{ // valid = false; // return; //} //// test if a parent exists //XShapes parent; //bool parentSuccess = tryGetParentByXShape(out parent, Shape); //if (parentSuccess && parent == null) //{ // valid = false; // // should bee disposed?! // Dispose(); // return; //} _valid = true; } catch (System.Threading.ThreadAbortException) { DisableValidationTemporary(); } catch (System.Threading.ThreadInterruptedException) { DisableValidationTemporary(); } }, "ShapeValidation Shape " + _lastName); } else { _valid = false; } } catch (unoidl.com.sun.star.lang.DisposedException) { Dispose(); } catch { } } _lastValidation = ts; return(_valid); }