// 编辑器 BLoC — 手写状态管理 + 撤销/重做 import 'package:flutter_bloc/flutter_bloc.dart'; import '../widgets/stroke_model.dart'; // ===== Events ===== abstract class EditorEvent {} class BrushChanged extends EditorEvent { final BrushType type; final String color; final double width; BrushChanged({required this.type, required this.color, required this.width}); } class StrokeCompleted extends EditorEvent { final Stroke stroke; StrokeCompleted(this.stroke); } class Undo extends EditorEvent {} class Redo extends EditorEvent {} class ClearCanvas extends EditorEvent {} class StrokesLoaded extends EditorEvent { final List strokes; StrokesLoaded(this.strokes); } // ===== State ===== class EditorState { final List strokes; final List redoStack; final BrushType brushType; final String brushColor; final double brushWidth; final int maxUndoSteps; const EditorState({ this.strokes = const [], this.redoStack = const [], this.brushType = BrushType.pen, this.brushColor = '#2D2420', this.brushWidth = 3.0, this.maxUndoSteps = 50, }); EditorState copyWith({ List? strokes, List? redoStack, BrushType? brushType, String? brushColor, double? brushWidth, }) => EditorState( strokes: strokes ?? this.strokes, redoStack: redoStack ?? this.redoStack, brushType: brushType ?? this.brushType, brushColor: brushColor ?? this.brushColor, brushWidth: brushWidth ?? this.brushWidth, maxUndoSteps: maxUndoSteps, ); } // ===== BLoC ===== class EditorBloc extends Bloc { EditorBloc() : super(const EditorState()) { on(_onBrushChanged); on(_onStrokeCompleted); on(_onUndo); on(_onRedo); on(_onClearCanvas); on(_onStrokesLoaded); } void _onBrushChanged(BrushChanged event, Emitter emit) { emit(state.copyWith( brushType: event.type, brushColor: event.color, brushWidth: event.width, )); } void _onStrokeCompleted(StrokeCompleted event, Emitter emit) { final updatedStrokes = List.from(state.strokes)..add(event.stroke); // 超过最大撤销步数时移除最旧的 if (updatedStrokes.length > state.maxUndoSteps) { updatedStrokes.removeAt(0); } emit(state.copyWith( strokes: updatedStrokes, redoStack: [], // 新笔画清空重做栈 )); } void _onUndo(Undo event, Emitter emit) { if (state.strokes.isEmpty) return; final updatedStrokes = List.from(state.strokes); final lastStroke = updatedStrokes.removeLast(); final updatedRedoStack = List.from(state.redoStack)..add(lastStroke); emit(state.copyWith( strokes: updatedStrokes, redoStack: updatedRedoStack, )); } void _onRedo(Redo event, Emitter emit) { if (state.redoStack.isEmpty) return; final updatedRedoStack = List.from(state.redoStack); final stroke = updatedRedoStack.removeLast(); final updatedStrokes = List.from(state.strokes)..add(stroke); emit(state.copyWith( strokes: updatedStrokes, redoStack: updatedRedoStack, )); } void _onClearCanvas(ClearCanvas event, Emitter emit) { emit(state.copyWith(strokes: [], redoStack: [])); } void _onStrokesLoaded(StrokesLoaded event, Emitter emit) { emit(state.copyWith(strokes: event.strokes, redoStack: [])); } }