import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; /// 工具栏组件 - 支持顶部和底部工具栏 /// /// 顶部工具栏:撤销/重做/保存/设置 /// 底部工具栏:元件库/走线模式/选择模式 /// 支持可折叠/隐藏 class ToolbarWidget extends ConsumerStatefulWidget { /// 是否显示顶部工具栏 final bool showTopToolbar; /// 是否显示底部工具栏 final bool showBottomToolbar; /// 工具栏是否可折叠 final bool collapsible; /// 撤销回调 final VoidCallback? onUndo; /// 重做回调 final VoidCallback? onRedo; /// 保存回调 final VoidCallback? onSave; /// 设置回调 final VoidCallback? onSettings; /// 元件库回调 final VoidCallback? onComponentLibrary; /// 走线模式回调 final VoidCallback? onWireMode; /// 选择模式回调 final VoidCallback? onSelectMode; const ToolbarWidget({ super.key, this.showTopToolbar = true, this.showBottomToolbar = true, this.collapsible = true, this.onUndo, this.onRedo, this.onSave, this.onSettings, this.onComponentLibrary, this.onWireMode, this.onSelectMode, }); @override ConsumerState createState() => _ToolbarWidgetState(); } class _ToolbarWidgetState extends ConsumerState with SingleTickerProviderStateMixin { // 顶部工具栏是否展开 bool _isTopExpanded = true; // 底部工具栏是否展开 bool _isBottomExpanded = true; // 当前激活的模式 ToolbarMode _currentMode = ToolbarMode.select; // 动画控制器 late AnimationController _animationController; late Animation _topAnimation; late Animation _bottomAnimation; @override void initState() { super.initState(); _animationController = AnimationController( duration: const Duration(milliseconds: 200), vsync: this, ); _topAnimation = CurvedAnimation( parent: _animationController, curve: Curves.easeInOut, ); _bottomAnimation = CurvedAnimation( parent: _animationController, curve: Curves.easeInOut, ); } @override void dispose() { _animationController.dispose(); super.dispose(); } void _toggleTopToolbar() { if (!widget.collapsible) return; setState(() { _isTopExpanded = !_isTopExpanded; if (_isTopExpanded) { _animationController.forward(); } else { _animationController.reverse(); } }); } void _toggleBottomToolbar() { if (!widget.collapsible) return; setState(() { _isBottomExpanded = !_isBottomExpanded; }); } void _setMode(ToolbarMode mode) { setState(() { _currentMode = mode; }); switch (mode) { case ToolbarMode.select: widget.onSelectMode?.call(); break; case ToolbarMode.wire: widget.onWireMode?.call(); break; case ToolbarMode.library: widget.onComponentLibrary?.call(); break; default: break; } } @override Widget build(BuildContext context) { return Stack( children: [ // 顶部工具栏 if (widget.showTopToolbar) _buildTopToolbar(), // 底部工具栏 if (widget.showBottomToolbar) _buildBottomToolbar(), ], ); } Widget _buildTopToolbar() { return Positioned( top: 0, left: 0, right: 0, child: SafeArea( child: AnimatedBuilder( animation: _topAnimation, builder: (context, child) { return Transform.translate( offset: Offset(0, -(_isTopExpanded ? 0 : 60) * (1 - _topAnimation.value)), child: Opacity( opacity: _isTopExpanded ? 1.0 : (1 - _topAnimation.value), child: child, ), ); }, child: _buildTopToolbarContent(), ), ), ); } Widget _buildTopToolbarContent() { return Container( margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Row( children: [ // 折叠按钮 if (widget.collapsible) IconButton( icon: Icon(_isTopExpanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down), iconSize: 20, onPressed: _toggleTopToolbar, tooltip: _isTopExpanded ? '收起' : '展开', ), // 撤销按钮 _buildToolButton( icon: Icons.undo, label: '撤销', onPressed: widget.onUndo, ), // 重做按钮 _buildToolButton( icon: Icons.redo, label: '重做', onPressed: widget.onRedo, ), const Spacer(), // 保存按钮 _buildToolButton( icon: Icons.save, label: '保存', onPressed: widget.onSave, showLabel: true, ), // 设置按钮 _buildToolButton( icon: Icons.settings, label: '设置', onPressed: widget.onSettings, ), ], ), ); } Widget _buildBottomToolbar() { return Positioned( bottom: 0, left: 0, right: 0, child: SafeArea( child: AnimatedContainer( duration: const Duration(milliseconds: 200), curve: Curves.easeInOut, transform: Matrix4.translationValues( 0, _isBottomExpanded ? 0 : 80, 0, ), child: Opacity( opacity: _isBottomExpanded ? 1.0 : 0.0, child: _buildBottomToolbarContent(), ), ), ), ); } Widget _buildBottomToolbarContent() { return Container( margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Row( children: [ // 折叠按钮 if (widget.collapsible) IconButton( icon: Icon(_isBottomExpanded ? Icons.keyboard_arrow_down : Icons.keyboard_arrow_up), iconSize: 20, onPressed: _toggleBottomToolbar, tooltip: _isBottomExpanded ? '收起' : '展开', ), // 选择模式 _buildModeButton( icon: Icons.touch_app, label: '选择', mode: ToolbarMode.select, ), // 走线模式 _buildModeButton( icon: Icons.edit, label: '走线', mode: ToolbarMode.wire, ), const Spacer(), // 元件库 _buildToolButton( icon: Icons.apps, label: '元件库', onPressed: widget.onComponentLibrary, showLabel: true, ), ], ), ); } Widget _buildToolButton({ required IconData icon, required String label, VoidCallback? onPressed, bool showLabel = false, }) { return Tooltip( message: label, child: Material( color: Colors.transparent, child: InkWell( onTap: onPressed, borderRadius: BorderRadius.circular(8), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(icon, size: 24, color: Colors.grey[700]), if (showLabel) Text( label, style: TextStyle(fontSize: 10, color: Colors.grey[600]), ), ], ), ), ), ), ); } Widget _buildModeButton({ required IconData icon, required String label, required ToolbarMode mode, }) { final isActive = _currentMode == mode; return Tooltip( message: label, child: Material( color: isActive ? Theme.of(context).primaryColor.withOpacity(0.1) : Colors.transparent, child: InkWell( onTap: () => _setMode(mode), borderRadius: BorderRadius.circular(8), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon( icon, size: 24, color: isActive ? Theme.of(context).primaryColor : Colors.grey[700], ), Text( label, style: TextStyle( fontSize: 10, color: isActive ? Theme.of(context).primaryColor : Colors.grey[600], fontWeight: isActive ? FontWeight.bold : FontWeight.normal, ), ), ], ), ), ), ), ); } } /// 工具栏模式枚举 enum ToolbarMode { select, // 选择模式 wire, // 走线模式 library, // 元件库模式 place, // 放置模式 edit, // 编辑模式 }