unit LinkedDashboardForm; // A form created in code that links KPI, chart and grid widgets of a // TAtlasDashboard to one TAtlasTable. A region filter, a new row and a saved // layout each refresh every widget from the same snapshot. interface uses System.Classes, Vcl.Forms, Vcl.Controls, Vcl.StdCtrls, Vcl.ExtCtrls, Atlas.Data, Atlas.Dashboard; type TLinkedDashboardForm = class(TForm) private FSource: TAtlasTable; FDashboard: TAtlasDashboard; FRegion: TComboBox; FStatus: TLabel; FLayoutFile: string; procedure RegionChanged(Sender: TObject); procedure AddSaleClick(Sender: TObject); procedure SaveLayoutClick(Sender: TObject); procedure LoadLayoutClick(Sender: TObject); procedure ShowStatus(const Note: string = ''); public constructor Create(AOwner: TComponent); override; property Dashboard: TAtlasDashboard read FDashboard; end; function SalesTable(Owner: TComponent): TAtlasTable; implementation uses System.SysUtils, System.IOUtils, Vcl.Graphics, Atlas.Analytics; function SalesTable(Owner: TComponent): TAtlasTable; begin Result := TAtlasTable.Create(Owner); Result.AddColumn('Region'); Result.AddColumn('Product'); Result.AddColumn('Revenue', ackNumber); Result.AddColumn('Units', ackNumber); Result.AddColumn('Booked', ackDate); Result.ImportCSV( 'Region,Product,Revenue,Units,Booked' + sLineBreak + 'East,Desktop,18000,12,2026-09-01' + sLineBreak + 'West,Desktop,22500,15,2026-09-02' + sLineBreak + 'East,Service,6400,8,2026-09-03' + sLineBreak + 'North,Desktop,12000,8,2026-09-04' + sLineBreak + 'West,Service,9600,12,2026-09-05' + sLineBreak + 'North,Service,4800,6,2026-09-06'); end; constructor TLinkedDashboardForm.Create(AOwner: TComponent); var Header: TPanel; function AddButton(Left: Integer; const Caption: string; OnClick: TNotifyEvent): TButton; begin Result := TButton.Create(Self); Result.Parent := Header; Result.SetBounds(Left, 13, 110, 30); Result.Caption := Caption; Result.OnClick := OnClick; end; begin inherited CreateNew(AOwner); Caption := 'Atlas Analytics: linked dashboard'; Width := 1200; Height := 860; Position := poScreenCenter; Font.Name := 'Segoe UI'; Font.Size := 10; FLayoutFile := TPath.Combine(TPath.GetDirectoryName(ParamStr(0)), 'dashboard-layout.json'); Header := TPanel.Create(Self); Header.Parent := Self; Header.Align := alTop; Header.Height := 56; Header.BevelOuter := bvNone; Header.Color := $003D2C1E; Header.ParentBackground := False; FRegion := TComboBox.Create(Self); FRegion.Parent := Header; FRegion.SetBounds(16, 14, 150, 28); FRegion.Style := csDropDownList; FRegion.Items.Add('All regions'); FRegion.Items.Add('East'); FRegion.Items.Add('West'); FRegion.Items.Add('North'); FRegion.ItemIndex := 0; FRegion.OnChange := RegionChanged; AddButton(182, 'Add a sale', AddSaleClick); AddButton(300, 'Save layout', SaveLayoutClick); AddButton(418, 'Load layout', LoadLayoutClick); FStatus := TLabel.Create(Self); FStatus.Parent := Header; FStatus.SetBounds(548, 18, 630, 22); FStatus.AutoSize := False; FStatus.Font.Color := clWhite; // The table is owned by the form; the dashboard only listens to it. FSource := SalesTable(Self); FDashboard := TAtlasDashboard.Create(Self); FDashboard.Parent := Self; FDashboard.Align := alClient; FDashboard.Source := FSource; FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awKPI, 'Revenue', 'Revenue')); FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awKPI, 'Average sale', 'Revenue', amAverage)); FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awKPI, 'Orders', '', amCount)); FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awChart, 'Revenue by region', 'Revenue', amSum, 'Region')); FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awChart, 'Units by product', 'Units', amSum, 'Product')); FDashboard.AddWidget(TAtlasWidgetDefinition.Create(awGrid, 'Sales detail', '')); ShowStatus; end; procedure TLinkedDashboardForm.RegionChanged(Sender: TObject); begin // SetFilters rebuilds every widget from one filtered snapshot. The source // table keeps its own filter and sort; a bad filter raises and leaves the // previous filters in place. if FRegion.ItemIndex > 0 then FDashboard.SetFilters([TAtlasFilter.Create('Region', FRegion.Text)]) else FDashboard.SetFilters([]); ShowStatus; end; procedure TLinkedDashboardForm.AddSaleClick(Sender: TObject); begin // The dashboard listens to the table, so every widget updates by itself. FSource.AddRow(['West', 'Service', '1500', '2', '2026-09-07']); ShowStatus('Added a West/Service sale of 1500'); end; procedure TLinkedDashboardForm.SaveLayoutClick(Sender: TObject); begin // ToJSON persists widget definitions and dashboard filters, not the data. TFile.WriteAllText(FLayoutFile, FDashboard.ToJSON, TEncoding.UTF8); ShowStatus('Layout saved to ' + FLayoutFile); end; procedure TLinkedDashboardForm.LoadLayoutClick(Sender: TObject); begin if not FileExists(FLayoutFile) then begin ShowStatus('Save a layout first'); Exit; end; // LoadJSON validates every widget against the current source before it // replaces anything; an invalid file leaves the current widgets in place. FDashboard.LoadJSON(TFile.ReadAllText(FLayoutFile, TEncoding.UTF8)); ShowStatus('Layout loaded from ' + FLayoutFile); end; procedure TLinkedDashboardForm.ShowStatus(const Note: string); var Text: string; Widget: TAtlasDashboardWidget; I: Integer; begin Text := Format('%d source rows, %d widgets', [FSource.RowCount, FDashboard.WidgetCount]); for I := 0 to FDashboard.WidgetCount - 1 do begin Widget := FDashboard.Widgets[I]; if (Widget.Definition.Kind = awKPI) and Assigned(Widget.Data) then Text := Text + Format(', %s %s', [Widget.Definition.Title, Widget.Data.Cell(0, 0)]); end; if FDashboard.LastError <> '' then Text := 'Last error: ' + FDashboard.LastError else if Note <> '' then Text := Note + ' (' + Text + ')'; FStatus.Caption := Text; end; end.