feat(editor): empty-graph CTA + fit-to-screen button
Two polishing tweaks on the graph tab: - When the active flow has no steps, the canvas would have rendered as a near-empty grid (just inputs / outputs sidebars). Overlay a centred call-to-action with the graph icon, the "No steps yet" / "Noch keine Schritte" heading, a one-liner explainer, and a primary Add Step button that opens the capability picker directly. - Auto-fit zoom on first open of each flow + a floating "Fit to screen" button (bottom-right corner of the canvas viewport). The auto-fit re-runs only when the flow name changes, so the operator's manual pan / zoom on the current flow is preserved. The fit math expands the bounding box to include inputs + outputs pseudo- nodes too, so wide flows zoom out enough to show every port at once. Fit math: - Walk every step's stored position + height; merge with the inputs sidebar's known position. - Compute scale that makes the bounding box fit the viewport with 80 px padding on each side. - Clamp to [0.4, 2.0] — InteractiveViewer's own bounds. - Translate so the box centres in the viewport. `flutter analyze` clean, all 11 tests still pass. Signed-off-by: flemming-it <sf@flemming.it>
This commit is contained in:
parent
6b70ba65fd
commit
9d21bd5318
2 changed files with 220 additions and 81 deletions
|
|
@ -416,11 +416,58 @@ outputs:
|
|||
// When a step is selected, show the properties panel on
|
||||
// the right as a fixed sidebar. Selection is owned by
|
||||
// the controller and ChangeNotifier rebuilds drive the
|
||||
// panel show / hide.
|
||||
// panel show / hide. When the flow has no steps at all,
|
||||
// overlay a call-to-action so the operator's first
|
||||
// instinct is the right action rather than staring at an
|
||||
// empty grid.
|
||||
final hasSteps = _controller.graph.steps.isNotEmpty;
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(child: FlowCanvas(controller: _controller)),
|
||||
Expanded(
|
||||
child: Stack(
|
||||
children: [
|
||||
FlowCanvas(controller: _controller),
|
||||
if (!hasSteps)
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
color: theme.colorScheme.surface.withValues(alpha: 0.92),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.account_tree_outlined,
|
||||
size: 48,
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
const SizedBox(height: FaiSpace.md),
|
||||
Text(
|
||||
_l.graphEmptyTitle,
|
||||
style: theme.textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: FaiSpace.sm),
|
||||
Text(
|
||||
_l.graphEmptyBody,
|
||||
textAlign: TextAlign.center,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: FaiSpace.md),
|
||||
FilledButton.icon(
|
||||
onPressed: _addStep,
|
||||
icon: const Icon(Icons.add_box_outlined, size: 16),
|
||||
label: Text(_l.addStep),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (_controller.selectedStepId != null) ...[
|
||||
const VerticalDivider(width: 1),
|
||||
SizedBox(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue