diff --git a/win_text_editor/lib/app/widgets/editor_pane.dart b/win_text_editor/lib/app/widgets/editor_pane.dart index 635f112..8d1a215 100644 --- a/win_text_editor/lib/app/widgets/editor_pane.dart +++ b/win_text_editor/lib/app/widgets/editor_pane.dart @@ -3,7 +3,7 @@ import 'package:provider/provider.dart'; import '../models/editor_tab.dart'; import '../providers/editor_provider.dart'; -import 'template_parser.dart'; +// import 'template_parser.dart'; class EditorPane extends StatelessWidget { const EditorPane({super.key}); @@ -60,7 +60,7 @@ class EditorPane extends StatelessWidget { switch (activeTab.type) { case EditorTabType.template: - return const TemplateParser(); // 你的模板解析组件 + return Container(); //TemplateParser(); // 你的模板解析组件 default: return Container(); // 空白或其他默认视图 } diff --git a/win_text_editor/lib/app/widgets/template_parser.dart b/win_text_editor/lib/app/widgets/template_parser.dart index 60ad57d..a733501 100644 --- a/win_text_editor/lib/app/widgets/template_parser.dart +++ b/win_text_editor/lib/app/widgets/template_parser.dart @@ -1,113 +1,38 @@ import 'package:flutter/material.dart'; +// import 'text_editor.dart'; -class TemplateParser extends StatelessWidget { - const TemplateParser({Key? key}) : super(key: key); +class TemplateParser extends StatefulWidget { + final String? initialContent; + + const TemplateParser({Key? key, this.initialContent}) : super(key: key); @override - Widget build(BuildContext context) { - return Card( - margin: EdgeInsets.zero, // 移除默认边距以填满整个区域 - color: Colors.grey[100], - child: Column( - children: [ - // 四个编辑框区域 - Expanded( - child: GridView.builder( - padding: const EdgeInsets.all(8.0), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - childAspectRatio: 1.0, - crossAxisSpacing: 8.0, - mainAxisSpacing: 8.0, - ), - itemCount: 4, - itemBuilder: (context, index) { - return _buildEditorPanel(context, index); - }, - ), - ), - ], - ), - ); - } + State createState() => _TemplateParserState(); +} - Widget _buildEditorPanel(BuildContext context, int index) { - // 定义每个面板的标题 - final titles = ['输入内容', '输出内容', '参考文件', '模板']; +class _TemplateParserState extends State { + late String _currentContent; - return Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // 工具条 - Container( - padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), - decoration: BoxDecoration( - color: Colors.grey[100], - borderRadius: const BorderRadius.vertical(top: Radius.circular(4.0)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - // 左侧标题 - Text( - titles[index], - style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14), - ), - // 右侧工具按钮 - Row( - mainAxisSize: MainAxisSize.min, - children: [ - IconButton( - icon: const Icon(Icons.folder_open, size: 18), - onPressed: () {}, - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - ), - IconButton( - icon: const Icon(Icons.content_copy, size: 18), - onPressed: () {}, - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - ), - IconButton( - icon: const Icon(Icons.save, size: 18), - onPressed: () {}, - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - ), - IconButton( - icon: const Icon(Icons.close, size: 18), - onPressed: () {}, - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - ), - ], - ), - ], - ), - ), + @override + void initState() { + super.initState(); + _currentContent = widget.initialContent ?? '这里是模板解析器的初始内容'; + } - // 编辑框 - Expanded( - child: Container( - decoration: BoxDecoration( - border: Border.all(color: Colors.grey), - borderRadius: const BorderRadius.vertical(bottom: Radius.circular(4.0)), - ), - child: const TextField( - maxLines: null, - expands: true, - decoration: InputDecoration( - fillColor: Colors.white, - filled: true, - border: InputBorder.none, - contentPadding: EdgeInsets.all(8.0), - hintText: '输入内容...', - ), - ), - ), - ), - ], + @override + Widget build(BuildContext context) { + return Card( + margin: EdgeInsets.zero, + color: Colors.grey[100], + // child: TextEditor( + // editorTitle: '模板解析器', + // initialContent: _currentContent, + // onContentChanged: (newContent) { + // setState(() { + // _currentContent = newContent; + // }); + // }, + // ), ); } } diff --git a/win_text_editor/lib/app/widgets/text_editor.dart b/win_text_editor/lib/app/widgets/text_editor.dart new file mode 100644 index 0000000..c358a5e --- /dev/null +++ b/win_text_editor/lib/app/widgets/text_editor.dart @@ -0,0 +1,181 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class TextEditor extends StatefulWidget { + final String? initialContent; + final String editorTitle; + final bool showToolbar; + final ValueChanged? onContentChanged; + + const TextEditor({ + Key? key, + this.initialContent, + this.editorTitle = '源文本', + this.showToolbar = true, + this.onContentChanged, + }) : super(key: key); + + @override + State createState() => _TextEditorState(); +} + +class _TextEditorState extends State { + late final TextEditingController _textController; + late String _currentFileName; + final ScrollController _scrollController = ScrollController(); + + @override + void initState() { + super.initState(); + _textController = TextEditingController(text: widget.initialContent); + _currentFileName = "未命名文件"; + _textController.addListener(_handleTextChanged); + } + + void _handleTextChanged() { + widget.onContentChanged?.call(_textController.text); + } + + @override + void didUpdateWidget(TextEditor oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.initialContent != oldWidget.initialContent && + widget.initialContent != _textController.text) { + _textController.text = widget.initialContent ?? ''; + } + } + + @override + void dispose() { + _textController.removeListener(_handleTextChanged); + _textController.dispose(); + _scrollController.dispose(); + super.dispose(); + } + + Future _openFile() async { + const String mockFileContent = """这是从文件加载的示例文本: +第1行内容 +第2行内容 +第3行内容"""; + + setState(() { + _textController.text = mockFileContent; + _currentFileName = "示例文件.txt"; + }); + } + + Future _copyToClipboard() async { + if (_textController.text.isNotEmpty) { + await Clipboard.setData(ClipboardData(text: _textController.text)); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已复制全部文本到剪贴板'))); + } + } + } + + Future _saveFile() async { + if (_textController.text.isEmpty) return; + + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('文件 "$_currentFileName" 保存成功'), + duration: const Duration(seconds: 2), + ), + ); + } + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + if (widget.showToolbar) ...[ + Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0), + decoration: BoxDecoration( + color: Colors.blue[50], + border: Border(bottom: BorderSide(color: Colors.grey[300]!)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + widget.editorTitle, + style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold), + ), + Row( + children: [ + IconButton( + icon: const Icon(Icons.folder_open, size: 20), + tooltip: '打开文件', + onPressed: _openFile, + ), + IconButton( + icon: const Icon(Icons.content_copy, size: 20), + tooltip: '复制全部', + onPressed: _copyToClipboard, + ), + IconButton( + icon: const Icon(Icons.save, size: 20), + tooltip: '保存文件', + onPressed: _saveFile, + ), + ], + ), + ], + ), + ), + ], + Expanded(child: _buildEditorField()), + ], + ); + } + + Widget _buildEditorField() { + return ScrollConfiguration( + behavior: _NoScrollBehavior(), + child: SingleChildScrollView( + controller: _scrollController, + physics: const ClampingScrollPhysics(), + child: ConstrainedBox( + constraints: BoxConstraints(minHeight: MediaQuery.of(context).size.height), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _textController, + maxLines: null, + scrollPhysics: const NeverScrollableScrollPhysics(), + decoration: InputDecoration( + hintText: '在此输入文本...', + border: InputBorder.none, + filled: true, + fillColor: Colors.white, + contentPadding: const EdgeInsets.all(12.0), + ), + style: const TextStyle(fontSize: 14), + ), + ), + ), + ), + ); + } +} + +class _NoScrollBehavior extends ScrollBehavior { + @override + Widget buildScrollbar(BuildContext context, Widget child, ScrollableDetails details) { + return child; + } + + @override + Widget buildOverscrollIndicator(BuildContext context, Widget child, ScrollableDetails details) { + return child; + } + + @override + ScrollPhysics getScrollPhysics(BuildContext context) { + return const ClampingScrollPhysics(); + } +} diff --git a/win_text_editor/lib/main.dart b/win_text_editor/lib/main.dart index 2016b5a..675f8d1 100644 --- a/win_text_editor/lib/main.dart +++ b/win_text_editor/lib/main.dart @@ -8,7 +8,7 @@ void main() async { // 配置窗口 await windowManager.ensureInitialized(); WindowOptions windowOptions = const WindowOptions( - size: Size(1800, 1200), + size: Size(1200, 700), center: true, title: '文本转换', );