YOUSEFUL / DELPHI / COMPONENTS
TAtlasKanban
Custom-drawn Kanban board that shows a TAtlasKanbanModel as columns of cards, with selection, mouse and keyboard moves and wheel scrolling.
Description
Assign a TAtlasKanbanModel to Model; the board draws it and repaints on every model change. The board keeps no data of its own apart from the selected card and the scroll position, and several boards may show one model.
Layout. Each column is 270 pixels wide and each card slot 110 pixels high (98 of card, 12 of gap), scaled with the control's DPI. A dark header shows the column title, the card count and, for a limited column, the limit (In progress 1/2). A card shows its title in bold and its detail text below, both word-wrapped and cut with an ellipsis. The selected card has a blue outline. The colours are fixed: there are no colour, style or card-template properties, VCL styles are not applied, and no focus rectangle is drawn. Font sets the typeface and size (Segoe UI 10 by default). Without a model the board shows Assign a Kanban model to begin.
Mouse. A left click selects the card under the pointer, or clears the selection over empty space, and focuses the board. Dragging a card more than 4 pixels and releasing it over another column calls MoveSelectedTo for that column, so the card is appended to the end: there is no drop position, drag image or insertion mark. Releasing it over its own column moves it to the end of that column. The wheel scrolls all columns up and down together, and Shift+wheel scrolls sideways. There are no scroll bars.
Keyboard. The control handles the Up and Down arrows (select the previous or next card in the column), Left and Right (select the card at the same position, or the last card, in the neighbouring column) and Ctrl+Left and Ctrl+Right (move the selected card to the end of the neighbouring column). When nothing is selected, a key press selects the first card. The selection does not scroll into view. On a form the arrow keys do not reach the board: the control does not ask for them (WM_GETDLGCODE), so the VCL uses them to move the focus to another control. Use a small subclass that asks for them, shown in the examples; the product's own tests call the key handler directly and do not cover this.
Errors. Moves made through the board never raise: MoveSelectedTo returns False, keeps the reason in LastError and paints it in red at the bottom-left corner of the board.
Only Model, Align, Anchors, TabStop, Font, ParentFont and OnClick are published by this class, plus the usual TControl ones such as Left, Top, Width, Height, Cursor and Hint. Visible and Enabled are public; set them in code. Keyboard, mouse and paint events are not published. A new board is 850 by 480 pixels, double-buffered, with TabStop on.
Members
| Member | Kind | What it does |
|---|---|---|
Create | constructor | Creates a board 850 by 480 pixels, double-buffered, with TabStop set and the font Segoe UI 10. |
Destroy | destructor | Detaches the board from its model (the model is not freed) and destroys the control. |
SelectCard | method | Selects the card with id ID and repaints. |
MoveSelectedTo | method | Moves the selected card to the end of column ColumnID with the model's MoveCard, and returns True when it moved. |
SelectedCard | property | The id of the selected card, or an empty string. |
LastError | property | Why the last MoveSelectedTo failed, or an empty string after a successful one. |
Model | property | The model to show. |
Align | property | Published from TControl; alClient lets the board fill its parent. |
Anchors | property | Published from TControl. |
TabStop | property | Published from TWinControl with the default changed to True, so Tab reaches the board. |
Font | property | Published from TControl. |
ParentFont | property | Published from TControl. |
OnClick | event | Published from TControl. |
Constructors
Create constructor
constructor Create(AOwner: TComponent); override;Creates a board 850 by 480 pixels, double-buffered, with TabStop set and the font Segoe UI 10. Assign Parent and Model.
Destructors
Destroy destructor
destructor Destroy; override;Detaches the board from its model (the model is not freed) and destroys the control.
Properties
SelectedCard property
property SelectedCard: string read FSelected;The id of the selected card, or an empty string. Read-only; select with SelectCard, a click or the arrow keys.
LastError property
property LastError: string read FLastError;Why the last MoveSelectedTo failed, or an empty string after a successful one. The board also paints it in red in its bottom-left corner. It keeps its value until the next MoveSelectedTo.
Model property
property Model: TAtlasKanbanModel read FModel write SetModel;The model to show. Assigning a model clears the selection and scrolls back to the top-left corner. The board is notified when the model is freed, and Model becomes nil.
Board.Model := Model;Align property
property Align;Published from TControl; alClient lets the board fill its parent.
Anchors property
property Anchors;Published from TControl.
TabStop property
property TabStop default True;Published from TWinControl with the default changed to True, so Tab reaches the board.
Font property
property Font;Published from TControl. Sets the typeface and size of headers and cards; the colours are fixed.
ParentFont property
property ParentFont;Published from TControl.
Events
OnClick event
property OnClick;Published from TControl. Fires when the left button is released after a click, after the board has updated SelectedCard.
Board.OnClick := BoardClick;Methods
SelectCard method
procedure SelectCard(const ID: string);Selects the card with id ID and repaints. Raises EAtlasKanban (Unknown card) when no model is assigned or the model has no such card. The selection is not scrolled into view. It survives moves of the card and is cleared when the card is removed or Model changes.
Board.SelectCard('order-42');MoveSelectedTo method
function MoveSelectedTo(const ColumnID: string): Boolean;Moves the selected card to the end of column ColumnID with the model's MoveCard, and returns True when it moved. It never raises for a refused move: when nothing is selected, no model is assigned or BeforeMove declines, the result is False and LastError is Move declined; when the model raises EAtlasKanban (a full column, an unknown column), the result is False and LastError holds the message. Exceptions of other classes, for example one raised by your BeforeMove handler, are not caught. LastError is cleared at the start of every call. The mouse and the Ctrl+arrow keys use this method.
if not Board.MoveSelectedTo('done') then
StatusBar.SimpleText := Board.LastError;Examples
Show a board on a form and react to clicks
A form built in code with a model of three columns and a board filling the form. Clicking a card puts its id in the caption; clicking empty space clears it.
uses System.SysUtils, System.Classes, Vcl.Forms, Vcl.Controls, Atlas.Kanban;
type
TPlanForm = class(TForm)
private
FModel: TAtlasKanbanModel;
FBoard: TAtlasKanban;
procedure BoardClick(Sender: TObject);
public
constructor Create(AOwner: TComponent); override;
end;
constructor TPlanForm.Create(AOwner: TComponent);
begin
inherited CreateNew(AOwner);
Caption := 'Plan';
Width := 900;
Height := 500;
FModel := TAtlasKanbanModel.Create(Self);
FModel.AddColumn('todo', 'To do');
FModel.AddColumn('doing', 'Doing', 2);
FModel.AddColumn('done', 'Done');
FModel.AddCard('todo', 'notes', 'Write the release notes', 'Due Friday');
FModel.AddCard('doing', 'total', 'Fix the invoice total');
FBoard := TAtlasKanban.Create(Self);
FBoard.Parent := Self;
FBoard.Align := alClient;
FBoard.Model := FModel;
FBoard.OnClick := BoardClick;
end;
procedure TPlanForm.BoardClick(Sender: TObject);
begin
if FBoard.SelectedCard = '' then
Caption := 'Plan'
else
Caption := 'Plan: ' + FBoard.SelectedCard;
end;
Let the board take the arrow keys
Use TKeyboardKanban instead of TAtlasKanban whenever the board should respond to the keyboard. It asks Windows for the arrow keys, so Up, Down, Left and Right select cards and Ctrl+Left and Ctrl+Right move them, even when other controls share the form. The Kanban board sample project uses it.
uses Winapi.Windows, Winapi.Messages, Atlas.Kanban;
type
// Asks Windows for the arrow keys, so a board on a form receives them
// instead of the form using them to move the focus.
TKeyboardKanban = class(TAtlasKanban)
protected
procedure WMGetDlgCode(var Message: TWMGetDlgCode); message WM_GETDLGCODE;
end;
procedure TKeyboardKanban.WMGetDlgCode(var Message: TWMGetDlgCode);
begin
inherited;
Message.Result := Message.Result or DLGC_WANTARROWS;
end;
Related
TAtlasKanbanModel · TAtlasKanbanCard · EAtlasKanban