Chart Architecture
Complete BeepChart internal architecture -- 5 partial files, 20 helper classes, painter pipeline (IChartPainter/IChartSeriesPainter/IChartAxisPainter/IChartLegendPainter), viewport control, and performance optimization for large datasets
Table of Contents
Overview
Namespace: TheTechIdea.Beep.Winform.Controls.Charts
Assembly: TheTechIdea.Beep.Winform.Controls.dll
Inheritance: BaseControl
BeepChart is a full-featured charting control supporting 5 chart types (Bar, Line, Pie, Area, Bubble) with interactive viewport control (zoom/pan/auto-scale), performance optimization for datasets exceeding 10,000 points, real-time streaming, trackball with crosshair and multi-series tooltips, and 18 events with dedicated EventArgs classes. It is decomposed across 5 partial files with ~20 helper classes organized into five subsystems.
Partial File Layout (5 Files)
| File | Lines | Content |
|---|---|---|
| BeepChart.cs | ~80 | Partial class declaration. Constructor calls InitializeDefaultSettings(), InitializeDesignTimeSampleData(), InitializePainter(). DefaultSize 400x300. Defines 4 enums: ChartSelectionMode, ChartVisualPreset, ChartSeriesFillPattern, ChartSurfaceStyle. |
| BeepChart.Properties.cs | ~250 | 80+ public properties across categories: Title (ShowTitle, ChartTitle, ChartValue, ChartSubtitle, title fonts/colors), Data (DataSeries, LegendLabels, ChartDefaultSeriesColors), Axis (BottomAxisType, LeftAxisType, X/YAxisTitle, X/YLabelAngle, X/YTimeGranularity), Viewport (ViewportXMin/Max, ViewportYMin/Max, CanResetViewport), Interaction (EnableMouseWheelZoom, MouseWheelZoomStepPercent, EnableMouseDragPan, EnableTrackball, TrackballShowCrosshair, EnablePointSelection, SelectionMode), Performance (EnablePerformanceMode, LargeDatasetThreshold, EnablePointCulling, EnableVertexSimplification, SimplificationTolerance), Appearance (ChartDrawingRect, ShowLegend, ChartType, LegendPlacement, SurfaceStyle, AccentColor, Stacked, SmoothLines, ShowMarkers), Theme colors (ChartBackColor, ChartLineColor, ChartFillColor, ChartAxisColor, ChartTitleColor, ChartTextColor, ChartLegendBackColor, ChartLegendTextColor, ChartLegendShapeColor, ChartGridLineColor), Streaming (EnableRealTimeStreaming, StreamRenderThrottleMs, MaxStreamPointsPerSeries). |
| BeepChart.Methods.cs | ~200 | 30+ methods: ResetViewport(), AutoScaleViewport(), StartAnimation(int durationMs), ApplyVisualPreset(ChartVisualPreset), FlushStreamingRender(), AppendDataPoint(int seriesIndex, ChartDataPoint, bool flush), AppendDataPoints(int seriesIndex, IEnumerable, bool flush), GetOptimizedPointsForSeries(int), GetCulledPointsForViewport(List), ClearSimplificationCache(), GetPerformanceReport(), GetTotalPointCount(), IsLargeDataset(), ConvertXValue(ChartDataPoint), ConvertYValue(ChartDataPoint). |
| BeepChart.Events.cs | ~250 | 18 events: CustomDrawSeries, InteractiveAreaHit, PointHit, AxisHit, LegendHit, PointHoverChanged, ViewportChanged, TrackballDataCollected, SeriesIsolationChanged, SelectionChanged, ContextMenuRequested, KeyboardFocusChanged, PerformanceOptimized, NonColorStateCommunicationChanged, LabelOptimizationApplied, StreamingDataAppended, IncrementalRenderCompleted. Plus 18 dedicated EventArgs classes (CustomDrawSeriesEventArgs, ChartPointHitEventArgs, ChartAxisHitEventArgs, ChartLegendHitEventArgs, ChartPointHoverChangedEventArgs, ChartViewportChangedEventArgs, ChartTrackballDataCollectedEventArgs with ChartTrackballDataPoint, ChartSelectionChangedEventArgs, etc.). |
| BeepChart.Drawing.cs | ~400 | DrawContent override, Paint(Graphics, Rectangle) method, chart render orchestration, painter integration (IChartPainter), custom draw hooks, hit area registration, Dispose (DataPointToolTip, AnimTimer, StreamRenderTimer). |
Helper Subsystems (20 Classes)
| Subsystem | Files | Role |
|---|---|---|
| Painter Contracts | IChartPainter.cs, IChartSeriesPainter.cs, IChartAxisPainter.cs, IChartLegendPainter.cs | 4 internal interfaces defining swappable rendering components |
| Painter Implementations | CardChartPainter.cs, CartesianAxisPainter.cs, RightSideLegendPainter.cs + 5 series painters | Concrete renderers implementing each interface |
| Series | SeriesPainterFactory.cs + Bar/Line/Pie/Area/Bubble series painters | ChartType-to-painter resolution, 5 series rendering strategies |
| Data | BeepChartDataHelper.cs | Auto-detect axis types (Numeric/Date/Text), convert X/Y values, category mapping |
| Viewport | BeepChartViewportHelper.cs | Auto-scale from data, enforce limits, drawing rect calculation |
| Performance | BeepChartPerformanceHelper.cs | Point culling, decimation, grid density optimization, label interval recommendation, rendering cost estimation |
| Input | ChartInputHelper.cs, ChartPainterBase.cs | Mouse hit testing, trackball crosshair interaction |
| Metrics | ChartPainterMetrics.cs, SeriesRenderOptions.cs | Shared constants, layout padding values, series render configuration class |
Painting Pipeline
DrawContent(Graphics g)
-> Paint(Graphics g, Rectangle bounds)
-> IChartPainter.Initialize(owner, theme)
-> IChartPainter.AdjustLayout(drawingRect, ctx) -> ChartLayout
|-- IChartAxisPainter.AdjustPlotRect(g, axisCtx) -> AxisLayout (48px margins)
-> IChartPainter.DrawBackground(g, ctx)
|-- CardChartPainter: rounded card background + border
|-- IChartAxisPainter.DrawAxes(g, axisCtx) -> X/Y axis lines + titles
|-- IChartAxisPainter.DrawTicks(g, axisCtx) -> numeric | date | text
-> [foreach DataSeries, palette index]:
IChartSeriesPainter.DrawSeries(g, plotRect, data, toX, toY,
xMin, xMax, yMin, yMax, palette, axisColor, textColor, options)
-> IChartLegendPainter.DrawLegend(g, chartRect, series, palette,
font, textColor, backColor, shapeColor, owner, onToggleSeries, ...)
-> IChartPainter.DrawForeground(g, ctx) -> title, subtitle, value
-> IChartPainter.UpdateHitAreas(owner, ctx, notifyAreaHit)Painter Contracts (4 Interfaces)
IChartPainter
Top-level chart painter. Handles layout adjustment, background/foreground, and hit area registration. Concrete implementation: CardChartPainter renders charts as cards with rounded corners, title bars, and value text areas.
internal interface IChartPainter
{
void Initialize(BaseControl owner, IBeepTheme theme);
ChartLayout AdjustLayout(Rectangle drawingRect, ChartLayout ctx);
void DrawBackground(Graphics g, ChartLayout ctx);
void DrawForeground(Graphics g, ChartLayout ctx);
void UpdateHitAreas(BaseControl owner, ChartLayout ctx,
Action<string, Rectangle> notifyAreaHit);
}
// ChartLayout data class:
// DrawingRect, PlotRect, Radius, AccentColor, TitleBottom
IChartSeriesPainter
Responsible for rendering individual chart series (bars, lines, pie slices, etc.). Five concrete implementations returned by SeriesPainterFactory.
internal interface IChartSeriesPainter
{
void Initialize(BaseControl owner);
void DrawSeries(Graphics g, Rectangle plotRect,
List<ChartDataSeries> data,
Func<ChartDataPoint, object> toX,
Func<ChartDataPoint, object> toY,
float xMin, float xMax, float yMin, float yMax,
List<Color> palette, Color axisColor, Color textColor,
SeriesRenderOptions options);
void UpdateHitAreas(BaseControl owner, Rectangle plotRect,
List<ChartDataSeries> data,
Func<ChartDataPoint, PointF> toScreen,
Action<string, Rectangle> notifyAreaHit);
}
IChartAxisPainter
Renders coordinate axes with intelligent tick calculation. Concrete implementation: CartesianAxisPainter (internal sealed). AxisLayout data class carries Bounds, PlotRect, BottomAxisType, LeftAxisType, XMin/XMax/YMin/YMax, XTitle/YTitle, XLabelAngle/YLabelAngle, AxisColor, GridLineColor, and category/date epoch data.
IChartLegendPainter
Renders a color-coded series reference panel. Concrete implementation: RightSideLegendPainter. Supports series toggle via onToggleSeries(int) callback and LegendPlacement (Right, Bottom, Top, Left). EnableLegendIsolate enables single-series isolation mode.
Series Painters (5 Types)
SeriesPainterFactory.Get(ChartType) resolves the chart type to its painter. LineSeriesPainter is the default fallback.
| ChartType | Painter | Rendering Style |
|---|---|---|
| Bar | BarSeriesPainter | Vertical bars with configurable width (BarWidth=0.8) and padding (BarPadding=0.2). Supports stacked mode and data labels on top. Negative values extend downward. |
| Line | LineSeriesPainter | Connected line segments with optional cubic Bezier smoothing (SmoothLines). Supports point markers: Circle, Square, Diamond, Triangle at configurable size (default 6px). |
| Pie | PieSeriesPainter | Proportional pie/donut slices. Donut mode when InnerRadius > 0. Exploded slice on hover. Hit areas are pie-slice-shaped polygons. |
| Area | AreaSeriesPainter | Filled polygon below each line to baseline. Semi-transparent (FillOpacity=0.3). Stacked mode accumulates vertically. |
| Bubble | BubbleSeriesPainter | Proportional circles at XY coordinates. Circle area (not radius) proportional to Size value. |
Axis & Legend System
CartesianAxisPainter
Implements IChartAxisPainter. Three-phase rendering:
- AdjustPlotRect -- Adds 48px margins on all sides of the chart area
- DrawAxes -- Renders X/Y axis lines and titles (titles drawn rotated)
- DrawTicks -- Dispatches to three sub-renderers based on axis type:
- NumericTicks -- "Nice" step sizes: 1, 2, 5, 10, 20, 50, 100, etc. No unnecessary decimal places.
- DateTicks -- Auto-granularity: < 1h -> minutes, < 24h -> hours, < 30d -> days, < 365d -> months, >= 1y -> years
- TextTicks -- Category-indexed labels from Dictionary<string,int> map, centered in each column
RightSideLegendPainter
Renders a compact color-coded legend on the right side. Shows colored square + series name per entry. Click toggles visibility. Hidden series crossed-out. Supports overflow scrolling. Colors from ChartDefaultSeriesColors palette.
Viewport & Performance
BeepChartViewportHelper (internal static)
| Method | Description |
|---|---|
| AutoScaleViewport(chart) | Scans all DataSeries points, computes min/max X and Y, adds 10% padding |
| EnforceViewportLimits(chart) | Clamps values, prevents inverted ranges (min > max) |
| UpdateChartDrawingRectBase(chart) | Sets private drawing rect with 40px margins via reflection |
BeepChartPerformanceHelper (public static)
| Method | Returns | Description |
|---|---|---|
| CullPointsOutsideViewport(...) | List<ChartDataPoint> | Filters to visible points only (always keeps first + last) |
| DecimatePoints(points, factor) | List<ChartDataPoint> | Reduces by taking every Nth (always includes last) |
| EstimateDecimationFactor(count, target=200) | int | Computes factor to reach target point count |
| OptimizeGridDensity(size, zoom) | int | Recommended grid interval based on dataset + zoom |
| RecommendLabelInterval(size, range%) | int | Skip factor to avoid label overcrowding |
| EstimateRenderingCost(points, pixels) | float | 0.0-1.0 cost estimate (points per pixel ratio) |
| ShouldOptimizePerformance(count, threshold) | bool | True when count exceeds threshold (default 10,000) |
Data Pipeline
BeepChartDataHelper (internal static)
// DetectAxisTypes(chart) -- reads first point of first series:
// float.TryParse -> AxisType.Numeric
// DateTime.TryParse -> AxisType.Date
// else -> AxisType.Text (with Dictionary category map)
// ConvertXValue(chart, point) / ConvertYValue(chart, point):
// Numeric: float.TryParse(value)
// Date: (DateTime.Parse(value) - dateMin).TotalDays
// Text: categoryMap[value] index
SeriesRenderOptions
| Property | Type | Default | Effect |
|---|---|---|---|
| BarWidth | float | 0.8 | Bar fraction of cell width |
| BarPadding | float | 0.2 | Gap between bars |
| ShowDataLabels | bool | false | Value text on bars/slices |
| SmoothLines | bool | false | Cubic Bezier interpolation |
| ShowMarkers | bool | true | Point markers on lines |
| MarkerShape | MarkerStyle | Circle | Circle/Square/Diamond/Triangle |
| MarkerSize | int | 6 | Marker radius in px |
| FillOpacity | float | 0.3 | Area transparency (0-1) |
| InnerRadius | float | 0 | Pie donut hole (0=full pie) |
| Stacked | bool | false | Accumulate bars/areas vertically |
Interaction & Trackball
ChartInputHelper supports:
- Trackball -- Crosshair overlay with multi-series tooltip values. Configurable colors and width.
- MouseWheelZoom -- Ctrl+Wheel zooms in/out (configurable step percent)
- MouseDragPan -- Click-drag pans the viewport (configurable factor)
- KeyboardNavigation -- Arrow keys for pan, +/- for zoom, configurable step percent
- PointHover -- DataPointToolTip on hover with point details
- PointSelection -- Click to select with visual highlight, configurable selection color/marker
- LegendIsolate -- Click legend item to isolate single series. Click again to restore all.
18 dedicated events enable full integration: CustomDrawSeries, InteractiveAreaHit, PointHit, AxisHit, LegendHit, PointHoverChanged, ViewportChanged, TrackballDataCollected, SeriesIsolationChanged, SelectionChanged, ContextMenuRequested, KeyboardFocusChanged, PerformanceOptimized, NonColorStateCommunicationChanged, LabelOptimizationApplied, StreamingDataAppended, IncrementalRenderCompleted.
Key Enums & EventArgs
| Enum | Values |
|---|---|
| ChartSelectionMode | Single, Multiple |
| ChartVisualPreset | Dashboard (compact, embedded), Analytical (full, exploration), HighContrast (accessibility), Print (B&W safe), Presentation (large fonts) |
| ChartSeriesFillPattern | Solid, Horizontal, Vertical, Diagonal, BackDiagonal, Cross, DiagonalCross, Dots |
| ChartSurfaceStyle | Classic (flat), Card (rounded, shadow), Outline (border-only), Glass (transparency) |
18 EventArgs classes in BeepChart.Events.cs: CustomDrawSeriesEventArgs (Graphics, series index), ChartPointHitEventArgs (series, index, point, screen location), ChartAxisHitEventArgs (axis, value, label), ChartLegendHitEventArgs (series index, toggle), ChartPointHoverChangedEventArgs (old/new point), ChartViewportChangedEventArgs (xMin/xMax/yMin/yMax), ChartTrackballDataCollectedEventArgs (screen point, data points list with ChartTrackballDataPoint), ChartSelectionChangedEventArgs (selected points list), ChartPerformanceOptimizedEventArgs (before/after point counts), ChartStreamingDataAppendedEventArgs (series index, new point count), ChartIncrementalRenderCompletedEventArgs (render time).
Code Examples
Basic Bar Chart
var chart = new BeepChart();
chart.ChartType = ChartType.Bar;
chart.ChartTitle = "Quarterly Revenue";
chart.ShowLegend = true;
chart.LegendPlacement = LegendPlacement.Right;
chart.DataSeries.Add(new ChartDataSeries
{
SeriesName = "Q1 Revenue",
DataPoints = new List<ChartDataPoint>
{
new ChartDataPoint { X = "Product A", Y = "1200" },
new ChartDataPoint { X = "Product B", Y = "800" },
new ChartDataPoint { X = "Product C", Y = "1500" }
}
});
Large Dataset with Performance Mode
chart.EnablePerformanceMode = true;
chart.LargeDatasetThreshold = 50000;
chart.EnablePointCulling = true;
chart.EnableVertexSimplification = true;
chart.ResetViewport();
if (BeepChartPerformanceHelper.ShouldOptimizePerformance(
chart.GetTotalPointCount(), chart.LargeDatasetThreshold))
{
float cost = BeepChartPerformanceHelper.EstimateRenderingCost(
chart.GetTotalPointCount(), chart.Width);
Console.WriteLine($"Rendering cost: {cost:P0}");
}
Real-Time Streaming
chart.EnableRealTimeStreaming = true;
chart.StreamRenderThrottleMs = 50; // render batch interval
chart.MaxStreamPointsPerSeries = 1000; // rolling window
chart.StreamingDataAppended += (s, e) =>
Console.WriteLine($"Stream: {e.NewPointCount} points");
chart.AppendDataPoint(0, new ChartDataPoint
{ X = DateTime.Now.ToString("o"), Y = sensorValue.ToString() });
Interactive Zoom/Pan with Trackball
chart.EnableMouseWheelZoom = true;
chart.EnableMouseDragPan = true;
chart.EnableTrackball = true;
chart.TrackballShowCrosshair = true;
chart.TrackballShowMultiSeriesValues = true;
chart.ViewportChanged += (s, e) =>
Console.WriteLine($"Viewport: {e.XMin}-{e.XMax}, {e.YMin}-{e.YMax}");