Esempio n. 1
0
        private void DrawSlider(SKCanvas canvas, SKRect frame, SKRect chart)
        {
            if (!IsSliderVisible)
            {
                return;
            }

            if (!IsInitialized)
            {
                FindClosestItem(TouchedPoint.X);
            }

            float x = chart.GetInsideXValue(TouchedPoint.X);

            using (var paint = new SKPaint
            {
                Style = SKPaintStyle.Stroke,
                StrokeCap = UseItemWidthSlider ? SKStrokeCap.Butt : SKStrokeCap.Round,
                Color = this.SliderColor.ToSKColor().AsTransparency(),
                StrokeWidth = UseItemWidthSlider ? frame.GetItemWidth(MaxItems) : this.SliderWidth
            })
            {
                // Straight slider line
                canvas.DrawLine(x, chart.Top, x, DisplayHorizontalValuesBySlider && !UseItemWidthSlider ? frame.Bottom + HorizontalTextSize : chart.Bottom, paint);

                DrawSliderHint(canvas, x);
            }

            // Get items on x axis
            var valueItems = ChartEntries.GetChartValueItemFromX(x, frame, frame.GetItemWidth(MaxItems));

            // Send selected items with command
            SelectedValuesCommand?.Execute(new SelectedChartValueItemArgs
            {
                ChartValueItems = valueItems,
                TouchedPoint    = new SKPoint(x, TouchedPoint.Y)
            });
        }
Esempio n. 2
0
        protected void CalculateChartValuesXPoints(SKRect chart)
        {
            ChartValueItemsXPoints = new List <Tuple <object, float> >();

            var chartEntries = ChartValuesDistinct;

            // Calculate the width of one item (distance between items)
            var itemWidth = chart.GetItemWidth(chartEntries.Count());

            for (int i = 0; i < chartEntries.Count(); i++)
            {
                var entry = chartEntries.ElementAt(i);

                float x = chart.Left + (i * itemWidth);

                ChartValueItemsXPoints.Add(new Tuple <object, float>(entry.Tag, x));
            }
        }
Esempio n. 3
0
        private void DrawBackground(SKCanvas canvas, SKRect frame)
        {
            if (!HasBackground)
            {
                return;
            }

            using (var paint = new SKPaint
            {
                IsAntialias = true,
                Color = ChartBackgroundColor.ToSKColor(),
                Style = SKPaintStyle.Fill
            })
            {
                var items = ChartValueItemsXPoints;

                var width = frame.GetItemWidth(MaxItems);

                for (int i = 0; i < items.Count; i++)
                {
                    if (i % 2 != 0)
                    {
                        continue;
                    }

                    var item = items[i];

                    var left = item.Item2;

                    // Don't draw outside frame
                    if ((left + (width * 2)).ToRounded() <= (frame.Right + FrameWidth).ToRounded())
                    {
                        canvas.DrawRect(left + width, frame.Top, width, frame.Height - FrameWidth, paint);
                    }
                }
            }
        }
Esempio n. 4
0
        protected SKPoint[] CalculatePoints(IEnumerable <ChartValueItem> valueItems, SKRect frame, SKRect chart)
        {
            var result = new List <SKPoint>();

            // Calculate how many values one y position is
            var valueY = MaxValue / frame.Height;

            // Calculate the width of one item (distance between items)
            var itemWidth = chart.GetItemWidth(MaxItems);

            for (int i = 0; i < valueItems.Count(); i++)
            {
                var entry = valueItems.ElementAt(i);

                float x;

                if (ChartValueItemsXPoints.FirstOrDefault(p => p.Item1.ToString() == entry.Tag.ToString())?.Item2 > 0)
                {
                    x = ChartValueItemsXPoints.FirstOrDefault(p => p.Item1.ToString() == entry.Tag.ToString()).Item2;
                }
                else
                {
                    x = chart.Left + (i * itemWidth);
                }

                // Calculate items y position with frame height (bottom to upper)
                var y = frame.Top + (frame.Height - (entry.Value / valueY));

                var point = new SKPoint(x, y);
                result.Add(point);

                entry.Point = point;
            }

            return(result.ToArray());
        }
Esempio n. 5
0
        private void DrawBackground(SKCanvas canvas, SKRect frame)
        {
            if (!HasBackground)
            {
                return;
            }

            using (var paint = new SKPaint
            {
                IsAntialias = true,
                Color = ChartBackgroundColor.ToSKColor(),
                Style = LineBackground ? SKPaintStyle.Stroke : SKPaintStyle.Fill,
                IsStroke = LineBackground,
            })
            {
                if (DashedFrame)
                {
                    paint.PathEffect = SKPathEffect.CreateDash(new float[] { 12, 12 }, 0);
                }

                if (LineBackground)
                {
                    paint.StrokeWidth = 2f;
                }

                var items = ChartValueItemsXPoints;

                var width = frame.GetItemWidth(MaxItems);

                for (int i = 0; i < items.Count; i++)
                {
                    if (LineBackground)
                    {
                        var item = items[i];

                        var left = item.Item2;

                        if (i != 0 && i != items.Count - 1)
                        {
                            canvas.DrawLine(left, frame.Bottom, left, frame.Top, paint);
                        }
                    }
                    else
                    {
                        if (i % 2 != 0)
                        {
                            continue;
                        }

                        var item = items[i];

                        var left = item.Item2;

                        // Don't draw outside frame
                        if ((left + (width * 2)).ToRounded() <= (frame.Right + FrameWidth).ToRounded())
                        {
                            canvas.DrawRect(left + width, frame.Top, width, frame.Height - FrameWidth, paint);
                        }
                    }
                }
            }
        }
Esempio n. 6
0
        private void DrawBars(SKCanvas canvas, SKRect frame, SKRect chart)
        {
            // Selected bar width
            var selectedValueItems = ChartEntries.GetChartValueItemFromX(chart.GetInsideXValue(TouchedPoint.X), chart, chart.GetItemWidth(MaxItems));
            var selectedTags       = selectedValueItems?.Select(x => x.ChartValueItem.Tag);

            // Invoke command with selected items
            SelectedValuesCommand?.Execute(new SelectedChartValueItemArgs
            {
                ChartValueItems = selectedValueItems,
                TouchedPoint    = new SKPoint(chart.GetInsideXValue(TouchedPoint.X), TouchedPoint.Y)
            });

            using (var paint = new SKPaint
            {
                IsAntialias = true,
                Style = SKPaintStyle.StrokeAndFill,
                StrokeCap = SKStrokeCap.Butt,
            })
            {
                var groupedItems = ChartEntries.Where(x => x.IsVisible).SelectMany(x => x.Items).GroupBy(x => x.Tag.ToString()).OrderBy(x => x.Key);

                // Calc max items in one group
                var maxItemsInGroups = groupedItems.Max(x => x.Count());

                // Calc how many groups there is
                var groupCount = groupedItems.Count();

                // Calc how many bars there will be
                var totalBars = groupCount * maxItemsInGroups;

                var internalGroupMargin = maxItemsInGroups == 1 ? BarMargin : GroupMargin;
                var internalBarMargin   = maxItemsInGroups == 1 ? 0 : BarMargin;
                var internalBarWidth    = MinimumBarWidth;

                float itemWidth;

                if (AllowScroll)
                {
                    // Calc total item width
                    itemWidth = internalBarWidth * maxItemsInGroups + ((maxItemsInGroups - 1) * barMargin);
                }
                else
                {
                    itemWidth = chart.Width / groupCount;

                    itemWidth -= internalGroupMargin;

                    internalBarWidth = (itemWidth / maxItemsInGroups) - ((maxItemsInGroups - 1) * barMargin);
                }

                int groupIndex = 0;

                float scrollLeftPadding = 0;
                float left      = 0;
                float groupLeft = 0;
                float right     = 0;

                groupCenters = new List <GroupChartItem>();

                foreach (var groupedItem in groupedItems)
                {
                    int itemIndex = 0;

                    groupLeft = left;

                    if (!AllowScroll && IsSliderVisible && selectedTags?.Contains(groupedItem.Key) == true)
                    {
                        var item = groupedItem.OrderByDescending(x => x.Value).First();

                        paint.Color      = SliderColor.ToSKColor();
                        paint.PathEffect = SKPathEffect.CreateCorner(SliderCornerRadius);

                        var bounds = new SKRect(
                            item.Point.X - (itemWidth * .5f) - (groupMargin * .5f),
                            item.Point.Y - (itemWidth * .5f),
                            item.Point.X + (itemWidth * .5f) + (groupMargin * .5f),
                            chart.Bottom + HorizontalTextSize);

                        paint.StrokeWidth = 0;

                        canvas.DrawRect(bounds, paint);
                    }

                    foreach (var item in groupedItem)
                    {
                        var parent = ChartEntries.FirstOrDefault(x => x.Items.Contains(item));

                        SKRect bounds = new SKRect();

                        if (AllowScroll)
                        {
                            if (left == 0)
                            {
                                left = itemWidth.FromDpiAdjusted();

                                groupLeft = left;

                                scrollLeftPadding = left;
                            }
                            else if (itemIndex != 0)
                            {
                                left += internalBarMargin;
                            }

                            right = left + internalBarWidth;

                            bounds = new SKRect(
                                left,
                                item.Point.Y,
                                right,
                                chart.Bottom);

                            left = right;
                        }
                        else
                        {
                            left  = (item.Point.X - (itemWidth * .5f)) + (internalBarWidth * itemIndex) + (internalBarMargin * itemIndex);
                            right = left + internalBarWidth;

                            bounds = new SKRect(
                                left,
                                item.Point.Y,
                                right,
                                chart.Bottom);
                        }

                        paint.StrokeWidth = 0;

                        if (parent.UseDashedEffect)
                        {
                            paint.Color      = parent.Color.ToSKColor().AsTransparency();
                            paint.PathEffect = SKPathEffect.CreateCorner(BarCornerRadius);

                            canvas.DrawRect(bounds, paint);

                            paint.Color      = parent.Color.ToSKColor();
                            paint.PathEffect = SKPathEffect.CreateDash(new float[] { StrokeDashFirst, StrokeDashSecond }, StrokeDashPhase);

                            paint.StrokeWidth = bounds.Width;

                            canvas.DrawLine(bounds.MidX, bounds.Bottom, bounds.MidX, bounds.Top, paint);
                        }
                        else
                        {
                            paint.Color      = parent.Color.ToSKColor();
                            paint.PathEffect = SKPathEffect.CreateCorner(BarCornerRadius);
                            canvas.DrawRect(bounds, paint);
                        }

                        itemIndex++;
                    }

                    left += internalGroupMargin;

                    groupIndex++;

                    var groupCenterPosition = groupLeft + (itemWidth / 2);

                    groupCenters.Add(new GroupChartItem
                    {
                        Label    = groupedItem.FirstOrDefault().Label,
                        Position = groupCenterPosition.FromDpiAdjusted(),
                        Tag      = groupedItem.Key
                    });
                }

                if (AllowScroll)
                {
                    var requestedWidth = right.FromDpiAdjusted() + frame.Left.FromDpiAdjusted();

                    if (requestedWidth != this.WidthRequest)
                    {
                        this.WidthRequest = requestedWidth;
                    }
                    else
                    {
                        SetStartPosition(groupCenters);
                        IsInitialized = true;
                    }

                    if (ScrollComponent != null)
                    {
                        var deviceWidth = Xamarin.Essentials.DeviceDisplay.MainDisplayInfo.Width;

                        var halfDeviceWidth = ((float)(deviceWidth / 2)).FromDpiAdjusted();

                        var frameLeftVal       = frame.Left.FromDpiAdjusted();
                        var rectRightMarginVal = ChartRectMargin.Right.FromDpiAdjusted();

                        var leftPadding = halfDeviceWidth - frameLeftVal - scrollLeftPadding.FromDpiAdjusted();

                        var rightPadding = halfDeviceWidth - frameLeftVal - rectRightMarginVal - itemWidth.FromDpiAdjusted();

                        ScrollComponent.Padding = new Thickness(leftPadding, 0, rightPadding, 0);
                        ScrollComponent.Margin  = new Thickness(frame.Left.FromDpiAdjusted(), 0, ChartRectMargin.Right.FromDpiAdjusted(), 0);

                        if (Selector != null)
                        {
                            Selector.WidthRequest = itemWidth.FromDpiAdjusted();
                            Selector.Margin       = new Thickness(halfDeviceWidth, 0, 0, this.Height - frame.Bottom.FromDpiAdjusted());
                        }

                        if (!isScrollEventActive)
                        {
                            ScrollComponent.Scrolled += ScrollComponent_Scrolled;
                            isScrollEventActive       = true;
                        }
                    }

                    if (SwipeNotificationLeft != null)
                    {
                        SwipeNotificationLeft.Margin       = new Thickness(frame.Left.FromDpiAdjusted(), 0, 0, this.Height - frame.Bottom.FromDpiAdjusted());
                        SwipeNotificationLeft.WidthRequest = ScrollComponent.Padding.Left;
                    }

                    if (SwipeNotificationRight != null)
                    {
                        SwipeNotificationRight.Margin       = new Thickness(0, 0, ChartRectMargin.Right.FromDpiAdjusted(), this.Height - frame.Bottom.FromDpiAdjusted());
                        SwipeNotificationRight.WidthRequest = ScrollComponent.Padding.Left;
                    }
                }
            }

            DrawHorizontalLabel(selectedValueItems?.FirstOrDefault()?.ChartValueItem, canvas, frame, chart);
        }
        public static IList <ChartValueItemParam> GetChartValueItemFromX(this IList <ChartItem> chartItems, float xPosition, SKRect frame, int maxItems, bool takeClosest = true)
        {
            var items = new List <ChartValueItemParam>();

            if (chartItems?.Any(x => x.IsVisible) != true)
            {
                return(items);
            }

            foreach (var chartEntry in chartItems.Where(x => x.Items?.Any() == true && x.IsVisible))
            {
                ChartValueItem item = null;

                if (!takeClosest)
                {
                    // Create a bound and get item inside this bound
                    foreach (var valueItem in chartEntry.Items)
                    {
                        SKRect rect = new SKRect((xPosition - (frame.GetItemWidth(maxItems) / 2)), 0, (xPosition + (frame.GetItemWidth(maxItems) / 2)), frame.Bottom + 2);

                        if (rect.Contains(valueItem.Point))
                        {
                            item = valueItem;
                        }
                    }
                }
                else
                {
                    // Order list and takes the first that's lower then X value
                    item = chartEntry.Items.OrderByDescending(c => c.Point.X).FirstOrDefault(c => c.Point.X <= xPosition);
                }

                // No item found so check if we touched left of the frame
                if (item == null)
                {
                    item = chartEntry.Items.FirstOrDefault();

                    if ((xPosition <= frame.Left && item.Point.X == frame.Left))
                    {
                        items.Add(new ChartValueItemParam(item, null, chartEntry));
                    }

                    continue;
                }

                // Get the index of the found item
                int index = chartEntry.Items.IndexOf(item);

                // It's the last item in the list so add just the this entry
                if (index + 1 >= chartEntry.Items.Count)
                {
                    if ((xPosition >= frame.Right && item.Point.X == frame.Right) || item.Point.X >= (xPosition - (frame.GetItemWidth(maxItems) / 2)))
                    {
                        items.Add(new ChartValueItemParam(item, null, chartEntry));
                    }

                    continue;
                }

                // Takes the next item in the list
                var nextItem = chartEntry.Items[index + 1];

                if (item != null)
                {
                    // Add current item, next item and parents line color
                    items.Add(new ChartValueItemParam(item, nextItem, chartEntry));
                }
            }

            return(items);
        }
Esempio n. 8
0
        private void DrawBars(SKCanvas canvas, SKRect frame, SKRect chart)
        {
            var itemWidth = (MaxItems >= 12 ? chart.GetItemWidth(MaxItems) : chart.GetItemWidth(12)) / 2;
            var count     = ChartEntries.Count(x => x.IsVisible);

            // Regular bar width
            var barWidth = (itemWidth / count) - 10;

            // Selected bar width
            var selectedValueItems = ChartEntries.GetChartValueItemFromX(chart.GetInsideXValue(TouchedPoint.X), chart, MaxItems, false);
            var selectedTags       = selectedValueItems?.Select(x => x.ChartValueItem.Tag);

            int index = 0;

            foreach (var item in ChartEntries.Where(x => x.IsVisible))
            {
                foreach (var valueItem in item.Items.Where(x => selectedTags?.Contains(x.Tag) != true))
                {
                    // Draw not selected bars //

                    canvas.DrawBar(
                        valueItem.Point.X,
                        valueItem.Point.Y,
                        chart.Bottom,
                        barWidth,
                        BarMargin,
                        count,
                        index,
                        IsSliderVisible ? item.Color.ToSKColor().AsTransparency() : item.Color.ToSKColor(),
                        item.UseDashedEffect);
                }

                index++;
            }

            if (!IsSliderVisible)
            {
                return;
            }

            count    = selectedValueItems?.Count() ?? 1;
            barWidth = (itemWidth / selectedValueItems?.Count() ?? 1) + 10;

            index = 0;

            foreach (var item in ChartEntries.Where(x => x.IsVisible))
            {
                var valueItems = item.Items.Where(x => selectedTags?.Contains(x.Tag) == true);

                if (valueItems?.Any() != true)
                {
                    continue;
                }

                foreach (var valueItem in valueItems)
                {
                    canvas.DrawBar(
                        valueItem.Point.X,
                        valueItem.Point.Y,
                        chart.Bottom,
                        barWidth,
                        BarMargin,
                        count,
                        index,
                        item.Color.ToSKColor(),
                        item.UseDashedEffect);

                    string text = Math.Round(double.Parse(valueItem.Value.ToString()), 0, MidpointRounding.AwayFromZero).ToString() + " " + this.VerticalUnit;

                    canvas.DrawSliderValue(
                        text,
                        frame.GetInsideXValue(valueItem.Point.X),
                        frame.Top,
                        SliderDetailTextSize,
                        SKColors.White,
                        item.Color.ToSKColor(),
                        SliderDetailPadding,
                        SliderDetailMargin,
                        MaxValue + " " + this.VerticalUnit,
                        selectedValueItems.Count,
                        index,
                        SliderDetailOrientation,
                        frame,
                        item.UseDashedEffect);
                }

                index++;
            }


            float hintX = selectedValueItems?.FirstOrDefault()?.ChartValueItem?.Point.X ?? 0;
            float hintY = selectedValueItems?.OrderByDescending(x => x.ChartValueItem.Point.Y)?.FirstOrDefault()?.ChartValueItem?.Point.Y ?? 0;

            if (hintX != 0 && hintY != 0)
            {
                DrawDragHintGraphic(
                    canvas,
                    hintX,
                    hintY + ((frame.Bottom - hintY) / 2),
                    (barWidth * count),
                    frame);
            }
        }