YOUSEFUL / DELPHI / SAMPLE PROJECTS
Application shell
A VCL program that builds a small application shell entirely in code with the layout and display components of Atlas VCL:
TAtlasWorkspacewith three panes: a navigation pane on the left, a command pane on top and a client pane for the content.TAtlasCommandBarwith a Home tab (groups Pages and Sales) and a View tab (groups Appearance and Layout), each button bound to an ordinaryTAction.TAtlasNavigationandTAtlasTileBoardsharing the same page actions as the command bar, so a list item, a tile and a button all switch the page.- A Sales page with a two-series
TAtlasChart: six months to start with, a missing value in April for West (the line breaks there), an Add month command that disables itself after December, and a Bars / lines toggle. - A Gauges page with three
TAtlasGaugecontrols (one custom range with its own thresholds) and a track bar that moves the first one. TAtlasThemeron the workspace, with a Next theme command that cycles through the eleven palettes and shows the theme name in the title bar.- A Float navigation command that moves the navigation pane into a tool window
and back, and layout persistence: the layout is saved to
shell-layout.jsonnext to the executable when the window closes and restored the next time it is first activated.
This is the project of the tutorial in Atlas VCL interface components.
Build and run
Open ApplicationShell.dpr in Delphi 13; the IDE creates the project file. Add the Atlas VCL src folder and the shared folder to the project's search path, then build and run for Win32 or Win64. No packages need to be installed. The shared folder is part of the sample download. It holds Atlas.TestVcl.pas, which the optional snapshot mode uses to save a picture of the window.
The program is interactive. To look at it without clicking, pass a PNG file name, and optionally a page number (0 Home, 1 Sales, 2 Gauges):
ApplicationShell.exe shell.png 1The window is then painted off screen, saved and closed. In this mode the layout file is not written (the window is never closed by the user), but a file left by an earlier interactive run is still restored.
Expected output
A 1000 × 680 window. Across the top, the command bar with the Home tab open: a Pages group with Home, Sales and Gauges buttons and a Sales group with Add month and Bars / lines. Below it, on the left, the navigation list (Home, Sales, Gauges) and, on the right, three dark blue tiles with the same captions. The Harbor theme gives white surfaces and dark text.
- Sales shows "Regional sales (thousands)" with East and West lines for January to June; West has a gap at month 4. The X axis shows numbers because a line chart does not use point captions. Bars / lines switches to grouped bars labelled Jan, Feb, ... from the East captions. Add month adds one month per click; after December the button is disabled.
- Gauges shows Queue depth at 120 (green), CPU % at 62 (green) and Disk % at 91 (red). Dragging the track bar past 300 turns the queue gauge amber and past 450 red.
- View / Next theme recolours the workspace. Index 10, Midnight, is the dark palette; native buttons and tab strips keep the Windows look.
- View / Float navigation opens the navigation list in a tool window titled "Navigation". Closing that window, or the command again, docks it back. Close the program while it floats and it opens floating next time.
What to change first
- Replace the Sales series data with your own values. Keep the X values increasing; give every point of the first series a caption if you want the bar chart to label its categories.
- Add a page: call
NewPageafter the Gauges page and put your control on it. The loop that follows creates a page action for every page and adds it to the navigation, the tiles and the command bar. - Put a fourth pane on the right with
AddPane('details', 'Details', alRight, 240). Right and bottom panes get a working splitter fromAddPane, but lose it afterMovePaneorLoadLayout(see Troubleshooting in the guide). If a layout file from an older version exists,LoadLayoutrejects it because it does not describe the new pane; the program then keeps the default layout. - Start with another palette: set
FThemer.ThemeIndexafter assigningRoot.
Project files
- ApplicationShell.dpr
- README.md
- Shell.MainForm.pas
- shared/Atlas.TestVcl.pas snapshot helper, in the download
The ZIP contains every sample project with its README. See getting started for the search path to add.
Source
ApplicationShell.dpr
program ApplicationShell;
// Atlas VCL application shell: workspace, navigation, command bar, tiles,
// chart, gauges and themes. Pass a file name to save a PNG of the window
// instead of running it interactively; an optional second argument selects
// the page shown in the image (0 Home, 1 Sales, 2 Gauges).
uses
System.SysUtils,
Vcl.Forms,
Atlas.TestVcl,
Shell.MainForm in 'Shell.MainForm.pas';
var
Form: TShellForm;
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TShellForm, Form);
if ParamCount > 0 then
begin
if ParamCount > 1 then Form.SelectPage(StrToInt(ParamStr(2)));
SaveFormImage(Form, ParamStr(1));
end
else
Application.Run;
end.
Shell.MainForm.pas
unit Shell.MainForm;
// Main form of the Atlas VCL application shell: a workspace with a navigation
// pane, a command bar and a content pane, themed by TAtlasThemer.
interface
uses
System.Classes, Vcl.Forms, Vcl.Controls, Vcl.ComCtrls, Vcl.ActnList,
Atlas.Layout, Atlas.Charts, Atlas.Gauges, Atlas.Themes;
type
TShellForm = class(TForm)
private
FWorkspace: TAtlasWorkspace;
FCommands: TAtlasCommandBar;
FNavigation: TAtlasNavigation;
FTiles: TAtlasTileBoard;
FPages: TPageControl;
FChart: TAtlasChart;
FEast, FWest: TAtlasChartSeries;
FQueue: TAtlasGauge;
FThemer: TAtlasThemer;
FAddMonth: TAction;
FMonths: Integer;
function NewAction(const Caption: string; Handler: TNotifyEvent; Tag: Integer = 0): TAction;
function NewPage(const Caption: string): TTabSheet;
function AddGauge(Parent: TWinControl; const Caption: string; Top: Integer; Value: Double): TAtlasGauge;
procedure ShowPage(Sender: TObject);
procedure AddMonth(Sender: TObject);
procedure ToggleBars(Sender: TObject);
procedure NextTheme(Sender: TObject);
procedure FloatNavigation(Sender: TObject);
procedure QueueChanged(Sender: TObject);
procedure FirstActivate(Sender: TObject);
procedure SaveLayout(Sender: TObject; var Action: TCloseAction);
public
constructor Create(AOwner: TComponent); override;
procedure SelectPage(Index: Integer);
end;
implementation
uses
System.SysUtils, System.Types, System.IOUtils, Vcl.Graphics, Vcl.StdCtrls;
const
MonthNames: array[0..11] of string = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
EastSales: array[0..11] of Double = (18, 22, 21, 29, 35, 38, 41, 39, 44, 47, 52, 58);
WestSales: array[0..11] of Double = (24, 29, 27, 32, 38, 42, 40, 45, 49, 51, 55, 61);
function LayoutFile: string;
begin
Result := TPath.Combine(ExtractFilePath(ParamStr(0)), 'shell-layout.json');
end;
constructor TShellForm.Create(AOwner: TComponent);
var
Page: TTabSheet;
Slider: TTrackBar;
Action: TAction;
I: Integer;
begin
inherited CreateNew(AOwner);
Caption := 'Atlas VCL application shell';
Position := poScreenCenter;
Width := 1000;
Height := 680;
Font.Name := 'Segoe UI';
Font.Size := 10;
OnActivate := FirstActivate;
OnClose := SaveLayout;
// 1. A workspace with three panes. The pane caption becomes the title of its floating window.
FWorkspace := TAtlasWorkspace.Create(Self);
FWorkspace.Parent := Self;
FWorkspace.Align := alClient;
FWorkspace.AddPane('navigation', 'Navigation', alLeft, 200);
FWorkspace.AddPane('commands', '', alTop, 150);
FWorkspace.AddPane('content', '', alClient, 400);
// AddPane leaves the splitter of a left or top pane on the outer edge, where it
// cannot be dragged; MovePane to the same edge puts it between pane and content.
FWorkspace.MovePane('navigation', alLeft, 200);
FWorkspace.MovePane('commands', alTop, 150);
// 2. The command bar, the navigation list and a page control inside the panes.
FCommands := TAtlasCommandBar.Create(Self);
FCommands.Parent := FWorkspace.Pane('commands');
FCommands.Align := alClient;
FNavigation := TAtlasNavigation.Create(Self);
FNavigation.Parent := FWorkspace.Pane('navigation');
FNavigation.Align := alClient;
FPages := TPageControl.Create(Self);
FPages.Parent := FWorkspace.Pane('content');
FPages.Align := alClient;
// 3. Content pages: a tile board, a chart and three gauges.
Page := NewPage('Home');
FTiles := TAtlasTileBoard.Create(Self);
FTiles.Parent := Page;
FTiles.Align := alClient;
FTiles.BevelOuter := bvNone;
Page := NewPage('Sales');
FChart := TAtlasChart.Create(Self);
FChart.Parent := Page;
FChart.Align := alClient;
FChart.Title := 'Regional sales (thousands)';
FEast := FChart.AddSeries('East', $00876524);
FWest := FChart.AddSeries('West', $005986B4);
for I := 1 to 6 do AddMonth(nil);
Page := NewPage('Gauges');
FQueue := AddGauge(Page, 'Queue depth (0-500, warning 300, critical 450)', 16, 0);
FQueue.SetRange(0, 500);
FQueue.SetThresholds(300, 450);
FQueue.Value := 120;
AddGauge(Page, 'CPU % (warning 70, critical 90)', 132, 62);
AddGauge(Page, 'Disk % (warning 70, critical 90)', 248, 91);
Slider := TTrackBar.Create(Self);
Slider.Parent := Page;
Slider.SetBounds(16, 364, 560, 40);
Slider.Anchors := [akLeft, akTop, akRight];
Slider.Max := 500;
Slider.Frequency := 50;
Slider.Position := 120;
Slider.OnChange := QueueChanged;
FPages.ActivePageIndex := 0;
// 4. Actions shared by the navigation list, the tile board and the command bar.
for I := 0 to FPages.PageCount - 1 do
begin
Action := NewAction(FPages.Pages[I].Caption, ShowPage, I);
FNavigation.AddAction(Action);
FTiles.AddTile(Action);
FCommands.AddCommand('Home', 'Pages', Action);
end;
FAddMonth := NewAction('Add month', AddMonth);
FCommands.AddCommand('Home', 'Sales', FAddMonth);
FCommands.AddCommand('Home', 'Sales', NewAction('Bars / lines', ToggleBars));
FCommands.AddCommand('View', 'Appearance', NewAction('Next theme', NextTheme));
FCommands.AddCommand('View', 'Layout', NewAction('Float navigation', FloatNavigation));
// 5. The themer colours every control below its root; assign it after the controls exist.
FThemer := TAtlasThemer.Create(Self);
FThemer.Root := FWorkspace;
end;
function TShellForm.NewAction(const Caption: string; Handler: TNotifyEvent; Tag: Integer): TAction;
begin
Result := TAction.Create(Self);
Result.Caption := Caption;
Result.Tag := Tag;
Result.OnExecute := Handler;
end;
function TShellForm.NewPage(const Caption: string): TTabSheet;
begin
Result := TTabSheet.Create(Self);
Result.PageControl := FPages;
Result.Caption := Caption;
Result.TabVisible := False;
end;
function TShellForm.AddGauge(Parent: TWinControl; const Caption: string; Top: Integer; Value: Double): TAtlasGauge;
begin
Result := TAtlasGauge.Create(Self);
Result.Parent := Parent;
Result.SetBounds(16, Top, 560, 100);
Result.Anchors := [akLeft, akTop, akRight];
Result.Caption := Caption;
Result.Value := Value;
end;
procedure TShellForm.SelectPage(Index: Integer);
begin
FPages.ActivePageIndex := Index;
FNavigation.ItemIndex := Index;
end;
procedure TShellForm.ShowPage(Sender: TObject);
begin
SelectPage(TAction(Sender).Tag);
end;
procedure TShellForm.AddMonth(Sender: TObject);
begin
if FMonths >= Length(MonthNames) then Exit;
// X is the month number. Captions label the bars; line charts use the numeric axis.
FEast.Add(FMonths + 1, EastSales[FMonths], MonthNames[FMonths]);
if FMonths = 3 then
FWest.AddMissing(FMonths + 1) // a gap: the line breaks and no bar is drawn
else
FWest.Add(FMonths + 1, WestSales[FMonths], MonthNames[FMonths]);
Inc(FMonths);
if Assigned(FAddMonth) then FAddMonth.Enabled := FMonths < Length(MonthNames);
end;
procedure TShellForm.ToggleBars(Sender: TObject);
begin
if FChart.Kind = acLine then FChart.Kind := acBar else FChart.Kind := acLine;
end;
procedure TShellForm.NextTheme(Sender: TObject);
begin
FThemer.ThemeIndex := (FThemer.ThemeIndex + 1) mod AtlasThemeCount;
Caption := 'Atlas VCL application shell - ' + AtlasTheme(FThemer.ThemeIndex).Name;
end;
procedure TShellForm.FloatNavigation(Sender: TObject);
var
Origin: TPoint;
begin
if FWorkspace.IsFloating('navigation') then
FWorkspace.DockPane('navigation')
else
begin
Origin := ClientToScreen(Point(40, 120));
FWorkspace.FloatPane('navigation', Rect(Origin.X, Origin.Y, Origin.X + 240, Origin.Y + 400));
end;
end;
procedure TShellForm.QueueChanged(Sender: TObject);
begin
FQueue.Value := TTrackBar(Sender).Position;
end;
procedure TShellForm.FirstActivate(Sender: TObject);
begin
// Restore the saved layout once the workspace is showing, so a floating pane can open its window.
OnActivate := nil;
if not FileExists(LayoutFile) then Exit;
try
FWorkspace.LoadLayout(TFile.ReadAllText(LayoutFile, TEncoding.UTF8));
except
on EAtlasLayoutError do ; // a stale or edited file: keep the default layout
end;
end;
procedure TShellForm.SaveLayout(Sender: TObject; var Action: TCloseAction);
begin
TFile.WriteAllText(LayoutFile, FWorkspace.SaveLayout, TEncoding.UTF8);
end;
end.