SSpreadsheet class

A reusable, spreadsheet-like 2D table composed of:

  • a fixed top header row
  • an optional fixed left row-header column
  • vertically virtualized body rows (ListView.builder)
  • synchronized horizontal scrolling for all rows and headers

This first engine intentionally mirrors the proven sync-scroll architecture used in heavy custom schedulers, while exposing reusable builders.

Inheritance
Available extensions

Constructors

SSpreadsheet({Key? key, required int rowCount, required int columnCount, required SSpreadsheetCellBuilder cellBuilder, SSpreadsheetRowHeaderBuilder? rowHeaderBuilder, SSpreadsheetColumnHeaderBuilder? columnHeaderBuilder, WidgetBuilder? cornerBuilder, double rowHeaderWidth = 100, double headerHeight = 48, SSpreadsheetRowHeightBuilder? rowHeightBuilder, SSpreadsheetColumnWidthBuilder? columnWidthBuilder, EdgeInsetsGeometry padding = EdgeInsets.zero, EdgeInsetsGeometry rowPadding = EdgeInsets.zero, IndexedScrollController? verticalIndexedController, ScrollPhysics? verticalPhysics, ScrollPhysics? horizontalPhysics, Color? backgroundColor, bool showColumnHeader = true, SSpreadsheetHorizontalMetricsChanged? onHorizontalMetricsChanged, SSpreadsheetHorizontalSyncController? horizontalSyncController, bool repaintBoundaryPerRow = false, Duration rowExtentAnimationDuration = Duration.zero, bool addAutomaticKeepAlives = false, bool enableRowAnimations = true, Key rowKeyBuilder(int rowIndex)?, Duration rowAnimationDuration = const Duration(milliseconds: 400), SSpreadsheetSelectionController? selectionController, Object columnKeyBuilder(int columnIndex)?, double dimUnselectedOpacity = 1.0, Duration dimAnimationDuration = const Duration(milliseconds: 250), bool enableTapToSelectRowHeader = false, bool enableTapToSelectColumnHeader = false, Color? rowHeaderTapSplashColor = Colors.transparent, Color? columnHeaderTapSplashColor = Colors.transparent, void onRowHeaderSelected(int rowIndex, Object? key)?, void onColumnHeaderSelected(int rowIndex, Object? key)?, VoidCallback? onSelectionCleared, void onCellTap(int rowIndex, int columnIndex)?, bool enableKeystrokes = false, bool keystrokeDebugLogs = false, Map<Type, VoidCallback>? keystrokeActionHandlers, Map<Type, String>? keystrokeActionLabels, Map<ShortcutActivator, Intent>? keystrokeShortcuts, bool includeDefaultKeystrokeShortcuts = true, void onKeystrokeEvent(KeyDownEvent)?, FocusNode? keystrokeFocusNode, bool keystrokeRequestFocusOnInit = true, bool shouldPauseKeystrokes()?, SSpreadsheetKeystrokeHudBuilder? keystrokeHudBuilder, Duration keystrokeHudDuration = const Duration(seconds: 1)})
const

Properties

addAutomaticKeepAlives → bool
Whether to keep body rows alive.
final
backgroundColor → Color?
Optional background color behind the sheet.
final
cellBuilder → SSpreadsheetCellBuilder
Builds each body cell.
final
columnCount → int
Number of body columns (horizontally scrollable columns).
final
columnHeaderBuilder → SSpreadsheetColumnHeaderBuilder?
Optional builder for the top fixed column-header cells.
final
columnHeaderTapSplashColor → Color?
Splash/hover color for enableTapToSelectColumnHeader's tap target. Mirrors rowHeaderTapSplashColor.
final
columnKeyBuilder → Object Function(int columnIndex)?
Optional key builder that gives each column a stable identity for selectionController. Mirrors rowKeyBuilder. If null, the raw column index is used as the identity key.
final
columnWidthBuilder → SSpreadsheetColumnWidthBuilder?
Width resolver for each body column.
final
cornerBuilder → WidgetBuilder?
Optional builder for the top-left corner (intersection of row/column headers).
final
dimAnimationDuration → Duration
Duration of the dim/undim opacity animation. Defaults to 250ms.
final
dimUnselectedOpacity → double
Opacity applied (via AnimatedOpacity) to every header/cell that does not belong to the selected row/column. Defaults to 1.0, which disables dimming entirely even when selectionController is set.
final
enableKeystrokes → bool
When true, wraps the spreadsheet content in a KeystrokeListener so that keyboard shortcuts are detected and dispatched to keystrokeActionHandlers. Defaults to false (backward compatible).
final
enableRowAnimations → bool
Whether to animate rows when they are inserted or removed.
final
enableTapToSelectColumnHeader → bool
When true, tapping a column-header cell toggles that column's selection on selectionController. Mirrors enableTapToSelectRowHeader. Requires selectionController to be set.
final
enableTapToSelectRowHeader → bool
When true, tapping a row-header cell toggles that row's selection on selectionController. The tap target wraps whatever rowHeaderBuilder renders as its ancestor (translucent, so interactive elements inside the header — e.g. an icon button — still take priority for their own bounds). Requires selectionController to be set.
final
hashCode → int
The hash code for this object.
no setterinherited
headerHeight → double
Height of the top header row.
final
horizontalPhysics → ScrollPhysics?
Horizontal row/header physics.
final
horizontalSyncController → SSpreadsheetHorizontalSyncController?
Optional external horizontal sync controller that tracks shared horizontal metrics and allows external scroll controls.
final
includeDefaultKeystrokeShortcuts → bool
Whether the built-in navigation/editing shortcuts (ESC, Ctrl+S, Ctrl+Z, etc.) should be registered. Defaults to true.
final
key → Key?
Controls how one widget replaces another widget in the tree.
finalinherited
keystrokeActionHandlers → Map<Type, VoidCallback>?
Maps an Intent type to a callback that implements the action.
final
keystrokeActionLabels → Map<Type, String>?
Maps an Intent type to a human-readable action label (e.g. "New Dept Booking"). Used together with the auto-derived shortcut label to populate the HUD overlay via keystrokeHudBuilder.
final
keystrokeDebugLogs → bool
When true and enableKeystrokes is true, every detected keystroke is printed via debugPrint. No action handlers fire in this mode.
final
keystrokeFocusNode → FocusNode?
External FocusNode for the internal KeystrokeListener. When provided, callers can call FocusNode.requestFocus externally to re-acquire keystroke focus after overlays dismiss.
final
keystrokeHudBuilder → SSpreadsheetKeystrokeHudBuilder?
Custom HUD widget builder. When provided, the HUD is shown automatically before each keystrokeActionHandlers callback runs (provided a label exists in keystrokeActionLabels).
final
keystrokeHudDuration → Duration
How long the HUD overlay remains visible before auto-dismissing. Defaults to 1 second.
final
keystrokeRequestFocusOnInit → bool
When true, the internal KeystrokeListener requests autofocus on init, giving the hidden TextField the HTML autofocus attribute on Flutter Web. Defaults to true when enableKeystrokes is true.
final
keystrokeShortcuts → Map<ShortcutActivator, Intent>?
Custom shortcut bindings scoped to this spreadsheet. Merged after the built-in default shortcuts (unless includeDefaultKeystrokeShortcuts is false). Use this with custom Intent subclasses to detect key combinations not covered by the defaults.
final
onCellTap → void Function(int rowIndex, int columnIndex)?
Optional callback fired when a body cell is tapped. Wraps the built cell in a translucent GestureDetector so it doesn't interfere with interactive widgets the cell itself renders (bookings, buttons, etc.).
final
onColumnHeaderSelected → void Function(int rowIndex, Object? key)?
Called after a column header tap changes selectionController's column selection. Mirrors onRowHeaderSelected. Only fires when enableTapToSelectColumnHeader is true.
final
onHorizontalMetricsChanged → SSpreadsheetHorizontalMetricsChanged?
Optional callback exposing synchronized horizontal scroll metrics.
final
onKeystrokeEvent → void Function(KeyDownEvent)?
Raw KeyDownEvent callback for custom handling beyond the Intent system. Fires for every key event that reaches the internal KeystrokeListener.
final
onRowHeaderSelected → void Function(int rowIndex, Object? key)?
Called after a row header tap changes selectionController's row selection (including when it toggles the selection off, in which case key is null). Only fires when enableTapToSelectRowHeader is true.
final
onSelectionCleared → VoidCallback?
Called whenever a tap outside the selected row/column clears selectionController's selection (either axis).
final
padding → EdgeInsetsGeometry
Padding applied around the whole spreadsheet.
final
repaintBoundaryPerRow → bool
Whether to wrap each built body row in a RepaintBoundary.
final
rowAnimationDuration → Duration
Duration of the insert/remove row animation. Defaults to 400ms.
final
rowCount → int
Number of body rows.
final
rowExtentAnimationDuration → Duration
Optional animation duration for row height changes.
final
rowHeaderBuilder → SSpreadsheetColumnHeaderBuilder?
Optional builder for the left fixed row-header cells.
final
rowHeaderTapSplashColor → Color?
Splash/hover color for enableTapToSelectRowHeader's tap target. Defaults to fully transparent (no visible feedback beyond the dimming/selection state itself) to preserve prior behavior. Pass null to fall back to SInkButton's own default (currently Colors.purple) for a visible ripple, or any other color to match your header's theme.
final
rowHeaderWidth → double
Width of the fixed left row-header column.
final
rowHeightBuilder → SSpreadsheetColumnWidthBuilder?
Height resolver for each body row.
final
rowKeyBuilder → Key Function(int rowIndex)?
Optional key builder that gives each row a stable identity across rebuilds.
final
rowPadding → EdgeInsetsGeometry
Padding applied inside each body row container.
final
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
selectionController → SSpreadsheetSelectionController?
Optional controller enabling row/column selection + dimming. See SSpreadsheetSelectionController.
final
shouldPauseKeystrokes → bool Function()?
When provided and returns true, all keystroke intent handlers are suppressed and the auto-refocus is paused. Use this when descendant text inputs need exclusive keyboard access (e.g. a search bar inside the spreadsheet).
final
showColumnHeader → bool
Whether to draw the top header row.
final
verticalIndexedController → IndexedScrollController?
Optional IndexedScrollController for vertical (row) index-based scrolling.
final
verticalPhysics → ScrollPhysics?
Vertical list physics.
final

Methods

addMaterialWidget() → Material

Available on Widget, provided by the GenericExtensions extension

addTooltipWidget(String toolTip) → Tooltip

Available on Widget, provided by the GenericExtensions extension

borderRadius([BorderRadiusGeometry? borderRadius]) → Widget

Available on Widget, provided by the GenericExtensions extension

boxDecoration([BoxDecoration? boxDecoration]) → Widget

Available on Widget, provided by the GenericExtensions extension

buildExport(BuildContext context, {List<int>? rowIndices}) → Widget
Builds all columns and the requested rows at their natural dimensions.
colorFilter([ColorFilter? colorFilter]) → Widget

Available on Widget, provided by the GenericExtensions extension

set parent widget in center
createElement() → StatefulElement
Creates a StatefulElement to manage this widget's location in the tree.
inherited
createState() → State<SSpreadsheet>
Creates the mutable state for this widget at a given location in the tree.
override
debugDescribeChildren() → List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children.
inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node.
inherited
exportSize(BuildContext context, {List<int>? rowIndices}) → Size
Natural dimensions of buildExport, before screenshot/PDF scaling.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toDiagnosticsNode({String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
inherited
toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) → String
A string representation of this object.
inherited
toStringDeep({String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug, int wrapWidth = 65}) → String
Returns a string representation of this node and its descendants.
inherited
toStringShallow({String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String
Returns a one-line detailed description of the object.
inherited
toStringShort() → String
A short, textual description of this widget.
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited