/// <summary> /// Helper function, which draws a screw on the frame /// </summary> /// <param name="graph">Chart graphics to use.</param> /// <param name="rect">Screw position.</param> private void DrawScrew(ChartGraphics graph, SKRect rect) { // Draw screw SKPaint screwPen = new() { Color = Color.FromArgb(128, 255, 255, 255), StrokeWidth = 1, Style = SKPaintStyle.Stroke }; graph.DrawEllipse(screwPen, rect.Left, rect.Top, rect.Width, rect.Height); graph.DrawLine(screwPen, rect.Left + 2 * resolution / 96.0f, rect.Top + rect.Height - 2 * resolution / 96.0f, rect.Right - 2 * resolution / 96.0f, rect.Top + 2 * resolution / 96.0f); screwPen.Color = Color.FromArgb(128, SKColors.Black); graph.DrawEllipse(screwPen, rect.Left + 1 * resolution / 96.0f, rect.Top + 1 * resolution / 96.0f, rect.Width, rect.Height); graph.DrawLine(screwPen, rect.Left + 3 * resolution / 96.0f, rect.Top + rect.Height - 1 * resolution / 96.0f, rect.Right - 1 * resolution / 96.0f, rect.Top + 3 * resolution / 96.0f); } #endregion Border properties and methods }
/// <summary> /// Draws a marker that represents a data point in FastPoint series. /// </summary> /// <param name="graph">Chart graphics used to draw the marker.</param> /// <param name="point">Series data point drawn.</param> /// <param name="pointIndex">Data point index in the series.</param> /// <param name="location">Marker location in pixels.</param> /// <param name="markerStyle">Marker style.</param> /// <param name="markerSize">Marker size in pixels.</param> /// <param name="brush">Brush used to fill marker shape.</param> /// <param name="borderPen">Marker border pen.</param> virtual protected void DrawMarker( ChartGraphics graph, DataPoint point, int pointIndex, SKPoint location, MarkerStyle markerStyle, int markerSize, SKPaint brush, SKPaint borderPen) { // Transform 3D coordinates if (chartArea3DEnabled) { Point3D[] points = new Point3D[1]; location = graph.GetRelativePoint(location); points[0] = new Point3D(location.X, location.Y, seriesZCoordinate); matrix3D.TransformPoints(points); location.X = points[0].X; location.Y = points[0].Y; location = graph.GetAbsolutePoint(location); } // Create marker bounding rectangle in pixels SKRect markerBounds = new( location.X - markerSize / 2f, location.Y - markerSize / 2f, markerSize, markerSize); // Draw Marker switch (markerStyle) { case (MarkerStyle.Star4): case (MarkerStyle.Star5): case (MarkerStyle.Star6): case (MarkerStyle.Star10): { // Set number of corners int cornerNumber = 4; if (markerStyle == MarkerStyle.Star5) { cornerNumber = 5; } else if (markerStyle == MarkerStyle.Star6) { cornerNumber = 6; } else if (markerStyle == MarkerStyle.Star10) { cornerNumber = 10; } // Get star polygon SKPoint[] points = ChartGraphics.CreateStarPolygon(markerBounds, cornerNumber); // Fill shape graph.FillPolygon(brush, points); // Draw border if (borderPen != null) { graph.DrawPolygon(borderPen, points); } break; } case (MarkerStyle.Circle): { graph.FillEllipse(brush, markerBounds); // Draw border if (borderPen != null) { graph.DrawEllipse(borderPen, markerBounds); } break; } case (MarkerStyle.Square): { graph.FillRectangle(brush, markerBounds); // Draw border if (borderPen != null) { graph.DrawRectangle( borderPen, (int)Math.Round(markerBounds.Left, 0), (int)Math.Round(markerBounds.Top, 0), (int)Math.Round(markerBounds.Width, 0), (int)Math.Round(markerBounds.Height, 0)); } break; } case (MarkerStyle.Cross): { // Calculate cross line width and size float crossLineWidth = (float)Math.Ceiling(markerSize / 4F); float crossSize = markerSize; // * (float)Math.Sin(45f/180f*Math.PI) // Calculate cross coordinates SKPoint[] points = new SKPoint[12]; points[0].X = location.X - crossSize / 2F; points[0].Y = location.Y + crossLineWidth / 2F; points[1].X = location.X - crossSize / 2F; points[1].Y = location.Y - crossLineWidth / 2F; points[2].X = location.X - crossLineWidth / 2F; points[2].Y = location.Y - crossLineWidth / 2F; points[3].X = location.X - crossLineWidth / 2F; points[3].Y = location.Y - crossSize / 2F; points[4].X = location.X + crossLineWidth / 2F; points[4].Y = location.Y - crossSize / 2F; points[5].X = location.X + crossLineWidth / 2F; points[5].Y = location.Y - crossLineWidth / 2F; points[6].X = location.X + crossSize / 2F; points[6].Y = location.Y - crossLineWidth / 2F; points[7].X = location.X + crossSize / 2F; points[7].Y = location.Y + crossLineWidth / 2F; points[8].X = location.X + crossLineWidth / 2F; points[8].Y = location.Y + crossLineWidth / 2F; points[9].X = location.X + crossLineWidth / 2F; points[9].Y = location.Y + crossSize / 2F; points[10].X = location.X - crossLineWidth / 2F; points[10].Y = location.Y + crossSize / 2F; points[11].X = location.X - crossLineWidth / 2F; points[11].Y = location.Y + crossLineWidth / 2F; // Rotate cross coordinates 45 degrees SKMatrix rotationMatrix = SKMatrix.CreateRotationDegrees(45, location.X, location.Y); rotationMatrix.TransformPoints(points); // Fill shape graph.FillPolygon(brush, points); // Draw border if (borderPen != null) { graph.DrawPolygon(borderPen, points); } break; } case (MarkerStyle.Diamond): { SKPoint[] points = new SKPoint[4]; points[0].X = markerBounds.Left; points[0].Y = markerBounds.Top + markerBounds.Height / 2F; points[1].X = markerBounds.Left + markerBounds.Width / 2F; points[1].Y = markerBounds.Top; points[2].X = markerBounds.Right; points[2].Y = markerBounds.Top + markerBounds.Height / 2F; points[3].X = markerBounds.Left + markerBounds.Width / 2F; points[3].Y = markerBounds.Bottom; graph.FillPolygon(brush, points); // Draw border if (borderPen != null) { graph.DrawPolygon(borderPen, points); } break; } case (MarkerStyle.Triangle): { SKPoint[] points = new SKPoint[3]; points[0].X = markerBounds.Left; points[0].Y = markerBounds.Bottom; points[1].X = markerBounds.Top + markerBounds.Width / 2F; points[1].Y = markerBounds.Top; points[2].X = markerBounds.Right; points[2].Y = markerBounds.Bottom; graph.FillPolygon(brush, points); // Draw border if (borderPen != null) { graph.DrawPolygon(borderPen, points); } break; } default: { throw (new InvalidOperationException(SR.ExceptionFastPointMarkerStyleUnknown)); } } // Process selection regions if (Common.ProcessModeRegions) { Common.HotRegionsList.AddHotRegion( graph.GetRelativeRectangle(markerBounds), point, point.series.Name, pointIndex); } }
/// <summary> /// Draws 3D button in the scroll bar /// </summary> /// <param name="graph">Chart graphics.</param> /// <param name="buttonRect">Button position.</param> /// <param name="pressedState">Indicates that button is pressed.</param> /// <param name="buttonType">Button type to draw.</param> internal void PaintScrollBar3DButton( ChartGraphics graph, SKRect buttonRect, bool pressedState, ScrollBarButtonType buttonType) { // Page Up/Down buttons do not require drawing if (buttonType == ScrollBarButtonType.LargeIncrement || buttonType == ScrollBarButtonType.LargeDecrement) { return; } // Get 3 levels of colors for button drawing var darkerColor = ChartGraphics.GetGradientColor(_buttonCurrentColor, SKColors.Black, 0.5); var darkestColor = ChartGraphics.GetGradientColor(_buttonCurrentColor, SKColors.Black, 0.8); var lighterColor = ChartGraphics.GetGradientColor(_buttonCurrentColor, SKColors.White, 0.5); // Fill button rectangle background graph.FillRectangleRel( buttonRect, _buttonCurrentColor, ChartHatchStyle.None, "", ChartImageWrapMode.Tile, SKColor.Empty, ChartImageAlignmentStyle.Center, GradientStyle.None, SKColor.Empty, darkerColor, (pressedState) ? 1 : 0, ChartDashStyle.Solid, SKColor.Empty, 0, PenAlignment.Outset); // Check if 2 or 1 pixel border will be drawn (if size too small) bool singlePixelBorder = Size <= 12; // Draw 3D effect around the button when not pressed if (!pressedState) { // Get relative size of 1 pixel SKSize pixelRelativeSize = new(1, 1); pixelRelativeSize = graph.GetRelativeSize(pixelRelativeSize); // Draw top/left border with button color graph.DrawLineRel( (singlePixelBorder) ? lighterColor : _buttonCurrentColor, 1, ChartDashStyle.Solid, new SKPoint(buttonRect.Left, buttonRect.Bottom), new SKPoint(buttonRect.Left, buttonRect.Top)); graph.DrawLineRel( (singlePixelBorder) ? lighterColor : _buttonCurrentColor, 1, ChartDashStyle.Solid, new SKPoint(buttonRect.Left, buttonRect.Top), new SKPoint(buttonRect.Right, buttonRect.Top)); // Draw right/bottom border with the darkest color graph.DrawLineRel( (singlePixelBorder) ? darkerColor : darkestColor, 1, ChartDashStyle.Solid, new SKPoint(buttonRect.Right, buttonRect.Bottom), new SKPoint(buttonRect.Right, buttonRect.Top)); graph.DrawLineRel( (singlePixelBorder) ? darkerColor : darkestColor, 1, ChartDashStyle.Solid, new SKPoint(buttonRect.Left, buttonRect.Bottom), new SKPoint(buttonRect.Right, buttonRect.Bottom)); if (!singlePixelBorder) { // Draw right/bottom border (offset 1) with the dark color graph.DrawLineRel( darkerColor, 1, ChartDashStyle.Solid, new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height), new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Top + pixelRelativeSize.Height)); graph.DrawLineRel( darkerColor, 1, ChartDashStyle.Solid, new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height), new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height)); // Draw top/left border (offset 1) with lighter color graph.DrawLineRel( lighterColor, 1, ChartDashStyle.Solid, new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Bottom - pixelRelativeSize.Height), new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Top + pixelRelativeSize.Height)); graph.DrawLineRel( lighterColor, 1, ChartDashStyle.Solid, new SKPoint(buttonRect.Left + pixelRelativeSize.Width, buttonRect.Left + pixelRelativeSize.Height), new SKPoint(buttonRect.Right - pixelRelativeSize.Width, buttonRect.Left + pixelRelativeSize.Height)); } } // Check axis orientation bool verticalAxis = (axis.AxisPosition == AxisPosition.Left || axis.AxisPosition == AxisPosition.Right); // Set graphics transformation for button pressed mode float pressedShifting = (singlePixelBorder) ? 0.5f : 1f; if (pressedState) { graph.TranslateTransform(pressedShifting, pressedShifting); } // Draw button image SKRect buttonAbsRect = graph.GetAbsoluteRectangle(buttonRect); float imageOffset = (singlePixelBorder) ? 2 : 3; switch (buttonType) { case (ScrollBarButtonType.SmallDecrement): { // Calculate triangal points position SKPoint[] points = new SKPoint[3]; if (verticalAxis) { points[0].X = buttonAbsRect.Left + imageOffset; points[0].Y = buttonAbsRect.Top + (imageOffset + 1f); points[1].X = buttonAbsRect.Left + buttonAbsRect.Width / 2f; points[1].Y = buttonAbsRect.Bottom - imageOffset; points[2].X = buttonAbsRect.Right - imageOffset; points[2].Y = buttonAbsRect.Top + (imageOffset + 1f); } else { points[0].X = buttonAbsRect.Left + imageOffset; points[0].Y = buttonAbsRect.Top + buttonAbsRect.Height / 2f; points[1].X = buttonAbsRect.Right - (imageOffset + 1f); points[1].Y = buttonAbsRect.Top + imageOffset; points[2].X = buttonAbsRect.Right - (imageOffset + 1f); points[2].Y = buttonAbsRect.Bottom - imageOffset; } using var brush = new SKPaint { Style = SKPaintStyle.Fill, Color = _lineCurrentColor }; graph.FillPolygon(brush, points); break; } case (ScrollBarButtonType.SmallIncrement): { // Calculate triangal points position SKPoint[] points = new SKPoint[3]; if (verticalAxis) { points[0].X = buttonAbsRect.Left + imageOffset; points[0].Y = buttonAbsRect.Bottom - (imageOffset + 1f); points[1].X = buttonAbsRect.Left + buttonAbsRect.Width / 2f; points[1].Y = buttonAbsRect.Top + imageOffset; points[2].X = buttonAbsRect.Right - imageOffset; points[2].Y = buttonAbsRect.Bottom - (imageOffset + 1f); } else { points[0].X = buttonAbsRect.Right - imageOffset; points[0].Y = buttonAbsRect.Top + buttonAbsRect.Height / 2f; points[1].X = buttonAbsRect.Left + (imageOffset + 1f); points[1].Y = buttonAbsRect.Top + imageOffset; points[2].X = buttonAbsRect.Left + (imageOffset + 1f); points[2].Y = buttonAbsRect.Bottom - imageOffset; } using var brush = new SKPaint { Style = SKPaintStyle.Fill, Color = _lineCurrentColor }; graph.FillPolygon(brush, points); break; } case (ScrollBarButtonType.ZoomReset): { // Draw circule with a minus sign using var pen = new SKPaint { Style = SKPaintStyle.Fill, Color = _lineCurrentColor }; graph.DrawEllipse(pen, buttonAbsRect.Left + imageOffset - 0.5f, buttonAbsRect.Top + imageOffset - 0.5f, buttonAbsRect.Width - 2f * imageOffset, buttonAbsRect.Height - 2f * imageOffset); graph.DrawLine(pen, buttonAbsRect.Left + imageOffset + 1.5f, buttonAbsRect.Top + buttonAbsRect.Height / 2f - 0.5f, buttonAbsRect.Right - imageOffset - 2.5f, buttonAbsRect.Top + buttonAbsRect.Height / 2f - 0.5f); break; } } // Reset graphics transformation for button pressed mode if (pressedState) { graph.TranslateTransform(-pressedShifting, -pressedShifting); } }