Dropping to C++

The same surface, in C++, for when the data already lives there.

Every node on the Blueprint side is a function on this side, so you lose nothing moving a table into C++. Four things are C++ only: a work dispatcher, Get Items, and the two delegates that add to a menu.

Reach for it when the data already lives in C++ and wrapping it in a UObject per row would be work for the sake of it.

The table

// the same three ways in
Table->SetItems( Ships );
Table->SetDataTable( ShipTable );
Table->SetModel( MyModel );

FSmartTableColumn Name;
Name.ColumnId = TEXT( "Callsign" );
Name.Sizing   = ESmartTableColumnSizing::Fixed;
Name.Width    = 140.0f;

Table->SetColumns( { Name } );

A model

int32 UMyModel::GetNumRows_Implementation()
{
    return Ships.Num();
}

FText UMyModel::GetCellText_Implementation( int32 Row, FName Col )
{
    const FShip & S = Ships[ Row ];

    return Col == "Name" ? FText::FromString( S.Name )
                         : FText::AsNumber( S.Shield );
}

FName UMyModel::GetRowId_Implementation( int32 Row )
{
    return Ships[ Row ].Id;
}

Sort keys

A key is a number, some text, or nothing at all. Override this one for numeric columns.

using FKey = FSmartTableSortKey;

FKey UMyModel::GetCellSortKey_Implementation( int32 Row,
                                              FName Col )
{
    if ( Col == "Shield" )
    {
        return FKey::MakeNumber( Ships[ Row ].Shield );
    }

    return Super::GetCellSortKey_Implementation( Row, Col );
}

A cell

void UMyCell::NativeOnCellAssigned()
{
    if ( AMyShip * Ship = Cast< AMyShip >( GetItem() ) )
    {
        Bar->SetPercent( Ship->ShieldPct );
    }
}

void UMyCell::NativeOnCellReleased()
{
    StopAnimation( Flash );
}

Off the game thread

Model->SetWorkDispatcher(
    SmartTable::Dispatchers::TaskGraph() );

A model with no dispatcher sorts on the game thread, so nothing leaves it until you say so. Only the sort itself moves. The model pulls its keys on the game thread first, as plain numbers and text, so no worker thread ever calls your model.

The headers carry the rest

Every public header has a page in the Reference section, and each page is the header itself. The doc comments, not somebody's retelling of them. The three worth reading before you write anything are SmartTableModel.h on the two row spaces, SmartTableCell.h on what a recycled cell owes you, and SmartTable.h on the widget's own contracts.

Next: Items