create method
create the widget given a WidgetData type
data the widget data
environment the current Environment
context the BuildContext
Implementation
@override
Widget create(GridWidgetData data, Environment environment, BuildContext context) {
final spacing = data.spacing.toDouble();
if (data.cols.isEmpty || data.rows.isEmpty) {
return const Center(
child: Text(
'Grid has no rows or columns',
style: TextStyle(color: Colors.grey),
),
);
}
final columnWidths = <int, TableColumnWidth>{
for (var i = 0; i < data.cols.length; i++)
i: switch (data.cols[i].sizeMode) {
GridSizeMode.fixed => FixedColumnWidth(data.cols[i].size),
GridSizeMode.flex => FlexColumnWidth(data.cols[i].size),
GridSizeMode.auto => const IntrinsicColumnWidth(),
}
};
Widget _buildDropArea(int rowIndex, int colIndex) {
return DragTarget<WidgetData>(
onWillAccept: (widget) => data.acceptsChild(widget!),
onAccept: (widget) {
environment.get<CommandStack>().execute(
ReparentCommand(
bus: environment.get<MessageBus>(),
widget: widget,
newParent: data,
newCell: Cell(row: rowIndex, col: colIndex),
),
);
},
builder: (context, candidateData, rejectedData) {
final isActive = candidateData.isNotEmpty;
return Container(
constraints: const BoxConstraints(minHeight: 60, minWidth: 60),
decoration: BoxDecoration(
border: Border.all(
color: isActive ? Colors.blue : Colors.grey,
width: 1,
style: BorderStyle.solid,
),
borderRadius: BorderRadius.circular(4),
),
child: Center(
child: Text(
isActive ? "Drop here" : "Empty",
style: TextStyle(
fontSize: 12,
color: isActive ? Colors.blue : Colors.grey,
fontStyle: FontStyle.italic,
),
),
),
);
},
);
}
// REMOVED _alignedCellContent to use TableCell properties instead
// The old logic was redundant/incorrect for a Table structure.
return Table(
// Default vertical alignment for the table is fine, but it can be overridden per cell
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
columnWidths: columnWidths,
defaultColumnWidth: const FlexColumnWidth(1.0),
children: List.generate(data.rows.length, (rowIndex) {
final row = data.rows[rowIndex];
return TableRow(
children: List.generate(data.cols.length, (colIndex) {
final col = data.cols[colIndex];
final childModel = findElement(
data.children,
(w) => w.cell?.row == rowIndex && w.cell?.col == colIndex,
);
Widget content = childModel != null
? EditWidget(model: childModel)
: _buildDropArea(rowIndex, colIndex);
// 1. HORIZONTAL ALIGNMENT: Wrap the content in Align/Container
// to handle start/center/end/stretch horizontally.
// Note: Horizontal stretch is often handled by FlexColumnWidths.
if (col.alignment != GridAlignment.stretch) {
content = Align(
alignment: _mapGridAlignmentToFlutterAlignment(col.alignment, GridAlignment.center),
child: content,
);
}
// 2. WRAP IN PADDING: Apply the spacing/padding
content = Padding(
padding: EdgeInsets.all(spacing / 2),
child: content,
);
// 3. VERTICAL ALIGNMENT: MUST wrap in TableCell to communicate
// vertical alignment preference to the Table widget's layout.
return TableCell(
verticalAlignment: _mapGridAlignmentToVertical(row.alignment),
child: content,
);
}),
);
}),
);
}