162 lines
5.6 KiB
Dart
162 lines
5.6 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:ainoval/utils/web_theme.dart';
|
||
import 'package:flutter/gestures.dart';
|
||
import 'package:flutter_quill/flutter_quill.dart';
|
||
import 'package:ainoval/utils/logger.dart';
|
||
import 'package:ainoval/utils/setting_reference_processor.dart';
|
||
|
||
/// 🎯 简化版设定引用悬停状态管理器
|
||
/// 使用TextStyle.backgroundColor实现悬停效果,比复杂的位置计算更简单高效
|
||
class SettingReferenceHoverManager extends ChangeNotifier {
|
||
static final SettingReferenceHoverManager _instance = SettingReferenceHoverManager._internal();
|
||
factory SettingReferenceHoverManager() => _instance;
|
||
SettingReferenceHoverManager._internal();
|
||
|
||
String? _hoveredSettingId;
|
||
String? get hoveredSettingId => _hoveredSettingId;
|
||
|
||
/// 设置悬停的设定引用ID
|
||
void setHoveredSetting(String? settingId) {
|
||
if (_hoveredSettingId != settingId) {
|
||
_hoveredSettingId = settingId;
|
||
notifyListeners();
|
||
AppLogger.d('SettingReferenceHoverManager',
|
||
_hoveredSettingId != null
|
||
? '🖱️ 设定引用悬停开始: $_hoveredSettingId'
|
||
: '🖱️ 设定引用悬停结束');
|
||
}
|
||
}
|
||
|
||
/// 清除悬停状态
|
||
void clearHover() {
|
||
setHoveredSetting(null);
|
||
}
|
||
}
|
||
|
||
/// 设定引用交互混入 - 为 SceneEditor 提供设定引用交互功能
|
||
mixin SettingReferenceInteractionMixin {
|
||
/// 🎯 获取支持悬停效果的设定引用样式构建器
|
||
/// 这是最核心的方法,直接在customStyleBuilder中处理悬停效果
|
||
static TextStyle Function(Attribute) getCustomStyleBuilderWithHover({
|
||
required String? hoveredSettingId,
|
||
}) {
|
||
return (Attribute attribute) {
|
||
// 处理设定引用的样式标记
|
||
if (attribute.key == SettingReferenceProcessor.settingStyleAttr &&
|
||
attribute.value == 'reference') {
|
||
|
||
// 🎯 关键:使用TextStyle.backgroundColor实现悬停效果
|
||
return const TextStyle(
|
||
decoration: TextDecoration.underline,
|
||
decorationStyle: TextDecorationStyle.dotted,
|
||
decorationColor: WebTheme.grey400,
|
||
decorationThickness: 1.5,
|
||
// 🎯 核心:直接使用TextStyle的backgroundColor属性
|
||
backgroundColor: Color(0x00FFF3CD),
|
||
).copyWith(
|
||
backgroundColor: hoveredSettingId != null ? const Color(0xFFFFF3CD) : null,
|
||
);
|
||
}
|
||
|
||
return const TextStyle();
|
||
};
|
||
}
|
||
|
||
/// 获取设定引用的自定义手势识别器构建器
|
||
static GestureRecognizer? Function(Attribute, Node) getCustomRecognizerBuilder({
|
||
required Function(String settingId)? onSettingReferenceClicked,
|
||
required Function(String settingId)? onSettingReferenceHovered,
|
||
required VoidCallback? onSettingReferenceHoverEnd,
|
||
}) {
|
||
return (Attribute attribute, Node node) {
|
||
|
||
// 检查是否是设定引用属性
|
||
if (attribute.key == SettingReferenceProcessor.settingReferenceAttr ) {
|
||
final settingId = attribute.value as String?;
|
||
if (settingId != null && settingId.isNotEmpty) {
|
||
//AppLogger.d('SettingReferenceInteraction', '🎯 创建设定引用手势识别器: $settingId');
|
||
|
||
// 创建支持点击和悬停的手势识别器
|
||
final tapRecognizer = TapGestureRecognizer()
|
||
..onTap = () {
|
||
AppLogger.i('SettingReferenceInteraction', '🖱️ 设定引用被点击: $settingId');
|
||
onSettingReferenceClicked?.call(settingId);
|
||
};
|
||
|
||
return tapRecognizer;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
};
|
||
}
|
||
|
||
/// 获取设定引用的自定义样式构建器(基础版本)
|
||
static TextStyle Function(Attribute) getCustomStyleBuilder() {
|
||
return (Attribute attribute) {
|
||
// 处理设定引用的样式标记
|
||
if (attribute.key == SettingReferenceProcessor.settingStyleAttr &&
|
||
attribute.value == 'reference') {
|
||
return const TextStyle(
|
||
decoration: TextDecoration.underline,
|
||
decorationStyle: TextDecorationStyle.dotted,
|
||
decorationColor: WebTheme.grey400,
|
||
decorationThickness: 1.5,
|
||
);
|
||
}
|
||
|
||
return const TextStyle();
|
||
};
|
||
}
|
||
|
||
}
|
||
|
||
/// 🎯 设定引用鼠标悬停检测器Widget
|
||
/// 使用MouseRegion包装编辑器,检测鼠标悬停并更新状态
|
||
class SettingReferenceMouseDetector extends StatefulWidget {
|
||
final Widget child;
|
||
final QuillController controller;
|
||
final String? novelId;
|
||
|
||
const SettingReferenceMouseDetector({
|
||
Key? key,
|
||
required this.child,
|
||
required this.controller,
|
||
this.novelId,
|
||
}) : super(key: key);
|
||
|
||
@override
|
||
State<SettingReferenceMouseDetector> createState() => _SettingReferenceMouseDetectorState();
|
||
}
|
||
|
||
class _SettingReferenceMouseDetectorState extends State<SettingReferenceMouseDetector> {
|
||
final _hoverManager = SettingReferenceHoverManager();
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return MouseRegion(
|
||
onHover: _handleMouseMove,
|
||
onExit: (_) => _hoverManager.clearHover(),
|
||
child: widget.child,
|
||
);
|
||
}
|
||
|
||
void _handleMouseMove(PointerHoverEvent event) {
|
||
// 🎯 这里可以实现基于鼠标位置的设定引用检测
|
||
// 为了简化,暂时先处理基本的悬停状态
|
||
try {
|
||
// TODO: 实现更精确的位置检测逻辑
|
||
// 目前先简化处理,后续可以根据需要优化
|
||
|
||
// 暂时用一个简单的方式来模拟检测
|
||
// 实际项目中可能需要更复杂的位置计算
|
||
|
||
AppLogger.v('SettingReferenceMouseDetector', '🖱️ 鼠标移动: ${event.localPosition}');
|
||
|
||
} catch (e) {
|
||
AppLogger.w('SettingReferenceMouseDetector', '检测设定引用悬停失败', e);
|
||
}
|
||
}
|
||
}
|
||
|
||
|