160 lines
5.8 KiB
C#
160 lines
5.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace EasyChart
|
|
{
|
|
public sealed class DefaultChartLayoutModel : IChartLayoutModel
|
|
{
|
|
public AxisId GetMappedXAxisId(ChartData data)
|
|
{
|
|
return data != null && data.Cartesian != null ? data.Cartesian.xAxisId : AxisId.XBottom;
|
|
}
|
|
|
|
public AxisId GetMappedYAxisId(ChartData data)
|
|
{
|
|
return data != null && data.Cartesian != null ? data.Cartesian.yAxisId : AxisId.YLeft;
|
|
}
|
|
|
|
public bool IsCartesianTransposed(ChartData data, Func<AxisId, AxisConfig> getAxis)
|
|
{
|
|
if (data == null || getAxis == null) return false;
|
|
|
|
AxisId xAxisId = GetMappedXAxisId(data);
|
|
AxisId yAxisId = GetMappedYAxisId(data);
|
|
|
|
var xAxis = getAxis(xAxisId);
|
|
var yAxis = getAxis(yAxisId);
|
|
|
|
var xDim = xAxis != null ? xAxis.axisType : AxisType.Category;
|
|
var yDim = yAxis != null ? yAxis.axisType : AxisType.Value;
|
|
return xDim == AxisType.Value && yDim == AxisType.Category;
|
|
}
|
|
|
|
public ChartRangeResult CalculateRange(ChartData data, Func<AxisId, AxisConfig> getAxis, int categoryWindowStartX, int categoryWindowStartY)
|
|
{
|
|
AxisId xAxisId = GetMappedXAxisId(data);
|
|
AxisId yAxisId = GetMappedYAxisId(data);
|
|
|
|
AxisConfig xAxisCfg = getAxis != null ? getAxis(xAxisId) : null;
|
|
AxisConfig yAxisCfg = getAxis != null ? getAxis(yAxisId) : null;
|
|
|
|
var xCategoryLabels = xAxisCfg != null ? xAxisCfg.labels : null;
|
|
var yCategoryLabels = yAxisCfg != null ? yAxisCfg.labels : null;
|
|
|
|
bool transposed = IsCartesianTransposed(data, getAxis);
|
|
|
|
return ChartRangeCalculator.Calculate(
|
|
data,
|
|
transposed,
|
|
xAxisCfg,
|
|
yAxisCfg,
|
|
xCategoryLabels,
|
|
yCategoryLabels,
|
|
categoryWindowStartX,
|
|
categoryWindowStartY);
|
|
}
|
|
|
|
public void UpdateCategoryAxisRangeOnly(
|
|
ChartData data,
|
|
Func<AxisId, AxisConfig> getAxis,
|
|
ref int categoryWindowStartX,
|
|
ref int categoryWindowStartY,
|
|
ref float xMin,
|
|
ref float xMax,
|
|
ref float yMin,
|
|
ref float yMax)
|
|
{
|
|
if (data == null) return;
|
|
if (data.CoordinateSystem != CoordinateSystemType.Cartesian2D) return;
|
|
if (getAxis == null) return;
|
|
|
|
var xAxisId = GetMappedXAxisId(data);
|
|
var yAxisId = GetMappedYAxisId(data);
|
|
var xAxis = getAxis(xAxisId);
|
|
var yAxis = getAxis(yAxisId);
|
|
|
|
if (xAxis != null && xAxis.axisType == AxisType.Category && xAxis.labels != null && xAxis.labels.Count > 0)
|
|
{
|
|
int count = xAxis.labels.Count;
|
|
int visible = ClampCategoryVisibleCount(xAxis, count);
|
|
if (count <= visible)
|
|
{
|
|
categoryWindowStartX = 0;
|
|
xMin = 0;
|
|
xMax = count > 1 ? count - 1 : 1;
|
|
}
|
|
else
|
|
{
|
|
categoryWindowStartX = Mathf.Clamp(categoryWindowStartX, 0, count - 1);
|
|
xMin = categoryWindowStartX;
|
|
xMax = categoryWindowStartX + (visible - 1);
|
|
}
|
|
}
|
|
|
|
if (yAxis != null && yAxis.axisType == AxisType.Category && yAxis.labels != null && yAxis.labels.Count > 0)
|
|
{
|
|
int count = yAxis.labels.Count;
|
|
int visible = ClampCategoryVisibleCount(yAxis, count);
|
|
if (count <= visible)
|
|
{
|
|
categoryWindowStartY = 0;
|
|
yMin = 0;
|
|
yMax = count > 1 ? count - 1 : 1;
|
|
}
|
|
else
|
|
{
|
|
categoryWindowStartY = Mathf.Clamp(categoryWindowStartY, 0, count - 1);
|
|
yMin = categoryWindowStartY;
|
|
yMax = categoryWindowStartY + (visible - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
public List<string> GetCategoryLabelsWindowed(AxisId id, AxisConfig axis, int windowStart, List<string> buffer)
|
|
{
|
|
if (axis == null || axis.axisType != AxisType.Category) return null;
|
|
var labels = axis.labels;
|
|
if (labels == null || labels.Count == 0) return labels;
|
|
|
|
int visible = ClampCategoryVisibleCount(axis, labels.Count);
|
|
if (visible <= 0 || labels.Count <= visible) return labels;
|
|
|
|
return BuildWindowedCategoryLabels(labels, windowStart, visible, buffer);
|
|
}
|
|
|
|
private static int ClampCategoryVisibleCount(AxisConfig axis, int labelsCount)
|
|
{
|
|
if (labelsCount <= 0) return 0;
|
|
// When autoTicks is true, use all labels
|
|
if (axis != null && axis.autoTicks) return labelsCount;
|
|
int v = axis != null ? axis.splitCount : 0;
|
|
if (v < 2) v = 2;
|
|
if (v > labelsCount) v = labelsCount;
|
|
return v;
|
|
}
|
|
|
|
private static List<string> BuildWindowedCategoryLabels(List<string> all, int start, int visible, List<string> buffer)
|
|
{
|
|
if (all == null || all.Count == 0) return all;
|
|
if (visible <= 0) return all;
|
|
if (visible >= all.Count) return all;
|
|
if (buffer == null)
|
|
{
|
|
buffer = new List<string>(visible);
|
|
}
|
|
|
|
if (start < 0) start = 0;
|
|
if (start >= all.Count) start = all.Count - 1;
|
|
|
|
buffer.Clear();
|
|
for (int i = 0; i < visible; i++)
|
|
{
|
|
int idx = (start + i) % all.Count;
|
|
buffer.Add(all[idx]);
|
|
}
|
|
return buffer;
|
|
}
|
|
}
|
|
}
|