Пример #1
0
        ///
        override protected bool IsOffscreenCore()
        {
            IsOffscreenBehavior behavior = AutomationProperties.GetIsOffscreenBehavior(_owner);

            switch (behavior)
            {
            case IsOffscreenBehavior.Onscreen:
                return(false);

            case IsOffscreenBehavior.Offscreen:
                return(true);

            case IsOffscreenBehavior.FromClip:
            {
                bool isOffscreen = !_owner.IsVisible;

                if (!isOffscreen)
                {
                    UIElement containingUIElement = GetContainingUIElement(_owner);
                    if (containingUIElement != null)
                    {
                        Rect boundingRect = UIElementAutomationPeer.CalculateVisibleBoundingRect(containingUIElement);

                        isOffscreen = (DoubleUtil.AreClose(boundingRect, Rect.Empty) ||
                                       DoubleUtil.AreClose(boundingRect.Height, 0) ||
                                       DoubleUtil.AreClose(boundingRect.Width, 0));
                    }
                }

                return(isOffscreen);
            }

            default:
                return(!_owner.IsVisible);
            }
        }
Пример #2
0
        // Verifies scrolling data using the passed viewport and extent as newly computed values.
        // Checks the X/Y offset and coerces them into the range [0, Extent - ViewportSize]
        // If extent, viewport, or the newly coerced offsets are different than the existing offset,
        //   cachces are updated and InvalidateScrollInfo() is called.
        private void VerifyScrollData(double viewportWidth, double extentWidth)
        {
            var isValid = true;

            if (double.IsInfinity(viewportWidth))
            {
                viewportWidth = extentWidth;
            }

            var offsetX = CoerceOffset(this.ScrollData.OffsetX, extentWidth, viewportWidth);

            isValid &= DoubleUtil.AreClose(viewportWidth, this.ScrollData.ViewportWidth);
            isValid &= DoubleUtil.AreClose(extentWidth, this.ScrollData.ExtentWidth);
            isValid &= DoubleUtil.AreClose(this.ScrollData.OffsetX, offsetX);

            this.ScrollData.ViewportWidth = viewportWidth;
            this.ScrollData.ExtentWidth   = extentWidth;
            this.ScrollData.OffsetX       = offsetX;

            if (isValid == false)
            {
                this.ScrollOwner?.InvalidateScrollInfo();
            }
        }
Пример #3
0
        internal override bool AreClose(Geometry geometry)
        {
            RectangleGeometry rectGeometry2 = geometry as RectangleGeometry;

            if (rectGeometry2 != null)
            {
                RectangleGeometry rectGeometry1 = this;
                Rect rect1 = rectGeometry1.Rect;
                Rect rect2 = rectGeometry2.Rect;

                return(
                    DoubleUtil.AreClose(rect1.X, rect2.X) &&
                    DoubleUtil.AreClose(rect1.Y, rect2.Y) &&
                    DoubleUtil.AreClose(rect1.Width, rect2.Width) &&
                    DoubleUtil.AreClose(rect1.Height, rect2.Height) &&
                    DoubleUtil.AreClose(rectGeometry1.RadiusX, rectGeometry2.RadiusX) &&
                    DoubleUtil.AreClose(rectGeometry1.RadiusY, rectGeometry2.RadiusY) &&
                    (rectGeometry1.Transform == rectGeometry2.Transform) &&
                    (rectGeometry1.IsFrozen == rectGeometry2.IsFrozen)
                    );
            }

            return(base.AreClose(geometry));
        }
Пример #4
0
        // Parse a GridLength from a string given the CultureInfo.
        static internal void FromString(
            string s,
            CultureInfo cultureInfo,
            out double value,
            out GridUnitType unit)
        {
            string goodString = s.Trim().ToLowerInvariant();

            value = 0.0;
            unit  = GridUnitType.Pixel;

            int    i;
            int    strLen     = goodString.Length;
            int    strLenUnit = 0;
            double unitFactor = 1.0;

            //  this is where we would handle trailing whitespace on the input string.
            //  peel [unit] off the end of the string
            i = 0;

            if (goodString == UnitStrings[i])
            {
                strLenUnit = UnitStrings[i].Length;
                unit       = (GridUnitType)i;
            }
            else
            {
                for (i = 1; i < UnitStrings.Length; ++i)
                {
                    //  Note: this is NOT a culture specific comparison.
                    //  this is by design: we want the same unit string table to work across all cultures.
                    if (goodString.EndsWith(UnitStrings[i], StringComparison.Ordinal))
                    {
                        strLenUnit = UnitStrings[i].Length;
                        unit       = (GridUnitType)i;
                        break;
                    }
                }
            }

            //  we couldn't match a real unit from GridUnitTypes.
            //  try again with a converter-only unit (a pixel equivalent).
            if (i >= UnitStrings.Length)
            {
                for (i = 0; i < PixelUnitStrings.Length; ++i)
                {
                    //  Note: this is NOT a culture specific comparison.
                    //  this is by design: we want the same unit string table to work across all cultures.
                    if (goodString.EndsWith(PixelUnitStrings[i], StringComparison.Ordinal))
                    {
                        strLenUnit = PixelUnitStrings[i].Length;
                        unitFactor = PixelUnitFactors[i];
                        break;
                    }
                }
            }

            //  this is where we would handle leading whitespace on the input string.
            //  this is also where we would handle whitespace between [value] and [unit].
            //  check if we don't have a [value].  This is acceptable for certain UnitTypes.
            if (strLen == strLenUnit &&
                (unit == GridUnitType.Auto ||
                 unit == GridUnitType.Star))
            {
                value = 1;
            }
            //  we have a value to parse.
            else
            {
                Debug.Assert(unit == GridUnitType.Pixel ||
                             DoubleUtil.AreClose(unitFactor, 1.0));

                string valueString = goodString.Substring(0, strLen - strLenUnit);
                value = Convert.ToDouble(valueString, cultureInfo) * unitFactor;
            }
        }
 protected override bool CanRender(RenderContext2D context)
 {
     return(base.CanRender(context) && !DoubleUtil.AreClose(StartAngle, EndAngle));
 }
Пример #6
0
        /// <summary>TBS</summary>
        private bool Contains(Point point)
        {
            if (false == _boundingBox.Contains(point))
            {
                return(false);
            }

            bool isHigher = false;
            int  last     = _lasso.Count;

            while (--last >= 0)
            {
                if (false == DoubleUtil.AreClose(_lasso[last].Y, point.Y))
                {
                    isHigher = point.Y < _lasso[last].Y;
                    break;
                }
            }

            bool  isInside = false, isOnClosingSegment = false;
            Point prevLassoPoint = _lasso[_lasso.Count - 1];

            for (int i = 0; i < _lasso.Count; i++)
            {
                Point lassoPoint = _lasso[i];

                if (DoubleUtil.AreClose(lassoPoint.Y, point.Y))
                {
                    if (DoubleUtil.AreClose(lassoPoint.X, point.X))
                    {
                        isInside = true;
                        break;
                    }

                    if ((0 != i) && DoubleUtil.AreClose(prevLassoPoint.Y, point.Y) &&
                        DoubleUtil.GreaterThanOrClose(point.X, Math.Min(prevLassoPoint.X, lassoPoint.X)) &&
                        DoubleUtil.LessThanOrClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X)))
                    {
                        isInside = true;
                        break;
                    }
                }
                else if (isHigher != (point.Y < lassoPoint.Y))
                {
                    isHigher = !isHigher;
                    if (DoubleUtil.GreaterThanOrClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X)))
                    {
                        // there certainly is an intersection on the left
                        isInside = !isInside;

                        // The closing segment is the only exclusive one. Special case it.
                        if ((0 == i) && DoubleUtil.AreClose(point.X, Math.Max(prevLassoPoint.X, lassoPoint.X)))
                        {
                            isOnClosingSegment = true;
                        }
                    }
                    else if (DoubleUtil.GreaterThanOrClose(point.X, Math.Min(prevLassoPoint.X, lassoPoint.X)))
                    {
                        // The X of the point lies within the x ranges for the segment.
                        // Calculate the x value of the point where the segment intersects with the line.
                        Vector lassoSegment = lassoPoint - prevLassoPoint;
                        double x            = prevLassoPoint.X + (lassoSegment.X / lassoSegment.Y) * (point.Y - prevLassoPoint.Y);

                        if (DoubleUtil.GreaterThanOrClose(point.X, x))
                        {
                            isInside = !isInside;
                            if ((0 == i) && DoubleUtil.AreClose(point.X, x))
                            {
                                isOnClosingSegment = true;
                            }
                        }
                    }
                }

                prevLassoPoint = lassoPoint;
            }

            return(isInside ? !isOnClosingSegment : false);
        }
Пример #7
0
        /// <inheritdoc />
        protected override Size MeasureOverride(Size availableSize)
        {
            var allGroupsWidth = 0D;

            this.sizes.Clear();

            var availableSizeHeight = availableSize.Height;

            if (double.IsPositiveInfinity(availableSizeHeight))
            {
                availableSizeHeight = 0;
            }

            foreach (RibbonContextualTabGroup contextualGroup in this.InternalChildren)
            {
                // Calculate width of tab items of the group
                var tabsWidth = 0D;

                // We have to look at visible and items which already got measured only
                var visibleItems = contextualGroup.Items.Where(item => item.Visibility == Visibility.Visible && DoubleUtil.AreClose(item.DesiredSize.Width, 0) == false).ToList();

                foreach (var item in visibleItems)
                {
                    tabsWidth += item.DesiredSize.Width;
                }

                contextualGroup.Measure(SizeConstants.Infinite);
                var groupWidth = contextualGroup.DesiredSize.Width;

                var tabWasChanged = false;

                if (groupWidth > tabsWidth)
                {
                    // If tab's width is less than group's width we have to stretch tabs
                    var delta = (groupWidth - tabsWidth) / visibleItems.Count;

                    foreach (var item in visibleItems)
                    {
                        var newDesiredWidth = item.DesiredSize.Width + delta;

                        // Update cached DesiredWidth
                        if (DoubleUtil.AreClose(newDesiredWidth, item.DesiredWidth) == false)
                        {
                            item.DesiredWidth = newDesiredWidth;
                            item.Measure(new Size(item.DesiredWidth, item.DesiredSize.Height));
                            tabWasChanged = true;
                        }
                    }
                }

                if (tabWasChanged)
                {
                    // If we have changed tabs layout we have
                    // to invalidate down to RibbonTabsContainer
                    var visual = visibleItems[0] as Visual;

                    while (visual != null)
                    {
                        if (visual is UIElement uiElement)
                        {
                            if (uiElement is RibbonTabsContainer)
                            {
                                uiElement.InvalidateMeasure();
                                break;
                            }

                            uiElement.InvalidateMeasure();
                        }

                        visual = VisualTreeHelper.GetParent(visual) as Visual;
                    }

                    tabsWidth = 0;

                    foreach (var item in visibleItems)
                    {
                        tabsWidth += item.DesiredSize.Width;
                    }
                }

                // Calc final width and measure the group using it
                var finalWidth = tabsWidth;
                allGroupsWidth += finalWidth;

                if (allGroupsWidth > availableSize.Width)
                {
                    finalWidth    -= allGroupsWidth - availableSize.Width;
                    allGroupsWidth = availableSize.Width;
                }

                contextualGroup.Measure(new Size(Math.Max(0, finalWidth), availableSizeHeight));
                this.sizes.Add(new Size(Math.Max(0, finalWidth), availableSizeHeight));
            }

            return(new Size(allGroupsWidth, availableSizeHeight));
        }
Пример #8
0
 /// <summary>
 /// operator ==
 /// </summary>
 /// <param name="sfiLeft"></param>
 /// <param name="sfiRight"></param>
 /// <returns></returns>
 public static bool operator ==(StrokeFIndices sfiLeft, StrokeFIndices sfiRight)
 {
     return(DoubleUtil.AreClose(sfiLeft._beginFIndex, sfiRight._beginFIndex) &&
            DoubleUtil.AreClose(sfiLeft._endFIndex, sfiRight._endFIndex));
 }
Пример #9
0
        /// <summary>
        /// Content measurement.
        /// </summary>
        /// <param name="availableSize">Available size that parent can give to the child. This is soft constraint.</param>
        /// <returns>The DocumentPageView's desired size.</returns>
        protected override sealed Size MeasureOverride(Size availableSize)
        {
            Size newPageSize, pageZoom;
            Size pageSize;
            Size desiredSize = new Size(); // If no page is available, return (0,0) as size.

            CheckDisposed();

            if (_suspendLayout)
            {
                desiredSize = this.DesiredSize;
            }
            else if (_documentPaginator != null)
            {
                // Reflow content if needed.
                if (ShouldReflowContent())
                {
                    // Reflow is disabled when dealing with infinite size in both directions.
                    // If only one dimention is infinte, calculate value based on PageSize of the
                    // document and Stretching properties.
                    if (!Double.IsInfinity(availableSize.Width) || !Double.IsInfinity(availableSize.Height))
                    {
                        pageSize = _documentPaginator.PageSize;
                        if (Double.IsInfinity(availableSize.Width))
                        {
                            newPageSize        = new Size();
                            newPageSize.Height = availableSize.Height / _pageZoom;
                            newPageSize.Width  = newPageSize.Height * (pageSize.Width / pageSize.Height); // Keep aspect ratio.
                        }
                        else if (Double.IsInfinity(availableSize.Height))
                        {
                            newPageSize        = new Size();
                            newPageSize.Width  = availableSize.Width / _pageZoom;
                            newPageSize.Height = newPageSize.Width * (pageSize.Height / pageSize.Width); // Keep aspect ratio.
                        }
                        else
                        {
                            newPageSize = new Size(availableSize.Width / _pageZoom, availableSize.Height / _pageZoom);
                        }
                        if (!DoubleUtil.AreClose(pageSize, newPageSize))
                        {
                            _documentPaginator.PageSize = newPageSize;
                        }
                    }
                }

                // If the main page or pending async page are not available yet,
                // asynchronously request new page from Paginator.
                if (_documentPage == null && _documentPageAsync == null)
                {
                    if (PageNumber >= 0)
                    {
                        if (_useAsynchronous)
                        {
                            _documentPaginator.GetPageAsync(PageNumber, this);
                        }
                        else
                        {
                            _documentPageAsync = _documentPaginator.GetPage(PageNumber);
                            if (_documentPageAsync == null)
                            {
                                _documentPageAsync = DocumentPage.Missing;
                            }
                        }
                    }
                    else
                    {
                        _documentPage = DocumentPage.Missing;
                    }
                }

                // If pending async page is available, discard the main page and
                // set _documentPage to _documentPageAsync.
                if (_documentPageAsync != null)
                {
                    // Do cleanup for currently used page, because it gets replaced.
                    DisposeCurrentPage();
                    // DisposeCurrentPage raises PageDisposed and DocumentPage.PageDestroyed events.
                    // Handlers for those events may dispose _documentPageAsync. Treat this situation
                    // as missing page.
                    if (_documentPageAsync == null)
                    {
                        _documentPageAsync = DocumentPage.Missing;
                    }
                    if (_pageVisualClone != null)
                    {
                        RemoveDuplicateVisual();
                    }

                    // Replace the main page with cached async page.
                    _documentPage = _documentPageAsync;
                    if (_documentPage != DocumentPage.Missing)
                    {
                        _documentPage.PageDestroyed      += new EventHandler(HandlePageDestroyed);
                        _documentPageAsync.PageDestroyed -= new EventHandler(HandleAsyncPageDestroyed);
                    }
                    _documentPageAsync = null;

                    // Set a flag that will indicate that a PageConnected must be fired in
                    // ArrangeOverride
                    _newPageConnected = true;
                }

                // If page is available, return its size as desired size.
                if (_documentPage != null && _documentPage != DocumentPage.Missing)
                {
                    pageSize    = new Size(_documentPage.Size.Width * _pageZoom, _documentPage.Size.Height * _pageZoom);
                    pageZoom    = Viewbox.ComputeScaleFactor(availableSize, pageSize, this.Stretch, this.StretchDirection);
                    desiredSize = new Size(pageSize.Width * pageZoom.Width, pageSize.Height * pageZoom.Height);
                }

                if (_pageVisualClone != null)
                {
                    desiredSize = _visualCloneSize;
                }
            }

            return(desiredSize);
        }
Пример #10
0
        /// <summary>
        /// Clip-Testing a circluar inking segment against a linear segment.
        /// See http://tabletpc/longhorn/Specs/Rendering%20and%20Hit-Testing%20Ink%20in%20Avalon%20M11.doc section
        /// 5.4.4.14	Clip-Testing a Circular Inking Segment against a Linear Segment for details of the algorithm
        /// </summary>
        /// <param name="spineVector">Represent the spine of the inking segment pointing from the beginNode to endNode</param>
        /// <param name="beginRadius">Radius of the beginNode</param>
        /// <param name="endRadius">Radius of the endNode</param>
        /// <param name="hitBegin">Hitting segment start point</param>
        /// <param name="hitEnd">Hitting segment end point</param>
        /// <returns>A double which represents the location for cutting</returns>
        private static double ClipTest(Vector spineVector, double beginRadius, double endRadius, Vector hitBegin, Vector hitEnd)
        {
            // First handle the special case when the spineVector is (0,0). In other words, this is the case
            // when the stylus stays at the the location but pressure changes.
            if (DoubleUtil.IsZero(spineVector.X) && DoubleUtil.IsZero(spineVector.Y))
            {
                System.Diagnostics.Debug.Assert(DoubleUtil.AreClose(beginRadius, endRadius) == false);

                Vector nearest = GetNearest(hitBegin, hitEnd);
                double radius;
                if (nearest.X == 0)
                {
                    radius = Math.Abs(nearest.Y);
                }
                else if (nearest.Y == 0)
                {
                    radius = Math.Abs(nearest.X);
                }
                else
                {
                    radius = nearest.Length;
                }
                return(AdjustFIndex((radius - beginRadius) / (endRadius - beginRadius)));
            }

            // This change to ClipTest with a point if the two hitting segment are close enough.
            if (DoubleUtil.AreClose(hitBegin, hitEnd))
            {
                return(ClipTest(spineVector, beginRadius, endRadius, hitBegin));
            }

            double findex;
            Vector hitVector = hitEnd - hitBegin;

            if (DoubleUtil.IsZero(Vector.Determinant(spineVector, hitVector)))
            {
                // hitVector and spineVector are parallel
                findex = ClipTest(spineVector, beginRadius, endRadius, GetNearest(hitBegin, hitEnd));
                System.Diagnostics.Debug.Assert(!double.IsNaN(findex));
            }
            else
            {
                // On the line defined by the segment find point P1Xp, the nearest to the beginNode.Position
                double x    = GetProjectionFIndex(hitBegin, hitEnd);
                Vector P1Xp = hitBegin + (hitVector * x);
                if (P1Xp.LengthSquared < (beginRadius * beginRadius))
                {
                    System.Diagnostics.Debug.Assert(DoubleUtil.IsBetweenZeroAndOne(x) == false);
                    findex = ClipTest(spineVector, beginRadius, endRadius, (0 > x) ? hitBegin : hitEnd);
                    System.Diagnostics.Debug.Assert(!double.IsNaN(findex));
                }
                else
                {
                    // Find the projection point P of endNode.Position to the line (beginNode.Position, B).
                    Vector P1P2p = spineVector + GetProjection(-spineVector, P1Xp - spineVector);

                    //System.Diagnostics.Debug.Assert(false == DoubleUtil.IsZero(P1P2p.LengthSquared));
                    //System.Diagnostics.Debug.Assert(false == DoubleUtil.IsZero(endRadius - beginRadius + P1P2p.Length));
                    // There checks are here since if either fail no real solution can be caculated and we may
                    // as well bail out now and save the caculations that are below.
                    if (DoubleUtil.IsZero(P1P2p.LengthSquared) || DoubleUtil.IsZero(endRadius - beginRadius + P1P2p.Length))
                    {
                        return(1d);
                    }

                    // Calculate the findex of the point to split the ink segment at.
                    findex = (P1Xp.Length - beginRadius) / (endRadius - beginRadius + P1P2p.Length);
                    System.Diagnostics.Debug.Assert(!double.IsNaN(findex));

                    // Find the projection of the split point to the line of this segment.
                    Vector S = spineVector * findex;

                    double r = GetProjectionFIndex(hitBegin - S, hitEnd - S);

                    // If the nearest point misses the segment, then find the findex
                    // of the node nearest to the segment.
                    if (false == DoubleUtil.IsBetweenZeroAndOne(r))
                    {
                        findex = ClipTest(spineVector, beginRadius, endRadius, (0 > r) ? hitBegin : hitEnd);
                        System.Diagnostics.Debug.Assert(!double.IsNaN(findex));
                    }
                }
            }
            return(AdjustFIndex(findex));
        }
Пример #11
0
        /// <summary>
        /// CutTest an inking StrokeNode segment (two nodes and a connecting quadrangle) against a hitting contour
        /// (represented by an enumerator of Contoursegments).
        /// </summary>
        /// <param name="beginNode">The begin StrokeNodeData</param>
        /// <param name="endNode">The end StrokeNodeData</param>
        /// <param name="quad">Connecing quadrangle between the begin and end inking node</param>
        /// <param name="hitContour">The hitting ContourSegments</param>
        /// <returns>StrokeFIndices representing the location for cutting</returns>
        internal override StrokeFIndices CutTest(
            StrokeNodeData beginNode, StrokeNodeData endNode, Quad quad, IEnumerable <ContourSegment> hitContour)
        {
            // Compute the positions of the beginNode relative to the endNode.
            Vector spineVector = beginNode.IsEmpty ? new Vector(0, 0) : (beginNode.Position - endNode.Position);

            // If the node shape is an ellipse, transform the scene to turn the shape to a circle
            if (_nodeShapeToCircle.IsIdentity == false)
            {
                spineVector = _nodeShapeToCircle.Transform(spineVector);
            }

            double beginRadius = 0, endRadius;
            double beginRadiusSquared = 0, endRadiusSquared;

            endRadius        = _radius * endNode.PressureFactor;
            endRadiusSquared = endRadius * endRadius;
            if (beginNode.IsEmpty == false)
            {
                beginRadius        = _radius * beginNode.PressureFactor;
                beginRadiusSquared = beginRadius * beginRadius;
            }

            bool           isInside = true;
            StrokeFIndices result   = StrokeFIndices.Empty;

            foreach (ContourSegment hitSegment in hitContour)
            {
                if (hitSegment.IsArc)
                {
                    // ISSUE-2004/06/15-vsmirnov - ellipse vs arc hit-testing is not implemented
                    // and currently disabled in ErasingStroke
                }
                else
                {
                    Vector hitBegin = hitSegment.Begin - endNode.Position;
                    Vector hitEnd   = hitBegin + hitSegment.Vector;

                    // If the node shape is an ellipse, transform the scene to turn
                    // the shape into circle.
                    if (_nodeShapeToCircle.IsIdentity == false)
                    {
                        hitBegin = _nodeShapeToCircle.Transform(hitBegin);
                        hitEnd   = _nodeShapeToCircle.Transform(hitEnd);
                    }

                    bool isHit = false;

                    // Hit-test the end node
                    Vector nearest = GetNearest(hitBegin, hitEnd);
                    if (nearest.LengthSquared < endRadiusSquared)
                    {
                        isHit = true;
                        if (!DoubleUtil.AreClose(result.EndFIndex, StrokeFIndices.AfterLast))
                        {
                            result.EndFIndex = StrokeFIndices.AfterLast;
                            if (beginNode.IsEmpty)
                            {
                                result.BeginFIndex = StrokeFIndices.BeforeFirst;
                                break;
                            }
                            if (DoubleUtil.AreClose(result.BeginFIndex, StrokeFIndices.BeforeFirst))
                            {
                                break;
                            }
                        }
                    }

                    if ((beginNode.IsEmpty == false) && (!isHit || !DoubleUtil.AreClose(result.BeginFIndex, StrokeFIndices.BeforeFirst)))
                    {
                        // Hit-test the first node
                        nearest = GetNearest(hitBegin - spineVector, hitEnd - spineVector);
                        if (nearest.LengthSquared < beginRadiusSquared)
                        {
                            isHit = true;
                            if (!DoubleUtil.AreClose(result.BeginFIndex, StrokeFIndices.BeforeFirst))
                            {
                                result.BeginFIndex = StrokeFIndices.BeforeFirst;
                                if (DoubleUtil.AreClose(result.EndFIndex, StrokeFIndices.AfterLast))
                                {
                                    break;
                                }
                            }
                        }
                    }

                    // If both nodes are hit or nothing is hit at all, return.
                    if (beginNode.IsEmpty || (!isHit && (quad.IsEmpty ||
                                                         (HitTestQuadSegment(quad, hitSegment.Begin, hitSegment.End) == false))))
                    {
                        if (isInside && (WhereIsVectorAboutVector(
                                             endNode.Position - hitSegment.Begin, hitSegment.Vector) != HitResult.Right))
                        {
                            isInside = false;
                        }
                        continue;
                    }

                    isInside = false;

                    // NTRAID#Window OS bug-1029694-2004/10/18-xiaotu, refactor the code to make it a method
                    // to increase the maintainability of the program. FxCop bug.
                    // Calculate the exact locations to cut.
                    CalculateCutLocations(spineVector, hitBegin, hitEnd, endRadius, beginRadius, ref result);

                    if (result.IsFull)
                    {
                        break;
                    }
                }
            }

            //
            if (!result.IsFull)
            {
                if (isInside == true)
                {
                    System.Diagnostics.Debug.Assert(result.IsEmpty);
                    result = StrokeFIndices.Full;
                }
                else if ((DoubleUtil.AreClose(result.EndFIndex, StrokeFIndices.BeforeFirst)) && (!DoubleUtil.AreClose(result.BeginFIndex, StrokeFIndices.AfterLast)))
                {
                    result.EndFIndex = StrokeFIndices.AfterLast;
                }
                else if ((DoubleUtil.AreClose(result.BeginFIndex, StrokeFIndices.AfterLast)) && (!DoubleUtil.AreClose(result.EndFIndex, StrokeFIndices.BeforeFirst)))
                {
                    result.BeginFIndex = StrokeFIndices.BeforeFirst;
                }
            }

            if (IsInvalidCutTestResult(result))
            {
                return(StrokeFIndices.Empty);
            }

            return(result);
        }
Пример #12
0
        /// <summary>
        /// Cut-test ink segment defined by two nodes and a connecting quad against a linear segment
        /// </summary>
        /// <param name="beginNode">Begin node of the ink segment</param>
        /// <param name="endNode">End node of the ink segment</param>
        /// <param name="quad">Pre-computed quadrangle connecting the two ink nodes</param>
        /// <param name="hitBeginPoint">egin point of the hitting segment</param>
        /// <param name="hitEndPoint">End point of the hitting segment</param>
        /// <returns>Exact location to cut at represented by StrokeFIndices</returns>
        internal override StrokeFIndices CutTest(
            StrokeNodeData beginNode, StrokeNodeData endNode, Quad quad, Point hitBeginPoint, Point hitEndPoint)
        {
            // Compute the positions of the involved points relative to the endNode.
            Vector spineVector = beginNode.IsEmpty ? new Vector(0, 0) : (beginNode.Position - endNode.Position);
            Vector hitBegin    = hitBeginPoint - endNode.Position;
            Vector hitEnd      = hitEndPoint - endNode.Position;

            // If the node shape is an ellipse, transform the scene to turn the shape to a circle
            if (_nodeShapeToCircle.IsIdentity == false)
            {
                spineVector = _nodeShapeToCircle.Transform(spineVector);
                hitBegin    = _nodeShapeToCircle.Transform(hitBegin);
                hitEnd      = _nodeShapeToCircle.Transform(hitEnd);
            }

            StrokeFIndices result = StrokeFIndices.Empty;

            // Hit-test the end node
            double beginRadius = 0, endRadius = _radius * endNode.PressureFactor;
            Vector nearest = GetNearest(hitBegin, hitEnd);

            if (nearest.LengthSquared <= (endRadius * endRadius))
            {
                result.EndFIndex   = StrokeFIndices.AfterLast;
                result.BeginFIndex = beginNode.IsEmpty ? StrokeFIndices.BeforeFirst : 1;
            }
            if (beginNode.IsEmpty == false)
            {
                // Hit-test the first node
                beginRadius = _radius * beginNode.PressureFactor;
                nearest     = GetNearest(hitBegin - spineVector, hitEnd - spineVector);
                if (nearest.LengthSquared <= (beginRadius * beginRadius))
                {
                    result.BeginFIndex = StrokeFIndices.BeforeFirst;
                    if (!DoubleUtil.AreClose(result.EndFIndex, StrokeFIndices.AfterLast))
                    {
                        result.EndFIndex = 0;
                    }
                }
            }

            // If both nodes are hit or nothing is hit at all, return.
            if (result.IsFull || quad.IsEmpty ||
                (result.IsEmpty && (HitTestQuadSegment(quad, hitBeginPoint, hitEndPoint) == false)))
            {
                return(result);
            }

            // Find out whether the {begin, end} segment intersects with the contour
            // of the stroke segment {_lastNode, _thisNode}, and find the lower index
            // of the fragment to cut out.
            if (!DoubleUtil.AreClose(result.BeginFIndex, StrokeFIndices.BeforeFirst))
            {
                result.BeginFIndex = ClipTest(-spineVector, beginRadius, endRadius, hitBegin - spineVector, hitEnd - spineVector);
            }

            if (!DoubleUtil.AreClose(result.EndFIndex, StrokeFIndices.AfterLast))
            {
                result.EndFIndex = 1 - ClipTest(spineVector, endRadius, beginRadius, hitBegin, hitEnd);
            }

            if (IsInvalidCutTestResult(result))
            {
                return(StrokeFIndices.Empty);
            }

            return(result);
        }
 // Token: 0x06007849 RID: 30793 RVA: 0x00224218 File Offset: 0x00222418
 protected override Size MeasureOverride(Size constraint)
 {
     if (this.ReferenceElement != null && base.AdornedElement != null && base.AdornedElement.IsMeasureValid && !DoubleUtil.AreClose(this.ReferenceElement.DesiredSize, base.AdornedElement.DesiredSize))
     {
         this.ReferenceElement.InvalidateMeasure();
     }
     this._child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
     return(this._child.DesiredSize);
 }
Пример #14
0
        /// <summary>
        ///     Measure
        /// </summary>
        protected override Size MeasureOverride(Size availableSize)
        {
            // Note: The logic below assumes that the TabHeaders belonging to inactive
            // ContextualTabGroups have their IsVisible set to false.

            //_separatorOpacity = 0.0;
            Size desiredSize = new Size();

            UIElementCollection children = InternalChildren;

            if (children.Count == 0)
            {
                return(desiredSize);
            }

            Size   childConstraint  = new Size(double.PositiveInfinity, availableSize.Height);
            int    countRegularTabs = 0;
            double totalDefaultPaddingAllTabHeaders     = 0;
            double totalDefaultPaddingRegularTabHeaders = 0;
            double totalDesiredWidthRegularTabHeaders   = 0;
            bool   showRegularTabHeaderToolTips         = false;
            bool   showContextualTabHeaderToolTips      = false;
            int    countVisibleTabs = 0;

            // Measure all TabHeaders to fit their content
            // desiredSize should hold the total size required to fit all TabHeaders
            desiredSize = InitialMeasure(childConstraint,
                                         out totalDefaultPaddingAllTabHeaders,
                                         out totalDefaultPaddingRegularTabHeaders,
                                         out totalDesiredWidthRegularTabHeaders,
                                         out countRegularTabs,
                                         out countVisibleTabs);

            int countContextualTabs = countVisibleTabs - countRegularTabs;

            SpaceAvailable = 0.0;
            double overflowWidth = desiredSize.Width - availableSize.Width;             // Total overflow width

            if (DoubleUtil.GreaterThan(overflowWidth, 0))
            {
                // Calculate max tab width if tab clipping is necessary
                double totalClipWidthRegularTabHeaders    = 0;                               // How much pixels we need to clip regular tabs
                double totalClipWidthContextualTabHeaders = 0;                               // How much pixels we need to clip contextual tabs

                if (DoubleUtil.GreaterThan(overflowWidth, totalDefaultPaddingAllTabHeaders)) // Clipping is necessary - all tabs padding will we 0
                {
                    showRegularTabHeaderToolTips    = true;
                    totalClipWidthRegularTabHeaders = overflowWidth - totalDefaultPaddingAllTabHeaders;                     // Try to use the whole totalClipAmount in the regular tabs
                }

                double maxRegularTabHeaderWidth = CalculateMaxTabHeaderWidth(totalClipWidthRegularTabHeaders, false);
                if (DoubleUtil.AreClose(maxRegularTabHeaderWidth, _tabHeaderMinWidth))                 // Regular tabs are clipped to the min size -  need to clip contextual tabs
                {
                    showContextualTabHeaderToolTips = true;
                    double totalClipAmount = overflowWidth - totalDefaultPaddingAllTabHeaders;
                    double usedClipAmount  = totalDesiredWidthRegularTabHeaders - totalDefaultPaddingRegularTabHeaders - (_tabHeaderMinWidth * countRegularTabs);
                    totalClipWidthContextualTabHeaders = totalClipAmount - usedClipAmount;                     // Remaining clipping amount
                }

                double maxContextualTabHeaderWidth      = CalculateMaxTabHeaderWidth(totalClipWidthContextualTabHeaders, true);
                double reducePaddingRegularTabHeader    = 0;
                double reducePaddingContextualTabHeader = 0;

                if (DoubleUtil.GreaterThanOrClose(totalDefaultPaddingRegularTabHeaders, overflowWidth))
                {
                    reducePaddingRegularTabHeader = (0.5 * overflowWidth) / countRegularTabs;
                    //_separatorOpacity = Math.Max(0.0, reducePaddingRegularTabHeader * 0.2);
                }
                else
                {
                    //_separatorOpacity = 1.0;
                    reducePaddingRegularTabHeader = double.PositiveInfinity;
                    // If countContextualTabs==0 then reducePaddingContextualTab will become Infinity
                    reducePaddingContextualTabHeader = (0.5 * (overflowWidth - totalDefaultPaddingRegularTabHeaders)) / (countVisibleTabs - countRegularTabs);
                }

                desiredSize = FinalMeasure(childConstraint,
                                           reducePaddingContextualTabHeader,
                                           reducePaddingRegularTabHeader,
                                           maxContextualTabHeaderWidth,
                                           maxRegularTabHeaderWidth);
            }
            else if (countContextualTabs > 0)
            {
                // After assigning DefaultPadding, we are left with extra space.
                // If contextual tabs need that extra space, assign them more padding.
                NotifyDesiredWidthChanged();
                double spaceAvailable            = availableSize.Width - desiredSize.Width;
                double availableExtraWidthPerTab = CalculateMaxPadding(spaceAvailable);

                foreach (UIElement child in InternalChildren)
                {
                    RibbonTabHeader ribbonTabHeader = child as RibbonTabHeader;
                    if (ribbonTabHeader != null && ribbonTabHeader.IsVisible && ribbonTabHeader.IsContextualTab)
                    {
                        RibbonContextualTabGroup ctg = ribbonTabHeader.ContextualTabGroup;
                        if (ctg != null && DoubleUtil.GreaterThan(ctg.DesiredExtraPaddingPerTab, 0.0))
                        {
                            double desiredExtraPaddingPerTab = ctg.DesiredExtraPaddingPerTab;
                            double availableExtraWidth       = Math.Min(desiredExtraPaddingPerTab, availableExtraWidthPerTab);

                            Thickness newPadding = ribbonTabHeader.Padding;
                            newPadding.Left        += availableExtraWidth * 0.5;
                            newPadding.Right       += availableExtraWidth * 0.5;
                            ribbonTabHeader.Padding = newPadding;

                            // Remeasure with added padding
                            desiredSize.Width -= ribbonTabHeader.DesiredSize.Width;
                            ribbonTabHeader.Measure(new Size(Double.MaxValue, childConstraint.Height));
                            desiredSize.Width += ribbonTabHeader.DesiredSize.Width;
                        }
                    }
                }
            }

            // If the difference between desiredWidth and constraintWidth is less
            // than 1e-10 then assume that both are same. This avoids unnecessary
            // inequalities in extent and viewport resulting in spontaneous
            // flickering of scroll button.
            if (Math.Abs(desiredSize.Width - availableSize.Width) < _desiredWidthEpsilon)
            {
                desiredSize.Width = availableSize.Width;
            }

            SpaceAvailable = availableSize.Width - desiredSize.Width;
            // Update ContextualTabGroup.TabsDesiredWidth
            NotifyDesiredWidthChanged();

            // Update whether tooltips should be shown.
            UpdateToolTips(showRegularTabHeaderToolTips, showContextualTabHeaderToolTips);

            VerifyScrollData(availableSize.Width, desiredSize.Width);


            // Invalidate ContextualTabHeadersPanel
            if (Ribbon != null)
            {
                RibbonContextualTabGroupItemsControl groupHeaderItemsControl = Ribbon.ContextualTabGroupItemsControl;
                if (groupHeaderItemsControl != null && groupHeaderItemsControl.InternalItemsHost != null)
                {
                    groupHeaderItemsControl.InternalItemsHost.InvalidateMeasure();
                }
            }

            return(desiredSize);
        }
Пример #15
0
        /// <summary>
        /// Обработчик под тип входных данных OPTION_SERIES
        /// </summary>
        public IList <double> Execute(IOptionSeries optSer)
        {
            if (optSer == null)
            {
                return(Constants.EmptyListDouble);
            }

            ISecurity sec = optSer.UnderlyingAsset;
            int       len = sec.Bars.Count;

            if (len <= 0)
            {
                return(Constants.EmptyListDouble);
            }

            IOptionStrikePair[] pairs = optSer.GetStrikePairs().ToArray();
            if ((!Double.IsNaN(m_strikeStep)) && (m_strikeStep > Double.Epsilon))
            {
                // Выделяем страйки, которые нацело делятся на StrikeStep
                var tmp = (from p in pairs
                           let test = m_strikeStep * Math.Round(p.Strike / m_strikeStep)
                                      where DoubleUtil.AreClose(p.Strike, test)
                                      select p).ToArray();
                if (tmp.Length > 1)
                {
                    // Нормальная ситуация
                    pairs = tmp;
                }
                // [02-06-2016] PROD-2812 - Защита от ошибок при указании шага страйков
                // В противном случае буду показывать все страйки (уже лежат в pairs).
                // Это хотя бы позволит Пользователю продолжить работу.
            }
            if (pairs.Length < 2)
            {
                return(Constants.EmptyListDouble);
            }

            double[] res     = Context?.GetArray <double>(len) ?? new double[len];
            var      history = LocalHistory;
            double   prevK   = Double.NaN;

            for (int m = 0; m < len; m++)
            {
                DateTime now = sec.Bars[m].Date;

                double ck;
                if (history.TryGetValue(now, out ck))
                {
                    prevK  = ck;
                    res[m] = prevK;
                }
                else
                {
                    double futPx = sec.Bars[m].Close;

                    // 0. Валидация диапазона
                    IOptionStrikePair left  = pairs[0];
                    IOptionStrikePair right = pairs[pairs.Length - 1];
                    if ((futPx <= left.Strike + Double.Epsilon) || (right.Strike - Double.Epsilon <= futPx))
                    {
                        res[m] = Double.IsNaN(prevK) ? Constants.NaN : prevK;
                        continue;
                    }

                    // 1. Пробуем проверить середину серии в качестве кандидата на левую границу
                    int li = pairs.Length / 2;
                    if (pairs[li].Strike < futPx)
                    {
                        left = pairs[li];
                    }
                    else
                    {
                        li = 0;
                    }

                    // 2. Ищем правый страйк
                    double ratio = Double.NaN;
                    int    leftIndex = Int32.MinValue, rightIndex = Int32.MaxValue;
                    for (int j = li; j < pairs.Length - 1; j++)
                    {
                        if ((pairs[j].Strike - Double.Epsilon <= futPx) && (futPx < pairs[j + 1].Strike))
                        {
                            left  = pairs[j];
                            right = pairs[j + 1];

                            leftIndex  = Math.Max(0, j + m_shiftStrike);
                            leftIndex  = Math.Min(leftIndex, pairs.Length - 2);
                            rightIndex = Math.Max(1, j + 1 + m_shiftStrike);
                            rightIndex = Math.Min(rightIndex, pairs.Length - 1);

                            ratio = (futPx - left.Strike) / (right.Strike - left.Strike);
                            break;
                        }
                    }

                    if (ratio <= (1.0 - m_switchRatio))
                    {
                        prevK        = pairs[leftIndex].Strike; // left.Strike;
                        res[m]       = prevK;
                        history[now] = prevK;
                    }
                    else if (m_switchRatio <= ratio)
                    {
                        prevK        = pairs[rightIndex].Strike; // right.Strike;
                        res[m]       = prevK;
                        history[now] = prevK;
                    }
                    else
                    {
                        if (Double.IsNaN(prevK) || (prevK <= 0))
                        {
                            try
                            {
                                prevK = pairs[rightIndex].Strike; // right.Strike;
                            }
                            catch (IndexOutOfRangeException ioex)
                            {
                                string msg = String.Format(CultureInfo.InvariantCulture,
                                                           "{0} when trying to get StrikePair. rightIndex:{1}; pairs.Length:{2}; leftIndex:{3}; li:{4}; ratio:{5}; prevK:{6}; futPx:{7}; ticker:{8}",
                                                           ioex.GetType().FullName, rightIndex, pairs.Length, leftIndex, li, ratio, prevK, futPx, optSer.UnderlyingAsset.Symbol);
                                m_context.Log(msg, MessageType.Error, true);

                                // Здесь ПОКА оставляю выброс исключения, чтобы ситуация с самозакрытием окон агента воспроизводилась.
                                throw;
                            }
                            res[m]       = prevK;
                            history[now] = prevK;
                        }
                        else
                        {
                            res[m] = prevK;
                            // Надо ли здесь обновить history или это бессмысленно и расточительно???
                        }
                    }
                }

                //// "For some strange reason I didn't fill value at index m:" + m);
                //if (DoubleUtil.IsZero(res[m]))
                //    m_context.Log("[DEBUG:CentralStrike] For some strange reason I didn't fill value at index m:" + m, MessageType.Error, true);
            }

            double displayValue = FixedValue.ConvertToDisplayUnits(m_valueMode, res[len - 1]);

            m_displayPrice.Value = displayValue;

            return(res);
        }
Пример #16
0
#pragma warning restore SA1206 // Declaration keywords must follow order

        public override int Compare(double x, double y)
        {
            return(DoubleUtil.AreClose(x, y) ? 0 : x.CompareTo(y));
        }
Пример #17
0
        // ReSharper disable once UnusedMember.Global
        public IList <double> Execute(IOptionSeries optSer)
        {
            if (optSer == null)
            {
                return(Constants.EmptyListDouble);
            }

            // 1. Список страйков
            HashSet <string> serList = StrikeList;

            serList.Clear();

            IOptionStrikePair[] pairs;
            if (Double.IsNaN(m_strikeStep) || (m_strikeStep <= Double.Epsilon))
            {
                pairs = optSer.GetStrikePairs().ToArray();
            }
            else
            {
                // Выделяем страйки, которые нацело делятся на StrikeStep
                pairs = (from p in optSer.GetStrikePairs()
                         let test = m_strikeStep * Math.Round(p.Strike / m_strikeStep)
                                    where DoubleUtil.AreClose(p.Strike, test)
                                    select p).ToArray();

                // [2015-12-24] Если шаг страйков по ошибке задан совершенно неправильно,
                // то в коллекцию ставим все имеющиеся страйки.
                // Пользователь потом разберется
                if (pairs.Length <= 0)
                {
                    pairs = optSer.GetStrikePairs().ToArray();
                }
            }
            //if (pairs.Length < 2)
            //    return Constants.EmptyListDouble;

            foreach (IOptionStrikePair pair in pairs)
            {
                double k = pair.Strike;
                serList.Add(k.ToString(CultureInfo.InvariantCulture));
            }

            // 2. Локальный кеш страйков
            List <double> historyStrikes = LocalStrikeHistory;

            if (/* m_reset || */ m_context.Runtime.IsFixedBarsCount)
            {
                historyStrikes.Clear();
            }

            // Типа, кеширование?
            int len = Context.BarsCount;

            for (int j = historyStrikes.Count; j < len; j++)
            {
                double k;
                // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression
                if (Double.TryParse(m_strike, NumberStyles.Any, CultureInfo.InvariantCulture, out k))
                {
                    historyStrikes.Add(k);
                }
                else
                {
                    historyStrikes.Add(Constants.NaN);
                }
            }

            return(new ReadOnlyCollection <double>(historyStrikes));
        }
Пример #18
0
        /// <summary>
        /// Finds connecting points for a pair of stroke nodes
        /// </summary>
        /// <param name="beginNode">a node to connect</param>
        /// <param name="endNode">another node, next to beginNode</param>
        /// <returns>connecting quadrangle</returns>
        internal override Quad GetConnectingQuad(StrokeNodeData beginNode, StrokeNodeData endNode)
        {
            if (beginNode.IsEmpty || endNode.IsEmpty || DoubleUtil.AreClose(beginNode.Position, endNode.Position))
            {
                return(Quad.Empty);
            }

            // Get the vector between the node positions
            Vector spine = endNode.Position - beginNode.Position;

            if (_nodeShapeToCircle.IsIdentity == false)
            {
                spine = _nodeShapeToCircle.Transform(spine);
            }

            double beginRadius = _radius * beginNode.PressureFactor;
            double endRadius   = _radius * endNode.PressureFactor;

            // Get the vector and the distance between the node positions
            double distanceSquared = spine.LengthSquared;
            double delta           = endRadius - beginRadius;
            double deltaSquared    = DoubleUtil.IsZero(delta) ? 0 : (delta * delta);

            if (DoubleUtil.LessThanOrClose(distanceSquared, deltaSquared))
            {
                // One circle is contained within the other
                return(Quad.Empty);
            }

            // Thus, at this point, distance > 0, which avoids the DivideByZero error
            // Also, here, distanceSquared > deltaSquared
            // Thus, 0 <= rSin < 1
            // Get the components of the radius vectors
            double distance = Math.Sqrt(distanceSquared);

            spine /= distance;

            Vector rad = spine;

            // Turn left
            double temp = rad.Y;

            rad.Y = -rad.X;
            rad.X = temp;

            Vector vectorToLeftTangent, vectorToRightTangent;
            double rSinSquared = deltaSquared / distanceSquared;

            if (DoubleUtil.IsZero(rSinSquared))
            {
                vectorToLeftTangent  = rad;
                vectorToRightTangent = -rad;
            }
            else
            {
                rad   *= Math.Sqrt(1 - rSinSquared);
                spine *= Math.Sqrt(rSinSquared);
                if (beginNode.PressureFactor < endNode.PressureFactor)
                {
                    spine = -spine;
                }

                vectorToLeftTangent  = spine + rad;
                vectorToRightTangent = spine - rad;
            }

            // Get the common tangent points

            if (_circleToNodeShape.IsIdentity == false)
            {
                vectorToLeftTangent  = _circleToNodeShape.Transform(vectorToLeftTangent);
                vectorToRightTangent = _circleToNodeShape.Transform(vectorToRightTangent);
            }

            return(new Quad(beginNode.Position + (vectorToLeftTangent * beginRadius),
                            endNode.Position + (vectorToLeftTangent * endRadius),
                            endNode.Position + (vectorToRightTangent * endRadius),
                            beginNode.Position + (vectorToRightTangent * beginRadius)));
        }
        /// <summary>
        ///     Parses a DataGridLength from a string given the CultureInfo.
        /// </summary>
        /// <param name="s">String to parse from.</param>
        /// <param name="cultureInfo">Culture Info.</param>
        /// <returns>Newly created DataGridLength instance.</returns>
        /// <remarks>
        /// Formats:
        /// "[value][unit]"
        ///     [value] is a double
        ///     [unit] is a string in DataGridLength._unitTypes connected to a DataGridLengthUnitType
        /// "[value]"
        ///     As above, but the DataGridLengthUnitType is assumed to be DataGridLengthUnitType.Pixel
        /// "[unit]"
        ///     As above, but the value is assumed to be 1.0
        ///     This is only acceptable for a subset of DataGridLengthUnitType: Auto
        /// </remarks>
        private static DataGridLength ConvertFromString(string s, CultureInfo cultureInfo)
        {
            string goodString = s.Trim().ToLowerInvariant();

            // Check if the string matches any of the descriptive unit types.
            // In these cases, there is no need to parse a value.
            for (int i = 0; i < NumDescriptiveUnits; i++)
            {
                string unitString = _unitStrings[i];
                if (goodString == unitString)
                {
                    return(new DataGridLength(1.0, (DataGridLengthUnitType)i));
                }
            }

            double value = 0.0;
            DataGridLengthUnitType unit = DataGridLengthUnitType.Pixel;
            int    strLen     = goodString.Length;
            int    strLenUnit = 0;
            double unitFactor = 1.0;

            // Check if the string contains a non-descriptive unit at the end.
            int numUnitStrings = _unitStrings.Length;

            for (int i = NumDescriptiveUnits; i < numUnitStrings; i++)
            {
                string unitString = _unitStrings[i];

                // Note: This is NOT a culture specific comparison.
                // This is by design: we want the same unit string table to work across all cultures.
                if (goodString.EndsWith(unitString, StringComparison.Ordinal))
                {
                    strLenUnit = unitString.Length;
                    unit       = (DataGridLengthUnitType)i;
                    break;
                }
            }

            // Couldn't match a standard unit type, try a non-standard unit type.
            if (strLenUnit == 0)
            {
                numUnitStrings = _nonStandardUnitStrings.Length;
                for (int i = 0; i < numUnitStrings; i++)
                {
                    string unitString = _nonStandardUnitStrings[i];

                    // Note: This is NOT a culture specific comparison.
                    // This is by design: we want the same unit string table to work across all cultures.
                    if (goodString.EndsWith(unitString, StringComparison.Ordinal))
                    {
                        strLenUnit = unitString.Length;
                        unitFactor = _pixelUnitFactors[i];
                        break;
                    }
                }
            }

            // Check if there is a numerical value to parse
            if (strLen == strLenUnit)
            {
                // There is no numerical value to parse
                if (unit == DataGridLengthUnitType.Star)
                {
                    // Star's value defaults to 1. Anyone else would be 0.
                    value = 1.0;
                }
            }
            else
            {
                // Parse a numerical value
                Debug.Assert(
                    (unit == DataGridLengthUnitType.Pixel) || DoubleUtil.AreClose(unitFactor, 1.0),
                    "unitFactor should not be other than 1.0 unless the unit type is Pixel.");

                string valueString = goodString.Substring(0, strLen - strLenUnit);
                value = Convert.ToDouble(valueString, cultureInfo) * unitFactor;
            }

            return(new DataGridLength(value, unit));
        }
Пример #20
0
        // Updates Width and other layout properties in the Visual tree from RibbonControl to InRibbonGallery wherever needed
        // when attains In Ribbon mode.
        private void UpdateInRibbonGalleryModeProperties()
        {
            if (IsInInRibbonMode && ControlSizeDefinition != null)
            {
                _scrollButtonsBorderFactor = 0;
                if (_scrollButtonsBorder != null)
                {
                    if (DoubleUtil.AreClose(_scrollButtonsBorder.ActualWidth, 0))
                    {
                        _scrollButtonsBorderFactor = 0;
                    }
                    else
                    {
                        _scrollButtonsBorderFactor = Math.Max(_scrollButtonsBorder.ActualWidth, 0);
                    }
                }

                if (_contentPresenter != null)
                {
                    // Converts if the Width property values specified in terms of items and assigns it to
                    // InRibbonGallery Content Template parts from ControlSizeDefinition
                    double minWidth = GetPixelValueFromRibbonControlLength(ControlSizeDefinition.MinWidth);
                    if (!DoubleUtil.AreClose(minWidth, _contentPresenter.MinWidth))
                    {
                        // TODO: make sure we are robust against retemplating
                        //_contentPresenter.MinWidth = minWidth + _contentPresenter.Margin.Left + _contentPresenter.Margin.Right;
                        _contentPresenter.MinWidth = minWidth;
                    }

                    double maxWidth = GetPixelValueFromRibbonControlLength(ControlSizeDefinition.MaxWidth);
                    if (!DoubleUtil.AreClose(maxWidth, _contentPresenter.MaxWidth))
                    {
                        // TODO: make sure we are robust against retemplating
                        //_contentPresenter.MaxWidth = maxWidth + _contentPresenter.Margin.Left + _contentPresenter.Margin.Right;
                        _contentPresenter.MaxWidth = maxWidth;
                    }

                    double width = GetPixelValueFromRibbonControlLength(ControlSizeDefinition.Width);
                    if (!DoubleUtil.AreClose(width, _contentPresenter.Width) && !(double.IsNaN(width) && double.IsNaN(_contentPresenter.Width)))
                    {
                        _contentPresenter.Width = width;
                    }

                    if (_ribbonControl != null)
                    {
                        // Ribbon Control Length is bound to Min/Max values of ControlSizeDefinition by default
                        // but in case on InRibbonGallery it needs to be taken care specifically as InRibbonGallery
                        // supports Item unit types as well.
                        maxWidth = _contentPresenter.MaxWidth + _contentPresenter.Margin.Left + _contentPresenter.Margin.Right + _scrollButtonsBorderFactor + WidthStylePadding;
                        if (!DoubleUtil.AreClose(maxWidth, _ribbonControl.MaxWidth))
                        {
                            _ribbonControl.MaxWidth = maxWidth;
                        }

                        minWidth = _contentPresenter.MinWidth + _contentPresenter.Margin.Left + _contentPresenter.Margin.Right + _scrollButtonsBorderFactor + WidthStylePadding;
                        if (!DoubleUtil.AreClose(minWidth, _ribbonControl.MinWidth))
                        {
                            _ribbonControl.MinWidth = minWidth;
                        }

                        // RibbonControl's Horizontal alignment by default is Stretch but InRibbonGallery has
                        // specific requirement which RibbonControl understands.
                        if (this.HorizontalAlignment != HorizontalAlignment.Left)
                        {
                            this.HorizontalAlignment = HorizontalAlignment.Left;
                        }
                    }
                }
            }
            else
            {
                if (_ribbonControl != null)
                {
                    _ribbonControl.ClearValue(FrameworkElement.MaxWidthProperty);
                    _ribbonControl.ClearValue(FrameworkElement.MinWidthProperty);
                    _ribbonControl.ClearValue(FrameworkElement.HorizontalAlignmentProperty);
                }
            }
        }
        override protected bool IsOffscreenCore()
        {
            if (!Owner.IsVisible)
            {
                return(true);
            }

            Rect boundingRect = DataGridAutomationPeer.CalculateVisibleBoundingRect(this.Owner);

            return(DoubleUtil.AreClose(boundingRect, Rect.Empty) || DoubleUtil.AreClose(boundingRect.Height, 0.0) || DoubleUtil.AreClose(boundingRect.Width, 0.0));
        }
        /// <summary>
        ///   Parses a RibbonControlLength from a string given the CultureInfo.
        /// </summary>
        internal static RibbonControlLength FromString(string s, CultureInfo cultureInfo)
        {
            string goodString = s.Trim().ToLowerInvariant();

            double value = 0.0;
            RibbonControlLengthUnitType unit = RibbonControlLengthUnitType.Pixel;

            int    i;
            int    strLen     = goodString.Length;
            int    strLenUnit = 0;
            double unitFactor = 1.0;

            //  this is where we would handle trailing whitespace on the input string.
            //  peel [unit] off the end of the string
            i = 0;

            if (goodString == _unitStrings[i])
            {
                strLenUnit = _unitStrings[i].Length;
                unit       = (RibbonControlLengthUnitType)i;
            }
            else
            {
                for (i = 1; i < _unitStrings.Length; ++i)
                {
                    //  Note: this is NOT a culture specific comparison.
                    //  this is by design: we want the same unit string table to work across all cultures.
                    if (goodString.EndsWith(_unitStrings[i], StringComparison.Ordinal))
                    {
                        strLenUnit = _unitStrings[i].Length;
                        unit       = (RibbonControlLengthUnitType)i;
                        break;
                    }
                }
            }

            //  we couldn't match a real unit from RibbonControlLengthUnitTypes.
            //  try again with a converter-only unit (a pixel equivalent).
            if (i >= _unitStrings.Length)
            {
                for (i = 0; i < _pixelUnitStrings.Length; ++i)
                {
                    //  Note: this is NOT a culture specific comparison.
                    //  this is by design: we want the same unit string table to work across all cultures.
                    if (goodString.EndsWith(_pixelUnitStrings[i], StringComparison.Ordinal))
                    {
                        strLenUnit = _pixelUnitStrings[i].Length;
                        unitFactor = _pixelUnitFactors[i];
                        break;
                    }
                }
            }

            //  this is where we would handle leading whitespace on the input string.
            //  this is also where we would handle whitespace between [value] and [unit].
            //  check if we don't have a [value].  This is acceptable for certain UnitTypes.
            if (strLen == strLenUnit && (unit == RibbonControlLengthUnitType.Auto || unit == RibbonControlLengthUnitType.Star))
            {
                value = 1;
            }
            //  we have a value to parse.
            else
            {
                Debug.Assert(unit == RibbonControlLengthUnitType.Pixel || unit == RibbonControlLengthUnitType.Item ||
                             DoubleUtil.AreClose(unitFactor, 1.0));

                ReadOnlySpan <char> valueString = goodString.AsSpan(0, strLen - strLenUnit);
                value = double.Parse(valueString, provider: cultureInfo) * unitFactor;
            }

            return(new RibbonControlLength(value, unit));
        }
Пример #23
0
        /// <summary>
        /// Метод под флаг TemplateTypes.SECURITY, чтобы подключаться к источнику-БА
        /// </summary>
        public IList <double> Execute(ISecurity sec)
        {
            if (sec == null)
            {
                return(Constants.EmptyListDouble);
            }

            Dictionary <DateTime, double> hvSigmas;

            #region Get cache
            int    barLengthInSeconds = (int)sec.IntervalInstance.ToSeconds();
            string cashKey            = GetGlobalCashKey(sec.Symbol, false, m_useAllData, barLengthInSeconds, m_annualizingMultiplier, m_period);
            if (UseGlobalCache)
            {
                object globalObj = Context.LoadGlobalObject(cashKey, true);
                hvSigmas = globalObj as Dictionary <DateTime, double>;
                // PROD-3970 - 'Важный' объект
                if (hvSigmas == null)
                {
                    var container = globalObj as NotClearableContainer;
                    if ((container != null) && (container.Content != null))
                    {
                        hvSigmas = container.Content as Dictionary <DateTime, double>;
                    }
                }
                if (hvSigmas == null)
                {
                    hvSigmas = new Dictionary <DateTime, double>();
                    var container = new NotClearableContainer(hvSigmas);
                    Context.StoreGlobalObject(cashKey, container, true);
                }
            }
            else
            {
                object locObj = Context.LoadObject(cashKey);
                hvSigmas = locObj as Dictionary <DateTime, double>;
                // PROD-3970 - 'Важный' объект
                if (hvSigmas == null)
                {
                    var container = locObj as NotClearableContainer;
                    if ((container != null) && (container.Content != null))
                    {
                        hvSigmas = container.Content as Dictionary <DateTime, double>;
                    }
                }
                if (hvSigmas == null)
                {
                    hvSigmas = new Dictionary <DateTime, double>();
                    var container = new NotClearableContainer(hvSigmas);
                    Context.StoreObject(cashKey, container);
                }
            }
            #endregion Get cache

            List <double> historySigmas = LocalHistory;

            if (m_reset || m_context.Runtime.IsFixedBarsCount)
            {
                historySigmas.Clear();
            }

            int len = Context.BarsCount;
            // Локальный ключ можно всегда формировать вместе с периодом!
            string logsLocObjKey = VariableId + "_logs_" + m_period;
            object logsLocObj    = m_context.LoadObject(logsLocObjKey);
            LinkedList <KeyValuePair <DateTime, double> > logs = logsLocObj as LinkedList <KeyValuePair <DateTime, double> >;
            #region Get cache
            // PROD-3970 - 'Важный' объект
            if (logs == null)
            {
                var container = logsLocObj as NotClearableContainer;
                if ((container != null) && (container.Content != null))
                {
                    logs = container.Content as LinkedList <KeyValuePair <DateTime, double> >;
                }
            }
            if (logs == null)
            {
                logs = new LinkedList <KeyValuePair <DateTime, double> >();
                var container = new NotClearableContainer(logs);
                m_context.StoreObject(logsLocObjKey, container);
            }
            #endregion Get cache

            if (m_reset || m_context.Runtime.IsFixedBarsCount)
            {
                logs.Clear();
            }

            if (len <= 0)
            {
                return(historySigmas);
            }

            // Типа, кеширование?
            for (int j = historySigmas.Count; j < len; j++)
            {
                IDataBar bar;
                try
                {
                    // Наблюдал на реале странную картину (ВО ВРЕМЯ КЛИРИНГА!):
                    // Context.BarsCount == 3843 && sec.Bars.Count == 3842
                    bar = sec.Bars[j];
                    // если бар технический (то есть имеет нулевой объём), пропускаем его
                    // 2017-04-26 - На эксанте при запросе истории все бары имеют нулевой объём, но при этом большинство из них являются нормальными:
                    //              имеют ненулевой размах и осмысленные значения открытия/закрытия
                    if ((bar.Volume <= Double.Epsilon) && (DoubleUtil.AreClose(bar.High, bar.Low)))
                    {
                        // пишу NaN в такой ситуации
                        historySigmas.Add(Constants.NaN);
                        continue;
                    }
                }
                catch (ArgumentOutOfRangeException)
                {
                    // Перехватываю aorEx и пишу NaN в такой ситуации
                    historySigmas.Add(Constants.NaN);
                    continue;
                }

                DateTime t  = bar.Date;
                double   v  = bar.Close;
                double   ln = Math.Log(v);

                Contract.Assert(logs != null, "Каким образом переменная logs оказалась null?");
                logs.AddLast(new KeyValuePair <DateTime, double>(t, ln));

                double hv;
                if (TryEstimateHv(
                        logs, m_period, barLengthInSeconds, m_annualizingMultiplier,
                        m_useAllData, out hv))
                {
                    double vol = hv;
                    historySigmas.Add(vol);

                    lock (hvSigmas)
                    {
                        hvSigmas[t] = vol;
                    }
                }
                else
                {
                    historySigmas.Add(Constants.NaN);
                }
            }

            // Попытку записи в глобальный кеш делаю только в самом конце всех вычислений
            // для экономии времени на сериализацию и запись
            lock (hvSigmas)
            {
                if (sec.Bars.Count > len - 1)
                {
                    // Наблюдал на реале странную картину (ВО ВРЕМЯ КЛИРИНГА!):
                    // Context.BarsCount == 3760 && sec.Bars.Count == 3759
                    bool success = IvOnF.TryWrite(m_context, UseGlobalCache, AllowGlobalReadWrite, GlobalSavePeriod,
                                                  cashKey, hvSigmas, sec.Bars[len - 1].Date, historySigmas[historySigmas.Count - 1]);
                }

                return(new ReadOnlyCollection <double>(historySigmas));
            }
        }
Пример #24
0
        // ------------------------------------------------------------------
        // Set information about column rules that are necessary for rendering
        // process. Draw column rules if necessary.
        //
        //      arrayColumnDesc - column description including rectangle coordinates, etc
        //      columnVStart - vertical start coordinate of column rule
        //      columnHeight - height of column rule
        //      columnProperties - column properties.
        // ------------------------------------------------------------------
        internal void DrawColumnRules(ref PTS.FSTRACKDESCRIPTION[] arrayColumnDesc, double columnVStart, double columnHeight, ColumnPropertiesGroup columnProperties)
        {
            // Compute column rules data first.
            Point[] rulePositions = null;
            double  ruleWidth     = columnProperties.ColumnRuleWidth;

            if (arrayColumnDesc.Length > 1)
            {
                if (ruleWidth > 0)
                {
                    int gapWidth = (arrayColumnDesc[1].fsrc.u - (arrayColumnDesc[0].fsrc.u + arrayColumnDesc[0].fsrc.du)) / 2;
                    rulePositions = new Point[(arrayColumnDesc.Length - 1) * 2];
                    for (int index = 1; index < arrayColumnDesc.Length; index++)
                    {
                        double u  = TextDpi.FromTextDpi(arrayColumnDesc[index].fsrc.u - gapWidth);
                        double v  = columnVStart;
                        double dv = columnHeight;
                        rulePositions[(index - 1) * 2].X     = u;
                        rulePositions[(index - 1) * 2].Y     = v;
                        rulePositions[(index - 1) * 2 + 1].X = u;
                        rulePositions[(index - 1) * 2 + 1].Y = v + dv;
                    }
                }
            }

            // Check if update of the visual render data is needed.
            bool needsUpdate = _ruleWidth != ruleWidth;

            if (!needsUpdate && _rulePositions != rulePositions)
            {
                int prevSize = _rulePositions == null ? 0 : _rulePositions.Length;
                int newSize  = rulePositions == null ? 0 : rulePositions.Length;
                if (prevSize == newSize)
                {
                    for (int index = 0; index < rulePositions.Length; index++)
                    {
                        if (!DoubleUtil.AreClose(rulePositions[index].X, _rulePositions[index].X) ||
                            !DoubleUtil.AreClose(rulePositions[index].Y, _rulePositions[index].Y))
                        {
                            needsUpdate = true;
                            break;
                        }
                    }
                }
                else
                {
                    needsUpdate = true;
                }
            }

            // Draw column rules if necessary
            if (needsUpdate)
            {
                _ruleWidth     = ruleWidth;
                _rulePositions = rulePositions;

                // Open DrawingContext and draw background.
                // If background is not set, Open will clear the render data, but it
                // will preserve visual children.
                using (DrawingContext dc = RenderOpen())
                {
                    if (rulePositions != null)
                    {
                        // We do not want to cause the user's Brush to become frozen when we
                        // freeze pen below, therefore we make our own copy of the Brush if
                        // it is not already frozen.
                        Brush columnRuleBrush = (Brush)FreezableOperations.GetAsFrozenIfPossible(columnProperties.ColumnRuleBrush);

                        Pen pen = new Pen(columnRuleBrush, ruleWidth);

                        // Freeze the pen if possible.  Doing this avoids the overhead of
                        // maintaining changed handlers.
                        if (pen.CanFreeze)
                        {
                            pen.Freeze();
                        }

                        for (int index = 0; index < rulePositions.Length; index += 2)
                        {
                            dc.DrawLine(pen, rulePositions[index], rulePositions[index + 1]);
                        }
                    }
                }
            }
        }
Пример #25
0
        /// <summary>TBS</summary>
        public Point[] AddPoints(List <Point> points)
        {
            if (null == points)
            {
                throw new ArgumentNullException("points");
            }

            // Lazy initialization.
            EnsureReady();

            List <Point> justAdded = new List <Point>();
            int          count     = points.Count;

            for (int i = 0; i < count; i++)
            {
                Point point = points[i];

                if (0 == _count)
                {
                    AddLassoPoint(point);

                    justAdded.Add(point);
                    _lasso.Add(point);
                    _boundingBox.Union(point);

                    _firstLassoPoint = point;
                    _lastLassoPoint  = point;
                    _count++;
                }
                else
                {
                    Vector last2next       = point - _lastLassoPoint;
                    double distanceSquared = last2next.LengthSquared;

                    // Avoid using Sqrt when the distance is equal to the step.
                    if (DoubleUtil.AreClose(MinDistanceSquared, distanceSquared))
                    {
                        AddLassoPoint(point);
                        justAdded.Add(point);
                        _lasso.Add(point);
                        _boundingBox.Union(point);

                        _lastLassoPoint = point;
                        _count++;
                    }
                    else if (MinDistanceSquared < distanceSquared)
                    {
                        double step = Math.Sqrt(MinDistanceSquared / distanceSquared);
                        Point  last = _lastLassoPoint;
                        for (double findex = step; findex < 1.0f; findex += step)
                        {
                            Point lassoPoint = last + (last2next * findex);
                            AddLassoPoint(lassoPoint);
                            justAdded.Add(lassoPoint);
                            _lasso.Add(lassoPoint);
                            _boundingBox.Union(lassoPoint);

                            _lastLassoPoint = lassoPoint;
                            _count++;
                        }
                    }
                }
            }

            // still working on perf here.
            // Draw a line between the last point and the first one.
            //if (_count > 1)
            //{
            //    DrawingContext dc = _containerVisual.RenderOpen();
            //    dc.DrawLine(_linePen, _firstLassoPoint, _lastLassoPoint);
            //    dc.Close();
            //}

            return(justAdded.ToArray());
        }
Пример #26
0
        /// <summary>
        /// Метод под флаг TemplateTypes.INTERACTIVESPLINE
        /// </summary>
        public InteractiveSeries Execute(InteractiveSeries smile, IOptionSeries optSer, double scaleMult, int barNum)
        {
            if ((smile == null) || (optSer == null))
            {
                return(Constants.EmptySeries);
            }

            int barsCount = m_context.BarsCount;

            if (!m_context.IsLastBarUsed)
            {
                barsCount--;
            }
            if (barNum < barsCount - 1)
            {
                return(Constants.EmptySeries);
            }

            SmileInfo oldInfo = smile.GetTag <SmileInfo>();

            if ((oldInfo == null) || (oldInfo.ContinuousFunction == null))
            {
                return(Constants.EmptySeries);
            }

            double futPx = oldInfo.F;
            double dT    = oldInfo.dT;

            if (m_executeCommand)
            {
                string msg = String.Format("[{0}.StartButton] Strike: {1}", GetType().Name, m_strike);
                m_context.Log(msg, MessageType.Info, false);
            }

            #region 1. Список страйков
            HashSet <string> serList = StrikeList;
            serList.Clear();

            IOptionStrikePair[] pairs;
            if (Double.IsNaN(m_strikeStep) || (m_strikeStep <= Double.Epsilon))
            {
                pairs = optSer.GetStrikePairs().ToArray();
            }
            else
            {
                // Выделяем страйки, которые нацело делятся на StrikeStep
                pairs = (from p in optSer.GetStrikePairs()
                         let test = m_strikeStep * Math.Round(p.Strike / m_strikeStep)
                                    where DoubleUtil.AreClose(p.Strike, test)
                                    select p).ToArray();

                // [2015-12-24] Если шаг страйков по ошибке задан совершенно неправильно,
                // то в коллекцию ставим все имеющиеся страйки.
                // Пользователь потом разберется
                if (pairs.Length <= 0)
                {
                    pairs = optSer.GetStrikePairs().ToArray();
                }
            }
            //if (pairs.Length < 2)
            //    return Constants.EmptyListDouble;

            foreach (IOptionStrikePair pair in pairs)
            {
                double k = pair.Strike;
                serList.Add(k.ToString(StrikeFormat, CultureInfo.InvariantCulture));
            }
            #endregion 1. Список страйков

            InteractiveSeries        res           = Constants.EmptySeries;
            List <InteractiveObject> controlPoints = new List <InteractiveObject>();

            #region 2. Формируем улыбку просто для отображения текущего положения потенциальной котировки
            // При нулевом рабочем объёме не утруждаемся рисованием лишних линий
            if (!DoubleUtil.IsZero(m_qty))
            {
                for (int j = 0; j < pairs.Length; j++)
                {
                    var    pair  = pairs[j];
                    double sigma = oldInfo.ContinuousFunction.Value(pair.Strike) + m_shiftIv;
                    if (!DoubleUtil.IsPositive(sigma))
                    {
                        //string msg = String.Format("[DEBUG:{0}] Invalid sigma:{1} for strike:{2}", GetType().Name, sigma, nodeInfo.Strike);
                        //m_context.Log(msg, MessageType.Warning, true);
                        continue;
                    }

                    //bool isCall = (futPx <= pair.Strike);
                    bool isCall;
                    if (m_optionType == StrikeType.Call)
                    {
                        isCall = true;
                    }
                    else if (m_optionType == StrikeType.Put)
                    {
                        isCall = false;
                    }
                    else
                    {
                        isCall = (futPx <= pair.Strike);
                    }

                    StrikeType optionType = isCall ? StrikeType.Call : StrikeType.Put;
                    Contract.Assert(pair.Tick < 1, $"#1 На тестовом контуре Дерибит присылает неправильный шаг цены! Tick:{pair.Tick}; Decimals:{pair.Put.Security.Decimals}");
                    double theorOptPxDollars = FinMath.GetOptionPrice(futPx, pair.Strike, dT, sigma, oldInfo.RiskFreeRate, isCall);
                    // Сразу(!!!) переводим котировку из баксов в битки
                    double theorOptPxBitcoins = theorOptPxDollars / scaleMult;

                    // Сдвигаем цену в долларах (с учетом ш.ц. в баксах)
                    theorOptPxDollars += m_shiftPriceStep * pair.Tick * scaleMult;
                    theorOptPxDollars  = Math.Round(theorOptPxDollars / (pair.Tick * scaleMult)) * (pair.Tick * scaleMult);

                    // Сдвигаем цену в биткойнах (с учетом ш.ц. в битках)
                    theorOptPxBitcoins += m_shiftPriceStep * pair.Tick;
                    theorOptPxBitcoins  = Math.Round(theorOptPxBitcoins / pair.Tick) * pair.Tick;
                    if ((!DoubleUtil.IsPositive(theorOptPxBitcoins)) || (!DoubleUtil.IsPositive(theorOptPxDollars)))
                    {
                        //string msg = String.Format("[DEBUG:{0}] Invalid theorOptPx:{1} for strike:{2}", GetType().Name, theorOptPx, nodeInfo.Strike);
                        //m_context.Log(msg, MessageType.Warning, true);
                        continue;
                    }

                    // Пересчитываем сигму обратно, ЕСЛИ мы применили сдвиг цены в абсолютном выражении
                    if (m_shiftPriceStep != 0)
                    {
                        // Обратный пересчет в волатильность
                        sigma = FinMath.GetOptionSigma(futPx, pair.Strike, dT, theorOptPxDollars, oldInfo.RiskFreeRate, isCall);
                        if (!DoubleUtil.IsPositive(sigma))
                        {
                            //string msg = String.Format("[DEBUG:{0}] Invalid sigma:{1} for strike:{2}", GetType().Name, sigma, nodeInfo.Strike);
                            //m_context.Log(msg, MessageType.Warning, true);
                            continue;
                        }
                    }

                    // ReSharper disable once UseObjectOrCollectionInitializer
                    SmileNodeInfo nodeInfo = new SmileNodeInfo();
                    var           secDesc  = isCall ? pair.CallFinInfo.Security : pair.PutFinInfo.Security;
                    nodeInfo.F            = oldInfo.F;
                    nodeInfo.dT           = oldInfo.dT;
                    nodeInfo.RiskFreeRate = oldInfo.RiskFreeRate;
                    nodeInfo.Strike       = pair.Strike;
                    nodeInfo.Sigma        = sigma;
                    nodeInfo.OptPx        = theorOptPxBitcoins;
                    nodeInfo.OptionType   = isCall ? StrikeType.Call : StrikeType.Put;
                    nodeInfo.Pair         = pair;

                    nodeInfo.Symbol   = secDesc.Name;
                    nodeInfo.DSName   = secDesc.DSName;
                    nodeInfo.Expired  = secDesc.Expired;
                    nodeInfo.FullName = secDesc.FullName;

                    // ReSharper disable once UseObjectOrCollectionInitializer
                    InteractivePointActive tmp = new InteractivePointActive();

                    tmp.IsActive     = true;
                    tmp.ValueX       = pair.Strike;
                    tmp.ValueY       = sigma;
                    tmp.DragableMode = DragableMode.Yonly;
                    tmp.Tooltip      = String.Format(CultureInfo.InvariantCulture,
                                                     " F: {0}\r\n K: {1}; IV: {2:P2}\r\n {3} px {4}",
                                                     futPx, pair.Strike, sigma, optionType, theorOptPxBitcoins);

                    tmp.Tag = nodeInfo;

                    //tmp.Color = Colors.White;
                    if (m_qty > 0)
                    {
                        tmp.Geometry = Geometries.Triangle;
                    }
                    else if (m_qty < 0)
                    {
                        tmp.Geometry = Geometries.TriangleDown;
                    }
                    else
                    {
                        tmp.Geometry = Geometries.None;
                    }

                    InteractiveObject obj = new InteractiveObject();
                    obj.Anchor = tmp;

                    controlPoints.Add(obj);
                }

                // ReSharper disable once UseObjectOrCollectionInitializer
                res = new InteractiveSeries(); // Здесь так надо -- мы делаем новую улыбку
                res.ControlPoints = new ReadOnlyCollection <InteractiveObject>(controlPoints);

                // ReSharper disable once UseObjectOrCollectionInitializer
                SmileInfo sInfo = new SmileInfo();
                sInfo.F            = futPx;
                sInfo.dT           = dT;
                sInfo.Expiry       = oldInfo.Expiry;
                sInfo.ScriptTime   = oldInfo.ScriptTime;
                sInfo.RiskFreeRate = oldInfo.RiskFreeRate;
                sInfo.BaseTicker   = oldInfo.BaseTicker;

                res.Tag = sInfo;

                if (controlPoints.Count > 0)
                {
                    res.ClickEvent -= InteractiveSplineOnQuoteIvEvent;
                    res.ClickEvent += InteractiveSplineOnQuoteIvEvent;

                    m_clickableSeries = res;
                }
            }
            #endregion 2. Формируем улыбку просто для отображения текущего положения потенциальной котировки

            PositionsManager posMan = PositionsManager.GetManager(m_context);
            if (m_cancelAllLong)
            {
                posMan.DropAllLongIvTargets(m_context);
            }
            if (m_cancelAllShort)
            {
                posMan.DropAllShortIvTargets(m_context);
            }

            #region 4. Котирование
            {
                var longTargets  = posMan.GetIvTargets(true);
                var shortTargets = posMan.GetIvTargets(false);
                var ivTargets    = longTargets.Union(shortTargets).ToList();
                for (int j = 0; j < ivTargets.Count; j++)
                {
                    var ivTarget = ivTargets[j];

                    // PROD-6102 - Требуется точное совпадение опционной серии
                    if (optSer.ExpirationDate.Date != ivTarget.SecInfo.Expiry.Date)
                    {
                        // Вывести предупреждение???
                        continue;
                    }

                    IOptionStrikePair pair;
                    double            k = ivTarget.SecInfo.Strike;
                    if (!optSer.TryGetStrikePair(k, out pair))
                    {
                        // Вывести предупреждение???
                        continue;
                    }

                    double      sigma;
                    QuoteIvMode quoteMode = ivTarget.QuoteMode;
                    if (quoteMode == QuoteIvMode.Absolute)
                    {
                        sigma = ivTarget.EntryIv;
                    }
                    else
                    {
                        sigma = oldInfo.ContinuousFunction.Value(k) + ivTarget.EntryIv;
                        if (!DoubleUtil.IsPositive(sigma))
                        {
                            //string msg = String.Format("[DEBUG:{0}] Invalid sigma:{1} for strike:{2}", GetType().Name, sigma, nodeInfo.Strike);
                            //m_context.Log(msg, MessageType.Warning, true);
                            continue;
                        }
                    }

                    //bool isCall = (futPx <= pair.Strike);
                    // Определяю тип опциона на основании информации в Задаче
                    StrikeType taskOptionType = StrikeType.Any;
                    if (ivTarget.SecInfo.StrikeType.HasValue)
                    {
                        taskOptionType = ivTarget.SecInfo.StrikeType.Value;
                    }

                    bool isCall;
                    if (taskOptionType == StrikeType.Call)
                    {
                        isCall = true;
                    }
                    else if (taskOptionType == StrikeType.Put)
                    {
                        isCall = false;
                    }
                    else
                    {
                        isCall = (futPx <= pair.Strike); // Это аварийная ситуация?
                    }
                    StrikeType optionType = isCall ? StrikeType.Call : StrikeType.Put;
                    Contract.Assert(pair.Tick < 1, $"#3 На тестовом контуре Дерибит присылает неправильный шаг цены! Tick:{pair.Tick}; Decimals:{pair.Put.Security.Decimals}");
                    double theorOptPxDollars = FinMath.GetOptionPrice(futPx, pair.Strike, dT, sigma, oldInfo.RiskFreeRate, isCall);
                    // Сразу(!!!) переводим котировку из баксов в битки
                    double theorOptPxBitcoins = theorOptPxDollars / scaleMult;

                    // Сдвигаем цену в долларах (с учетом ш.ц. в баксах)
                    theorOptPxDollars += ivTarget.EntryShiftPrice * pair.Tick * scaleMult;
                    theorOptPxDollars  = Math.Round(theorOptPxDollars / (pair.Tick * scaleMult)) * (pair.Tick * scaleMult);

                    // Сдвигаем цену в биткойнах (с учетом ш.ц. в битках)
                    theorOptPxBitcoins += ivTarget.EntryShiftPrice * pair.Tick;
                    theorOptPxBitcoins  = Math.Round(theorOptPxBitcoins / pair.Tick) * pair.Tick;
                    if ((!DoubleUtil.IsPositive(theorOptPxBitcoins)) || (!DoubleUtil.IsPositive(theorOptPxDollars)))
                    {
                        //string msg = String.Format("[DEBUG:{0}] Invalid theorOptPx:{1} for strike:{2}", GetType().Name, theorOptPx, nodeInfo.Strike);
                        //m_context.Log(msg, MessageType.Warning, true);
                        continue;
                    }

                    IOptionStrike optStrike = isCall ? pair.Call : pair.Put;
                    ISecurity     sec       = optStrike.Security;
                    double        totalQty  = posMan.GetTotalQty(sec, m_context.BarsCount, TotalProfitAlgo.AllPositions, ivTarget.IsLong);
                    // Поскольку котирование страйка по волатильности -- это вопрос набора нужного количества СТРЕДДЛОВ,
                    // то учитывать надо суммарный объём опционов как в колах, так и в путах.
                    // НО ЗАДАЧУ-ТО Я СТАВЛЮ ДЛЯ КОНКРЕТНОГО ИНСТРУМЕНТА!
                    // Как быть?
                    //double totalQty = posMan.GetTotalQty(pair.Put.Security, m_context.BarsCount, TotalProfitAlgo.AllPositions, ivTarget.IsLong);
                    //totalQty += posMan.GetTotalQty(pair.Call.Security, m_context.BarsCount, TotalProfitAlgo.AllPositions, ivTarget.IsLong);
                    double targetQty = Math.Abs(ivTarget.TargetShares) - totalQty;
                    // Если имеется дробный LotTick (как в Дерибит к примеру), то надо предварительно округлить
                    targetQty = sec.RoundShares(targetQty);
                    if (targetQty > 0)
                    {
                        string note = String.Format(CultureInfo.InvariantCulture,
                                                    "{0}; ActQty:{1}; Px:{2}; IV:{3:P2}",
                                                    ivTarget.EntryNotes, targetQty, theorOptPxBitcoins, sigma);
                        if (ivTarget.IsLong)
                        {
                            posMan.BuyAtPrice(m_context, sec, targetQty, theorOptPxBitcoins, ivTarget.EntrySignalName, note);
                        }
                        else
                        {
                            posMan.SellAtPrice(m_context, sec, targetQty, theorOptPxBitcoins, ivTarget.EntrySignalName, note);
                        }
                    }
                    else
                    {
                        string msg = String.Format(CultureInfo.InvariantCulture,
                                                   "IvTarget cancelled. SignalName:{0}; Notes:{1}", ivTarget.EntrySignalName, ivTarget.EntryNotes);
                        posMan.CancelVolatility(m_context, ivTarget, msg);

                        // TODO: потом убрать из ГЛ
                        m_context.Log(msg, MessageType.Info, true, new Dictionary <string, object> {
                            { "VOLATILITY_ORDER_CANCELLED", msg }
                        });
                    }
                }
            }
            #endregion 4. Котирование

            #region 5. Торговля
            if (m_executeCommand && (!DoubleUtil.IsZero(m_qty)))
            {
                double k;
                if ((!Double.TryParse(m_strike, out k)) &&
                    (!Double.TryParse(m_strike, NumberStyles.Any, CultureInfo.InvariantCulture, out k)))
                {
                    return(res);
                }

                var pair = (from p in pairs where DoubleUtil.AreClose(k, p.Strike) select p).SingleOrDefault();
                if (pair == null)
                {
                    return(res);
                }

                InteractiveObject obj = (from o in controlPoints where DoubleUtil.AreClose(k, o.Anchor.ValueX) select o).SingleOrDefault();
                if (obj == null)
                {
                    return(res);
                }

                // TODO: для режима котирования в абсолютных числах сделать отдельную ветку
                //double iv = obj.Anchor.ValueY;
                const QuoteIvMode QuoteMode = QuoteIvMode.Relative;
                if (posMan.BlockTrading)
                {
                    string msg = String.Format(RM.GetString("OptHandlerMsg.PositionsManager.TradingBlocked"),
                                               m_context.Runtime.TradeName + ":QuoteIv");
                    m_context.Log(msg, MessageType.Warning, true);
                    return(res);
                }

                // Выбираю тип инструмента пут или колл?
                bool isCall;
                if (m_optionType == StrikeType.Call)
                {
                    isCall = true;
                }
                else if (m_optionType == StrikeType.Put)
                {
                    isCall = false;
                }
                else
                {
                    isCall = (futPx <= k);
                }

                double iv     = m_shiftIv;
                int    shift  = m_shiftPriceStep;
                var    option = isCall ? pair.Call : pair.Put;
                if (m_qty > 0)
                {
                    // Пересчитываю целочисленный параметр Qty в фактические лоты конкретного инструмента
                    double actQty  = m_qty * option.LotTick;
                    string sigName = String.Format(CultureInfo.InvariantCulture,
                                                   "Qty:{0}; IV:{1:P2}+{2}; dT:{3}; Mode:{4}", actQty, iv, shift, dT, QuoteMode);
                    posMan.BuyVolatility(m_context, option, Math.Abs(actQty), QuoteMode, iv, shift, "BuyVola", sigName);

                    m_context.Log(sigName, MessageType.Info, false);
                }
                else if (m_qty < 0)
                {
                    // Пересчитываю целочисленный параметр Qty в фактические лоты конкретного инструмента
                    double actQty  = m_qty * option.LotTick;
                    string sigName = String.Format(CultureInfo.InvariantCulture,
                                                   "Qty:{0}; IV:{1:P2}+{2}; dT:{3}; Mode:{4}", actQty, iv, shift, dT, QuoteMode);
                    posMan.SellVolatility(m_context, option, Math.Abs(actQty), QuoteMode, iv, shift, "SellVola", sigName);

                    m_context.Log(sigName, MessageType.Info, false);
                }
            }
            #endregion 5. Торговля

            return(res);
        }
Пример #27
0
        /// <summary>
        /// UpdateElementBounds:
        ///     Called by   InkCanvasSelection.UpdateElementBounds
        ///                 ClipboardProcessor.CopySelectionInXAML
        /// </summary>
        /// <param name="originalElement"></param>
        /// <param name="updatedElement"></param>
        /// <param name="transform"></param>
        internal void UpdateElementBounds(UIElement originalElement, UIElement updatedElement, Matrix transform)
        {
            if (originalElement.DependencyObjectType.Id == updatedElement.DependencyObjectType.Id)
            {
                // Get the transform from element to Canvas
                GeneralTransform elementToCanvas = originalElement.TransformToAncestor(_inkCanvas.InnerCanvas);

                //cast to a FrameworkElement, nothing inherits from UIElement besides it right now
                FrameworkElement frameworkElement = originalElement as FrameworkElement;
                Size             size;
                Thickness        thickness = new Thickness();
                if (frameworkElement == null)
                {
                    // Get the element's render size.
                    size = originalElement.RenderSize;
                }
                else
                {
                    size      = new Size(frameworkElement.ActualWidth, frameworkElement.ActualHeight);
                    thickness = frameworkElement.Margin;
                }

                Rect elementBounds = new Rect(0, 0, size.Width, size.Height);   // Rect in element space
                elementBounds = elementToCanvas.TransformBounds(elementBounds); // Rect in Canvas space

                // Now apply the matrix to the element bounds
                Rect newBounds = Rect.Transform(elementBounds, transform);

                if (!DoubleUtil.AreClose(elementBounds.Width, newBounds.Width))
                {
                    if (frameworkElement == null)
                    {
                        Size newSize = originalElement.RenderSize;
                        newSize.Width             = newBounds.Width;
                        updatedElement.RenderSize = newSize;
                    }
                    else
                    {
                        ((FrameworkElement)updatedElement).Width = newBounds.Width;
                    }
                }

                if (!DoubleUtil.AreClose(elementBounds.Height, newBounds.Height))
                {
                    if (frameworkElement == null)
                    {
                        Size newSize = originalElement.RenderSize;
                        newSize.Height            = newBounds.Height;
                        updatedElement.RenderSize = newSize;
                    }
                    else
                    {
                        ((FrameworkElement)updatedElement).Height = newBounds.Height;
                    }
                }

                double left   = InkCanvas.GetLeft(originalElement);
                double top    = InkCanvas.GetTop(originalElement);
                double right  = InkCanvas.GetRight(originalElement);
                double bottom = InkCanvas.GetBottom(originalElement);

                Point originalPosition = new Point(); // Default as (0, 0)
                if (!double.IsNaN(left))
                {
                    originalPosition.X = left;
                }
                else if (!double.IsNaN(right))
                {
                    originalPosition.X = right;
                }

                if (!double.IsNaN(top))
                {
                    originalPosition.Y = top;
                }
                else if (!double.IsNaN(bottom))
                {
                    originalPosition.Y = bottom;
                }

                Point newPosition = originalPosition * transform;

                if (!double.IsNaN(left))
                {
                    InkCanvas.SetLeft(updatedElement, newPosition.X - thickness.Left);           // Left wasn't auto
                }
                else if (!double.IsNaN(right))
                {
                    // NOTICE-2005/05/05-WAYNEZEN
                    // Canvas.RightProperty means the distance between element right side and its parent Canvas
                    // right side. The same definition is applied to Canvas.BottomProperty
                    InkCanvas.SetRight(updatedElement, (right - (newPosition.X - originalPosition.X)));     // Right wasn't not auto
                }
                else
                {
                    InkCanvas.SetLeft(updatedElement, newPosition.X - thickness.Left);           // Both Left and Right were aut. Modify Left by default.
                }

                if (!double.IsNaN(top))
                {
                    InkCanvas.SetTop(updatedElement, newPosition.Y - thickness.Top);           // Top wasn't auto
                }
                else if (!double.IsNaN(bottom))
                {
                    InkCanvas.SetBottom(updatedElement, (bottom - (newPosition.Y - originalPosition.Y)));          // Bottom wasn't not auto
                }
                else
                {
                    InkCanvas.SetTop(updatedElement, newPosition.Y - thickness.Top);           // Both Top and Bottom were aut. Modify Left by default.
                }
            }
            else
            {
                Debug.Assert(false, "The updatedElement has to be the same type as the originalElement.");
            }
        }
Пример #28
0
        public static FrameworkElement GetLastVisibleContainer(
            DataGridControl gridControl,
            FrameworkElement container,
            ScrollViewer scrollViewer)
        {
            FrameworkElement retval = null;

            if (ScrollViewerHelper.IsPixelScrolling(gridControl, container, scrollViewer) == false)
            {
                //This means that the panel is performing Item Scrolling

                //if the panel is Vertically scrolling the items (means the Horizontal Axis is Pixel scrolling)
                if (ScrollViewerHelper.GetItemScrollingOrientation(gridControl, container, scrollViewer) == Orientation.Vertical)
                {
                    retval = ScrollViewerHelper.ProcessLastVisibleContainer(gridControl,
                                                                            scrollViewer.VerticalOffset,
                                                                            scrollViewer.ViewportHeight,
                                                                            scrollViewer.HorizontalOffset,
                                                                            scrollViewer.ViewportWidth,
                                                                            Orientation.Vertical);
                }
                //the panel is Horizontally scrolling the items (means the Vertically Axis is Pixel scrolling)
                else
                {
                    retval = ScrollViewerHelper.ProcessLastVisibleContainer(gridControl,
                                                                            scrollViewer.HorizontalOffset,
                                                                            scrollViewer.ViewportWidth,
                                                                            scrollViewer.VerticalOffset,
                                                                            scrollViewer.ViewportHeight,
                                                                            Orientation.Horizontal);
                }
            }
            else
            {
                Point pt = new Point();

                if ((container is VirtualizingPanel) ||
                    (container is DataGridItemsHost) ||
                    (scrollViewer == null))
                {
                    pt.X = 0;
                    pt.Y = 0;
                }
                else
                {
                    pt.X = scrollViewer.HorizontalOffset;
                    pt.Y = scrollViewer.VerticalOffset;
                }

                Size size = new Size((scrollViewer != null) ? scrollViewer.ViewportWidth : container.ActualWidth,
                                     (scrollViewer != null) ? scrollViewer.ViewportHeight : container.ActualHeight);

                Rect visibleRect = new Rect(pt, size);

                RectangleGeometry geo = new RectangleGeometry(visibleRect);

                lock (ScrollViewerHelper.Current)
                {
                    m_sVisibleChildList.Clear();
                    m_sGridControl = gridControl;

                    VisualTreeHelper.HitTest(container,
                                             new HitTestFilterCallback(ScrollViewerHelper.MyFilterFunct),
                                             new HitTestResultCallback(ScrollViewerHelper.UselessResultCallback),
                                             new GeometryHitTestParameters(geo));

                    m_sGridControl = null;

                    FrameworkElement  preservedChild  = null;
                    Nullable <Vector> preservedOffset = null;

                    foreach (FrameworkElement child in m_sVisibleChildList)
                    {
                        Vector itemOffset = VisualTreeHelper.GetOffset(child);

                        Rect itemRect = new Rect(itemOffset.X, itemOffset.Y, child.ActualWidth, child.ActualHeight);

                        itemRect.Intersect(visibleRect);

                        switch (gridControl.ItemsPrimaryAxis)
                        {
                        case PrimaryAxis.Vertical:
                            if (DoubleUtil.AreClose(itemRect.Width, 0) == false)
                            {
                                if (DoubleUtil.AreClose(itemRect.Height, child.ActualHeight) == true)
                                {
                                    if (ScrollViewerHelper.IsABetterLastRow(preservedChild, preservedOffset, itemOffset) == true)
                                    {
                                        preservedChild  = child;
                                        preservedOffset = itemOffset;
                                    }
                                }
                            }
                            break;

                        case PrimaryAxis.Horizontal:
                            if (DoubleUtil.AreClose(itemRect.Width, child.ActualWidth) == true)
                            {
                                if (DoubleUtil.AreClose(itemRect.Height, 0) == false)
                                {
                                    if (ScrollViewerHelper.IsABetterLastRow(preservedChild, preservedOffset, itemOffset) == true)
                                    {
                                        preservedChild  = child;
                                        preservedOffset = itemOffset;
                                    }
                                }
                            }
                            break;

                        case PrimaryAxis.Both:
                            if ((DoubleUtil.AreClose(itemRect.Width, child.ActualWidth) == true) &&
                                (DoubleUtil.AreClose(itemRect.Height, child.ActualHeight) == true))
                            {
                                if (ScrollViewerHelper.IsABetterLastRow(preservedChild, preservedOffset, itemOffset) == true)
                                {
                                    preservedChild  = child;
                                    preservedOffset = itemOffset;
                                }
                            }
                            break;

                        case PrimaryAxis.None:
                            if (itemRect.IsEmpty == false)
                            {
                                if ((DoubleUtil.AreClose(itemRect.Height, 0) == false) && (DoubleUtil.AreClose(itemRect.Width, 0) == false))
                                {
                                    if (ScrollViewerHelper.IsABetterLastRow(preservedChild, preservedOffset, itemOffset) == true)
                                    {
                                        preservedChild  = child;
                                        preservedOffset = itemOffset;
                                    }
                                }
                            }
                            break;
                        }
                    }

                    retval = preservedChild;
                }//end lock (protection of shared static members with GetFirstVisibleItem() )
            }


            return(retval);
        }
Пример #29
0
        // Token: 0x06007033 RID: 28723 RVA: 0x00203B70 File Offset: 0x00201D70
        protected sealed override Size ArrangeOverride(Size arrangeSize)
        {
            Rect empty = Rect.Empty;
            bool flag  = false;
            Size size  = arrangeSize;

            if (!this._suspendLayout)
            {
                TextDpi.SnapToTextDpi(ref size);
                if (this.Document != null)
                {
                    this.EnsureFormatter();
                    if (this._scrollData != null)
                    {
                        if (!DoubleUtil.AreClose(this._scrollData.Viewport, size))
                        {
                            this._scrollData.Viewport = size;
                            flag = true;
                        }
                        if (!DoubleUtil.AreClose(this._scrollData.Extent, this._formatter.DocumentPage.Size))
                        {
                            this._scrollData.Extent = this._formatter.DocumentPage.Size;
                            flag = true;
                            if (Math.Abs(this._scrollData.ExtentWidth - this._scrollData.ViewportWidth) < 1.0)
                            {
                                this._scrollData.ExtentWidth = this._scrollData.ViewportWidth;
                            }
                            if (Math.Abs(this._scrollData.ExtentHeight - this._scrollData.ViewportHeight) < 1.0)
                            {
                                this._scrollData.ExtentHeight = this._scrollData.ViewportHeight;
                            }
                        }
                        Vector vector = new Vector(Math.Max(0.0, Math.Min(this._scrollData.ExtentWidth - this._scrollData.ViewportWidth, this._scrollData.HorizontalOffset)), Math.Max(0.0, Math.Min(this._scrollData.ExtentHeight - this._scrollData.ViewportHeight, this._scrollData.VerticalOffset)));
                        if (!DoubleUtil.AreClose(vector, this._scrollData.Offset))
                        {
                            this._scrollData.Offset = vector;
                            flag = true;
                        }
                        if (flag && this._scrollData.ScrollOwner != null)
                        {
                            this._scrollData.ScrollOwner.InvalidateScrollInfo();
                        }
                        empty = new Rect(this._scrollData.HorizontalOffset, this._scrollData.VerticalOffset, size.Width, size.Height);
                    }
                    this._formatter.Arrange(size, empty);
                    if (this._pageVisual != this._formatter.DocumentPage.Visual)
                    {
                        if (this._textView != null)
                        {
                            this._textView.OnPageConnected();
                        }
                        if (this._pageVisual != null)
                        {
                            base.RemoveVisualChild(this._pageVisual);
                        }
                        this._pageVisual = (PageVisual)this._formatter.DocumentPage.Visual;
                        base.AddVisualChild(this._pageVisual);
                    }
                    if (this._scrollData != null)
                    {
                        this._pageVisual.Offset = new Vector(-this._scrollData.HorizontalOffset, -this._scrollData.VerticalOffset);
                    }
                    PtsHelper.UpdateMirroringTransform(base.FlowDirection, FlowDirection.LeftToRight, this._pageVisual, size.Width);
                }
                else
                {
                    if (this._pageVisual != null)
                    {
                        if (this._textView != null)
                        {
                            this._textView.OnPageDisconnected();
                        }
                        base.RemoveVisualChild(this._pageVisual);
                        this._pageVisual = null;
                    }
                    if (this._scrollData != null)
                    {
                        if (!DoubleUtil.AreClose(this._scrollData.Viewport, size))
                        {
                            this._scrollData.Viewport = size;
                            flag = true;
                        }
                        if (!DoubleUtil.AreClose(this._scrollData.Extent, default(Size)))
                        {
                            this._scrollData.Extent = default(Size);
                            flag = true;
                        }
                        if (!DoubleUtil.AreClose(this._scrollData.Offset, default(Vector)))
                        {
                            this._scrollData.Offset = default(Vector);
                            flag = true;
                        }
                        if (flag && this._scrollData.ScrollOwner != null)
                        {
                            this._scrollData.ScrollOwner.InvalidateScrollInfo();
                        }
                    }
                }
            }
            return(arrangeSize);
        }
Пример #30
0
        /// <summary>
        /// HitTest a line array and find the index of line hit in horizontal direction.
        /// Assumes that vertical hittesting has been already done and lineIndex points to
        /// index of line that has been hit in vertical direction.
        /// </summary>
        /// <param name="lines">Collection of lines.</param>
        /// <param name="point">Point in pixel coordinates to test.</param>
        /// <param name="snapToText">
        /// If true, this method must always return a line index
        /// (the closest position as calculated by the control's heuristics).
        /// If false, this method should return -1, if the test
        /// point does not fall within any character bounding box.
        /// </param>
        /// <param name="lineIndex">Index of line that has been hit.</param>
        /// <returns>True if hit has been found.</returns>
        private static bool GetHorizontalLineFromPoint(ReadOnlyCollection <LineResult> lines, Point point, bool snapToText, ref int lineIndex)
        {
            Debug.Assert(lines != null && lines.Count > 0);

            bool foundHit        = false;
            bool lookForSiblings = true;

            // It is possible to have successive lines with the same
            // vertical offset. It may happen when a line of text is split
            // because of figure/floater.
            // Figure out which line is the closest horizontally to the input pixel position.
            while (lookForSiblings)
            {
                Rect   lineBox = lines[lineIndex].LayoutBox;
                Rect   siblingLineBox;
                double siblingGap;

                // Check sibling lines.
                if (point.X < lineBox.X && lineIndex > 0)
                {
                    // Check if the previous line starts at the same vertical position.
                    siblingLineBox = lines[lineIndex - 1].LayoutBox;
                    if (DoubleUtil.AreClose(siblingLineBox.Y, lineBox.Y))
                    {
                        if (point.X <= siblingLineBox.X + siblingLineBox.Width)
                        {
                            --lineIndex;
                        }
                        else
                        {
                            siblingGap = Math.Max(lineBox.X - (siblingLineBox.X + siblingLineBox.Width), 0);
                            if (point.X < lineBox.X - siblingGap / 2)
                            {
                                --lineIndex;
                            }
                            foundHit        = snapToText;
                            lookForSiblings = false;
                            break;
                        }
                    }
                    else
                    {
                        foundHit        = snapToText;
                        lookForSiblings = false;
                        break;
                    }
                }
                else if ((point.X > lineBox.X + lineBox.Width) && (lineIndex < lines.Count - 1))
                {
                    // Check if the next line starts at the same vertical position.
                    siblingLineBox = lines[lineIndex + 1].LayoutBox;
                    if (DoubleUtil.AreClose(siblingLineBox.Y, lineBox.Y))
                    {
                        if (point.X >= siblingLineBox.X)
                        {
                            ++lineIndex;
                        }
                        else
                        {
                            siblingGap = Math.Max(siblingLineBox.X - (lineBox.X + lineBox.Width), 0);
                            if (point.X > siblingLineBox.X - siblingGap / 2)
                            {
                                ++lineIndex;
                            }
                            foundHit        = snapToText;
                            lookForSiblings = false;
                            break;
                        }
                    }
                    else
                    {
                        foundHit        = snapToText;
                        lookForSiblings = false;
                        break;
                    }
                }
                else
                {
                    foundHit        = snapToText || (point.X >= lineBox.X && point.X <= lineBox.X + lineBox.Width);
                    lookForSiblings = false;
                    break;
                }
            }

            return(foundHit);
        }