Files

264 lines
8.8 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine.UIElements;
namespace EasyChart
{
internal sealed class ChartKernel
{
private readonly ChartElement _owner;
private readonly ChartRefreshPipeline _pipeline;
private readonly ChartRefreshCallbacks _refreshCallbacks;
private readonly List<IChartModule> _modules = new List<IChartModule>(8);
private readonly List<IChartPointerModule> _pointerModules = new List<IChartPointerModule>(2);
private readonly List<IChartGeometryModule> _geometryModules = new List<IChartGeometryModule>(2);
private readonly List<IChartRefreshStageModule> _refreshStageModules = new List<IChartRefreshStageModule>(2);
private bool _modulesInstalled;
private bool _attached;
public ChartKernel(ChartElement owner, ChartRefreshPipeline pipeline, ChartRefreshCallbacks refreshCallbacks)
{
_owner = owner;
_pipeline = pipeline;
_refreshCallbacks = refreshCallbacks;
}
public void ExecuteRebuildRenderers()
{
for (int i = 0; i < _refreshStageModules.Count; i++)
{
_refreshStageModules[i]?.OnRebuildRenderers();
}
_refreshCallbacks.RebuildRenderers?.Invoke();
}
public void ExecuteCalculateRange()
{
for (int i = 0; i < _refreshStageModules.Count; i++)
{
_refreshStageModules[i]?.OnCalculateRange();
}
_refreshCallbacks.CalculateRange?.Invoke();
}
public void ExecuteRefreshAxisLayer()
{
for (int i = 0; i < _refreshStageModules.Count; i++)
{
_refreshStageModules[i]?.OnRefreshAxisLayer();
}
_refreshCallbacks.RefreshAxisLayer?.Invoke();
}
public void ExecuteRefreshGridLayer()
{
for (int i = 0; i < _refreshStageModules.Count; i++)
{
_refreshStageModules[i]?.OnRefreshGridLayer();
}
_refreshCallbacks.RefreshGridLayer?.Invoke();
}
public void ExecuteRefreshSeriesRenderers()
{
for (int i = 0; i < _refreshStageModules.Count; i++)
{
_refreshStageModules[i]?.OnRefreshSeriesRenderers();
}
_refreshCallbacks.RefreshSeriesRenderers?.Invoke();
}
public void ExecuteRefreshLayersNoLegend()
{
for (int i = 0; i < _refreshStageModules.Count; i++)
{
_refreshStageModules[i]?.OnRefreshLayersNoLegend();
}
_refreshCallbacks.RefreshLayersNoLegend?.Invoke();
}
public void ExecuteRefreshLegendDeferred()
{
for (int i = 0; i < _refreshStageModules.Count; i++)
{
_refreshStageModules[i]?.OnRefreshLegendDeferred();
}
_refreshCallbacks.RefreshLegendDeferred?.Invoke();
}
public void ExecutePlayAnimation()
{
for (int i = 0; i < _refreshStageModules.Count; i++)
{
_refreshStageModules[i]?.OnPlayAnimation();
}
_refreshCallbacks.PlayAnimation?.Invoke();
}
public void InstallDefaultModules()
{
if (_modulesInstalled) return;
_modulesInstalled = true;
AddModule(new ChartCategoryScrollModule());
AddModule(new ChartTooltipModule());
AddModule(new ChartPointerInteractionModule());
AddModule(new ChartGeometryModule());
AddModule(new ChartBackgroundModule());
AddModule(new ChartRefreshStagesModule());
}
public void AddModule(IChartModule module)
{
if (module == null) return;
_modules.Add(module);
if (module is IChartPointerModule pm) _pointerModules.Add(pm);
if (module is IChartGeometryModule gm) _geometryModules.Add(gm);
if (module is IChartRefreshStageModule rm) _refreshStageModules.Add(rm);
if (_attached) module.Bind(_owner, this);
}
public void OnAttachToPanel()
{
if (_attached) return;
_attached = true;
for (int i = 0; i < _modules.Count; i++)
{
_modules[i]?.Bind(_owner, this);
}
}
public void OnDetachFromPanel()
{
if (!_attached) return;
_attached = false;
for (int i = 0; i < _modules.Count; i++)
{
_modules[i]?.Unbind();
}
}
public void OnPointerMove(PointerMoveEvent evt)
{
for (int i = 0; i < _pointerModules.Count; i++)
{
_pointerModules[i]?.OnPointerMove(evt);
}
}
public void OnPointerLeave(PointerLeaveEvent evt)
{
for (int i = 0; i < _pointerModules.Count; i++)
{
_pointerModules[i]?.OnPointerLeave(evt);
}
}
public void OnGeometryChanged(GeometryChangedEvent evt)
{
for (int i = 0; i < _geometryModules.Count; i++)
{
_geometryModules[i]?.OnGeometryChanged(evt);
}
}
public void Invalidate(ChartDirtyReason reason, bool immediate)
{
if (_owner == null) return;
if (_pipeline == null) return;
var stage = MapToStages(reason);
if (stage == ChartRefreshStage.None) return;
if (immediate) _pipeline.RequestImmediate(stage);
else _pipeline.Request(stage);
}
public void Queue(ChartDirtyReason reason)
{
if (_owner == null) return;
if (_pipeline == null) return;
var stage = MapToStages(reason);
if (stage == ChartRefreshStage.None) return;
QueueStages(stage);
}
public void QueueStages(ChartRefreshStage stage)
{
if (_owner == null) return;
if (_pipeline == null) return;
if (stage == ChartRefreshStage.None) return;
_pipeline.Add(stage);
}
private ChartRefreshStage MapToStages(ChartDirtyReason reason)
{
if (reason == ChartDirtyReason.None) return ChartRefreshStage.None;
ChartRefreshStage stage = ChartRefreshStage.None;
if ((reason & ChartDirtyReason.DataAssigned) != 0)
stage |= ChartRefreshStage.RebuildRenderers | ChartRefreshStage.CalculateRange | ChartRefreshStage.LayersNoLegend | ChartRefreshStage.Legend;
if ((reason & ChartDirtyReason.DataMutated) != 0)
stage |= ChartRefreshStage.CalculateRange | ChartRefreshStage.LayersNoLegend | ChartRefreshStage.Legend;
if ((reason & ChartDirtyReason.GeometryChanged) != 0)
stage |= ChartRefreshStage.SeriesRenderers | ChartRefreshStage.Legend;
if ((reason & ChartDirtyReason.CategoryWindowChanged) != 0)
stage |= ChartRefreshStage.AxisLayer | ChartRefreshStage.Grid | ChartRefreshStage.SeriesRenderers;
if ((reason & ChartDirtyReason.LegendTogglePieSlice) != 0)
stage |= ChartRefreshStage.SeriesRenderers | ChartRefreshStage.Legend;
if ((reason & ChartDirtyReason.LegendToggleSeriesVisibility) != 0)
stage |= ChartRefreshStage.RebuildRenderers | ChartRefreshStage.CalculateRange | ChartRefreshStage.AxisLayer | ChartRefreshStage.Grid | ChartRefreshStage.SeriesRenderers | ChartRefreshStage.Legend;
return stage;
}
public void InvalidateDataAssignedWithAnimation(ChartData data, bool immediate)
{
var stage = MapToStages(ChartDirtyReason.DataAssigned);
if (data != null && data.animationDuration > 0f) stage |= ChartRefreshStage.PlayAnimation;
if (immediate) _pipeline.RequestImmediate(stage);
else _pipeline.Request(stage);
}
public void InvalidateDataMutated(bool rebuildRenderers, bool playAnimation, bool immediate)
{
var stage = MapToStages(rebuildRenderers ? ChartDirtyReason.DataAssigned : ChartDirtyReason.DataMutated);
if (playAnimation) stage |= ChartRefreshStage.PlayAnimation;
if (immediate) _pipeline.RequestImmediate(stage);
else _pipeline.Request(stage);
}
public void InvalidateGeometryChanged(bool showCartesian, bool immediate)
{
var stage = MapToStages(ChartDirtyReason.GeometryChanged);
if (showCartesian) stage |= ChartRefreshStage.AxisLayer | ChartRefreshStage.Grid;
if (immediate) _pipeline.RequestImmediate(stage);
else _pipeline.Request(stage);
}
}
}