/// 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); } }
// 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(); } }
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)); }
// 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)); }
/// <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); }
/// <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)); }
/// <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)); }
/// <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); }
/// <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)); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
#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)); }
// 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)); }
/// <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)); }
// 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)); }
/// <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)); } }
// ------------------------------------------------------------------ // 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]); } } } } }
/// <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()); }
/// <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); }
/// <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."); } }
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); }
// 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); }
/// <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); }