// lib/editor/input/tool_settings.dart // // Per-tool settings memory for the tool palette (F1/F5/F11). Each tool keeps its // OWN color + width, so switching pen → highlighter → pen restores the pen's // last color/width instead of bleeding the highlighter's. Immutable value type // with copy-on-write updates; the toolbar holds one of these and persists it. // // Pure (no widgets/storage); fully unit-tested. import 'package:flutter/foundation.dart'; enum EditorToolType { pen, highlighter, eraser } /// Color (ARGB int) + width (fraction of page width) for one tool. The eraser /// ignores color but keeps a width (its radius). @immutable class ToolConfig { const ToolConfig({required this.color, required this.width}); final int color; final double width; ToolConfig copyWith({int? color, double? width}) => ToolConfig(color: color ?? this.color, width: width ?? this.width); @override bool operator ==(Object other) => other is ToolConfig && other.color == color && other.width == width; @override int get hashCode => Object.hash(color, width); } /// The active tool + each tool's remembered [ToolConfig]. @immutable class ToolSettings { const ToolSettings({required this.active, required Map configs}) : _configs = configs; /// Sensible starting state: black thin pen, yellow fat highlighter, medium /// eraser; pen active. factory ToolSettings.defaults() => const ToolSettings( active: EditorToolType.pen, configs: { EditorToolType.pen: ToolConfig(color: 0xFF000000, width: 0.003), EditorToolType.highlighter: ToolConfig(color: 0x80FFEB3B, width: 0.02), EditorToolType.eraser: ToolConfig(color: 0x00000000, width: 0.02), }, ); final EditorToolType active; final Map _configs; ToolConfig configFor(EditorToolType tool) => _configs[tool] ?? const ToolConfig(color: 0xFF000000, width: 0.003); ToolConfig get activeConfig => configFor(active); /// Switch the active tool (each tool's own color/width is remembered). ToolSettings withActive(EditorToolType tool) => ToolSettings(active: tool, configs: _configs); ToolSettings _withConfig(EditorToolType tool, ToolConfig config) { return ToolSettings( active: active, configs: {..._configs, tool: config}, ); } /// Set the ACTIVE tool's color (no-op semantics for the eraser are the /// caller's choice; the value is still stored). ToolSettings withColor(int color) => _withConfig(active, activeConfig.copyWith(color: color)); /// Set the ACTIVE tool's width. ToolSettings withWidth(double width) => _withConfig(active, activeConfig.copyWith(width: width)); @override bool operator ==(Object other) => other is ToolSettings && other.active == active && mapEquals(other._configs, _configs); @override int get hashCode => Object.hash(active, Object.hashAll(_configs.entries)); }