From 55aeafec7a8786bfa6f5619f88b55c2800300a82 Mon Sep 17 00:00:00 2001 From: hejl Date: Wed, 14 May 2025 16:20:38 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9B=AE=E5=BD=95=E9=87=8D=E6=9E=84=EF=BC=8C?= =?UTF-8?q?=E5=BC=95=E5=85=A5=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- win_text_editor/lib/app/app.dart | 104 ----------------- .../file_explorer.dart | 41 +------ .../{widgets => components}/text_editor.dart | 0 .../lib/app/core/app_scaffold.dart | 46 ++++++++ .../app/{widgets => core}/console_panel.dart | 0 .../lib/app/core/file_explorer_pane.dart | 67 +++++++++++ .../tab_manager.dart} | 27 ++--- win_text_editor/lib/app/core/tab_view.dart | 105 ++++++++++++++++++ win_text_editor/lib/app/menus/app_menu.dart | 5 +- .../lib/app/menus/menu_actions.dart | 37 +++++- .../lib/app/menus/menu_constants.dart | 1 + win_text_editor/lib/app/models/tab_model.dart | 4 +- .../template_parser_controller.dart | 33 ++++++ .../template_parser_service.dart | 7 ++ .../template_parser_view.dart} | 14 +-- .../lib/app/widgets/editor_pane.dart | 84 -------------- win_text_editor/lib/main.dart | 6 +- 17 files changed, 318 insertions(+), 263 deletions(-) delete mode 100644 win_text_editor/lib/app/app.dart rename win_text_editor/lib/app/{widgets => components}/file_explorer.dart (82%) rename win_text_editor/lib/app/{widgets => components}/text_editor.dart (100%) create mode 100644 win_text_editor/lib/app/core/app_scaffold.dart rename win_text_editor/lib/app/{widgets => core}/console_panel.dart (100%) create mode 100644 win_text_editor/lib/app/core/file_explorer_pane.dart rename win_text_editor/lib/app/{providers/tab_provider.dart => core/tab_manager.dart} (81%) create mode 100644 win_text_editor/lib/app/core/tab_view.dart create mode 100644 win_text_editor/lib/app/modules/template_parser/template_parser_controller.dart create mode 100644 win_text_editor/lib/app/modules/template_parser/template_parser_service.dart rename win_text_editor/lib/app/{widgets/template_parser_tab.dart => modules/template_parser/template_parser_view.dart} (91%) delete mode 100644 win_text_editor/lib/app/widgets/editor_pane.dart diff --git a/win_text_editor/lib/app/app.dart b/win_text_editor/lib/app/app.dart deleted file mode 100644 index 55c3645..0000000 --- a/win_text_editor/lib/app/app.dart +++ /dev/null @@ -1,104 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:win_text_editor/app/menus/app_menu.dart'; -import 'package:win_text_editor/app/providers/tab_provider.dart'; -import 'package:win_text_editor/app/providers/file_provider.dart'; -import 'package:win_text_editor/app/widgets/editor_pane.dart'; -import 'package:win_text_editor/app/widgets/file_explorer.dart'; -import 'package:win_text_editor/app/widgets/console_panel.dart'; // 新增导入 - -class AppScaffold extends StatelessWidget { - const AppScaffold({super.key}); - - @override - Widget build(BuildContext context) { - return MultiProvider( - providers: [ - ChangeNotifierProvider(create: (_) => FileProvider()), - ChangeNotifierProvider(create: (_) => TabProvider()), - ], - child: const Scaffold( - body: Column( - children: [ - // 菜单栏 - AppMenu(), - // 主内容区域 - Expanded(child: _ResizablePanel()), - ], - ), - ), - ); - } -} - -class _ResizablePanel extends StatefulWidget { - const _ResizablePanel(); - - @override - State<_ResizablePanel> createState() => _ResizablePanelState(); -} - -class _ResizablePanelState extends State<_ResizablePanel> { - double _leftWidth = 0.2; // 初始宽度20% - final double _minWidth = 100; // 最小宽度 - final double _maxWidth = 400; // 最大宽度 - - @override - Widget build(BuildContext context) { - final screenWidth = MediaQuery.of(context).size.width; - - return LayoutBuilder( - builder: (context, constraints) { - // 计算实际宽度 - final leftPanelWidth = (_leftWidth * screenWidth).clamp(_minWidth, _maxWidth); - - return Column( - children: [ - Expanded( - child: Row( - children: [ - // 左侧文件资源管理器 - 添加Material小部件包裹 - Material( - elevation: 1, // 轻微阴影分隔 - child: SizedBox( - width: leftPanelWidth, - child: const ClipRect( - // 确保内容被裁剪 - child: FileExplorer(), - ), - ), - ), - // 拖拽手柄 - GestureDetector( - behavior: HitTestBehavior.translucent, - onPanUpdate: (details) { - setState(() { - _leftWidth = ((leftPanelWidth + details.delta.dx) / screenWidth).clamp( - _minWidth / screenWidth, - _maxWidth / screenWidth, - ); - }); - }, - child: MouseRegion( - cursor: SystemMouseCursors.resizeLeftRight, - child: Container(width: 4, color: Colors.grey[300]), - ), - ), - // 右侧编辑器区域 - 添加Material背景 - const Expanded( - child: Material( - color: Colors.white, - child: Column(children: [Expanded(child: EditorPane())]), - ), - ), - ], - ), - ), - // 控制台面板 - const ConsolePanel(), - ], - ); - }, - ); - } -} diff --git a/win_text_editor/lib/app/widgets/file_explorer.dart b/win_text_editor/lib/app/components/file_explorer.dart similarity index 82% rename from win_text_editor/lib/app/widgets/file_explorer.dart rename to win_text_editor/lib/app/components/file_explorer.dart index c742659..98efde6 100644 --- a/win_text_editor/lib/app/widgets/file_explorer.dart +++ b/win_text_editor/lib/app/components/file_explorer.dart @@ -4,11 +4,9 @@ import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:win_text_editor/app/providers/logger.dart'; -import 'package:win_text_editor/app/providers/tab_provider.dart'; import '../models/file_node.dart'; import '../providers/file_provider.dart'; -import '../providers/editor_provider.dart'; import 'dart:math'; @@ -60,24 +58,6 @@ class _FileExplorerState extends State { await fileProvider.loadDirectoryContents(node); } else { // Handle file opening - print("No active tab found"); - _openFileInEditor(context, node); - } - } - - Future _openFileInEditor(BuildContext context, FileNode node) async { - if (!node.isDirectory) { - try { - final editorProvider = Provider.of(context, listen: false); - await editorProvider.requestLoadFile(context, node.path); - } catch (e) { - Logger().error("打开文件失败: ${e.toString()}"); - if (context.mounted) { - ScaffoldMessenger.of( - context, - ).showSnackBar(SnackBar(content: Text('打开文件失败: ${e.toString()}'))); - } - } } } @@ -97,17 +77,6 @@ class _FileExplorerState extends State { return maxDepth * 200 + MediaQuery.of(context).size.width * 0.5; } - void _handleNodeDoubleTap(BuildContext context, FileNode node) async { - if (!node.isDirectory) { - // 如果是文件,直接打开 - Logger().info('双击打开文件: ${node.path}', source: 'FileExplorer'); - await _openFileInEditor(context, node); - } else { - // 如果是文件夹,可以执行其他操作或忽略 - Logger().debug('双击文件夹: ${node.path}', source: 'FileExplorer'); - } - } - @override Widget build(BuildContext context) { final fileProvider = Provider.of(context); @@ -149,7 +118,6 @@ class _FileExplorerState extends State { key: ValueKey(node.path), node: node, onTap: () => _handleNodeTap(context, node), - onDoubleTap: () => _handleNodeDoubleTap(context, node), ); }, ), @@ -197,14 +165,8 @@ FileNode _getVisibleNode(List nodes, int index) { class _FileNodeWidget extends StatelessWidget { final FileNode node; final VoidCallback onTap; - final VoidCallback onDoubleTap; // 新增双击回调 - const _FileNodeWidget({ - Key? key, - required this.node, - required this.onTap, - required this.onDoubleTap, // 新增参数 - }) : super(key: key); + const _FileNodeWidget({Key? key, required this.node, required this.onTap}) : super(key: key); @override Widget build(BuildContext context) { @@ -212,7 +174,6 @@ class _FileNodeWidget extends StatelessWidget { return InkWell( onTap: onTap, - onDoubleTap: onDoubleTap, splashColor: Colors.transparent, // 移除水波纹效果 highlightColor: Colors.grey.withOpacity(0.1), // 使用更柔和的悬停颜色 child: Container( diff --git a/win_text_editor/lib/app/widgets/text_editor.dart b/win_text_editor/lib/app/components/text_editor.dart similarity index 100% rename from win_text_editor/lib/app/widgets/text_editor.dart rename to win_text_editor/lib/app/components/text_editor.dart diff --git a/win_text_editor/lib/app/core/app_scaffold.dart b/win_text_editor/lib/app/core/app_scaffold.dart new file mode 100644 index 0000000..5180abc --- /dev/null +++ b/win_text_editor/lib/app/core/app_scaffold.dart @@ -0,0 +1,46 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:win_text_editor/app/core/file_explorer_pane.dart'; +import 'package:win_text_editor/app/core/tab_manager.dart'; +import 'package:win_text_editor/app/core/tab_view.dart'; +import 'package:win_text_editor/app/menus/app_menu.dart'; +import 'package:win_text_editor/app/providers/file_provider.dart'; +import 'package:win_text_editor/app/core/console_panel.dart'; + +class AppScaffold extends StatelessWidget { + const AppScaffold({super.key}); + + @override + Widget build(BuildContext context) { + return MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => FileProvider()), + ChangeNotifierProvider(create: (_) => TabManager()), // 改名为TabManager + ], + child: Scaffold( + body: Column( + children: [ + const AppMenu(), // 顶部菜单 + Expanded( + child: Row( + children: [ + // 左侧文件树 + const FileExplorerPane(), + // 主内容区 + Expanded( + child: Consumer( + builder: + (_, manager, __) => + TabView(tabs: manager.tabs, currentTabId: manager.activeTabId), + ), + ), + ], + ), + ), + const ConsolePanel(), // 底部状态栏 + ], + ), + ), + ); + } +} diff --git a/win_text_editor/lib/app/widgets/console_panel.dart b/win_text_editor/lib/app/core/console_panel.dart similarity index 100% rename from win_text_editor/lib/app/widgets/console_panel.dart rename to win_text_editor/lib/app/core/console_panel.dart diff --git a/win_text_editor/lib/app/core/file_explorer_pane.dart b/win_text_editor/lib/app/core/file_explorer_pane.dart new file mode 100644 index 0000000..783d367 --- /dev/null +++ b/win_text_editor/lib/app/core/file_explorer_pane.dart @@ -0,0 +1,67 @@ +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:win_text_editor/app/providers/file_provider.dart'; +import 'package:win_text_editor/app/widgets/file_explorer.dart'; + +class FileExplorerPane extends StatelessWidget { + const FileExplorerPane({super.key}); + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, fileProvider, child) { + return Material( + elevation: 1, + child: SizedBox( + width: _calculateWidth(context, fileProvider), + child: Column( + children: [ + // 标题栏和操作按钮 + _buildHeader(context), + // 文件树内容 + const Expanded(child: FileExplorer()), + ], + ), + ), + ); + }, + ); + } + + Widget _buildHeader(BuildContext context) { + return Container( + height: 40, + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + color: Colors.grey[100], + border: const Border(bottom: BorderSide(color: Colors.grey)), + ), + child: Row( + children: [ + const Text('文件资源管理器', style: TextStyle(fontWeight: FontWeight.bold)), + const Spacer(), + IconButton( + icon: const Icon(Icons.folder_open, size: 20), + tooltip: '打开文件夹', + onPressed: () => _openDirectory(context), + ), + ], + ), + ); + } + + double _calculateWidth(BuildContext context, FileProvider fileProvider) { + final screenWidth = MediaQuery.of(context).size.width; + final defaultWidth = screenWidth * 0.2; // 默认20%宽度 + return defaultWidth.clamp(200, 400); // 限制最小200,最大400 + } + + Future _openDirectory(BuildContext context) async { + final fileProvider = Provider.of(context, listen: false); + final String? selectedDirectory = await FilePicker.platform.getDirectoryPath(); + if (selectedDirectory != null) { + await fileProvider.setRootPath(selectedDirectory); + } + } +} diff --git a/win_text_editor/lib/app/providers/tab_provider.dart b/win_text_editor/lib/app/core/tab_manager.dart similarity index 81% rename from win_text_editor/lib/app/providers/tab_provider.dart rename to win_text_editor/lib/app/core/tab_manager.dart index 170c000..05c6432 100644 --- a/win_text_editor/lib/app/providers/tab_provider.dart +++ b/win_text_editor/lib/app/core/tab_manager.dart @@ -1,18 +1,18 @@ import 'package:flutter/material.dart'; import 'package:win_text_editor/app/models/tab_model.dart'; +import 'package:win_text_editor/app/modules/template_parser/template_parser_view.dart'; import 'package:win_text_editor/app/providers/logger.dart'; -import 'package:win_text_editor/app/widgets/template_parser_tab.dart'; -class TabProvider with ChangeNotifier { - final List _tabs = []; +class TabManager with ChangeNotifier { + final List _tabs = []; String? _activeTabId; - List get tabs => _tabs; + List get tabs => _tabs; String? get activeTabId => _activeTabId; - final Map _tabControllers = {}; + final Map _tabControllers = {}; - void registerTextTabController(String tabId, TemplateParserTabState controller) { + void registerTextTabController(String tabId, TemplateParserViewState controller) { _tabControllers[tabId] = controller; } @@ -20,7 +20,7 @@ class TabProvider with ChangeNotifier { _tabControllers.remove(tabId); } - ContentTab? get activeTab { + AppTab? get activeTab { if (_activeTabId == null) return null; try { return _tabs.firstWhere((tab) => tab.id == _activeTabId); @@ -30,26 +30,21 @@ class TabProvider with ChangeNotifier { } } - Future addTab({ + Future addTab( + String id, { String title = '未命名', String? type, IconData? icon, String content = '', }) async { - final newTab = ContentTab( - id: DateTime.now().millisecondsSinceEpoch.toString(), - title: title, - type: type, - icon: icon, - content: content, - ); + final newTab = AppTab(id: id, title: title, type: type, icon: icon, content: content); _tabs.add(newTab); _activeTabId = newTab.id; notifyListeners(); } - ContentTab? getTabById(String tabId) { + AppTab? getTabById(String tabId) { try { return _tabs.firstWhere((tab) => tab.id == tabId); } catch (e) { diff --git a/win_text_editor/lib/app/core/tab_view.dart b/win_text_editor/lib/app/core/tab_view.dart new file mode 100644 index 0000000..1c21c92 --- /dev/null +++ b/win_text_editor/lib/app/core/tab_view.dart @@ -0,0 +1,105 @@ +import 'package:flutter/material.dart'; +import 'package:win_text_editor/app/components/text_editor.dart'; +import 'package:win_text_editor/app/core/tab_manager.dart'; +import 'package:win_text_editor/app/models/tab_model.dart'; +import 'package:win_text_editor/app/modules/template_parser/template_parser_view.dart'; +import 'package:provider/provider.dart'; + +class TabView extends StatelessWidget { + final List tabs; + final String? currentTabId; + + const TabView({super.key, required this.tabs, required this.currentTabId}); + + @override + Widget build(BuildContext context) { + final activeTab = tabs.firstWhere( + (tab) => tab.id == currentTabId, + orElse: () => AppTab(id: '', title: ''), // 提供默认值 + ); + + return Column( + children: [ + // 选项卡标签栏 + _buildTabBar(context), + // 选项卡内容区 + Expanded( + child: + activeTab.id.isNotEmpty + ? _buildTabContent(activeTab) + : const Center(child: Text('无活动标签页')), + ), + ], + ); + } + + Widget _buildTabBar(BuildContext context) { + return SizedBox( + height: 40, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: tabs.length, + itemBuilder: (ctx, index) { + final tab = tabs[index]; + return _TabItem( + tab: tab, + isActive: tab.id == currentTabId, + onClose: () => context.read().closeTab(tab.id), + onTap: () => context.read().setActiveTab(tab.id), + ); + }, + ), + ); + } + + Widget _buildTabContent(AppTab tab) { + switch (tab.type) { + case 'template_parser': + return TemplateParserView(tabId: tab.id); // 使用选项卡的ID而不是新生成 + case 'content_search': + // return const ContentSearchView(); + return Container(); // 临时占位 + default: + return TextEditor(tabId: tab.id, initialContent: tab.content); + } + } +} + +class _TabItem extends StatelessWidget { + final AppTab tab; + final bool isActive; + final VoidCallback onClose; + final VoidCallback onTap; + + const _TabItem({ + required this.tab, + required this.isActive, + required this.onClose, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: isActive ? Colors.blue[100] : Colors.grey[200], + border: Border( + bottom: BorderSide(color: isActive ? Colors.blue : Colors.transparent, width: 2), + ), + ), + child: Row( + children: [ + if (tab.icon != null) Icon(tab.icon, size: 16), + if (tab.icon != null) const SizedBox(width: 4), + Text(tab.title), + const SizedBox(width: 8), + IconButton(icon: const Icon(Icons.close, size: 16), onPressed: onClose), + ], + ), + ), + ); + } +} diff --git a/win_text_editor/lib/app/menus/app_menu.dart b/win_text_editor/lib/app/menus/app_menu.dart index 29c5c05..6369f7b 100644 --- a/win_text_editor/lib/app/menus/app_menu.dart +++ b/win_text_editor/lib/app/menus/app_menu.dart @@ -24,7 +24,10 @@ class AppMenu extends StatelessWidget { } List> _buildToolsMenuItems() { - return [const PopupMenuItem(value: MenuConstants.templateParser, child: Text('模板解析'))]; + return [ + const PopupMenuItem(value: MenuConstants.contentSearch, child: Text('内容搜索')), + const PopupMenuItem(value: MenuConstants.templateParser, child: Text('模板解析')), + ]; } Widget _buildMenuButton(BuildContext context, String label, List> items) { diff --git a/win_text_editor/lib/app/menus/menu_actions.dart b/win_text_editor/lib/app/menus/menu_actions.dart index c807c24..0a5a52a 100644 --- a/win_text_editor/lib/app/menus/menu_actions.dart +++ b/win_text_editor/lib/app/menus/menu_actions.dart @@ -1,9 +1,9 @@ import 'package:flutter/material.dart'; import 'package:file_picker/file_picker.dart'; import 'package:provider/provider.dart'; +import 'package:win_text_editor/app/core/tab_manager.dart'; import 'package:win_text_editor/app/menus/menu_constants.dart'; import 'package:win_text_editor/app/providers/file_provider.dart'; -import 'package:win_text_editor/app/providers/tab_provider.dart'; import 'package:collection/collection.dart'; import 'dart:io'; @@ -14,11 +14,20 @@ class MenuActions { static const IconData templateParserTabIcon = Icons.auto_awesome_mosaic; static const String templateParserDefaultContent = ""; + // 定义内容搜索选项卡的常量 + static const String contentSearchTabType = "content_search"; + static const String contentSearchTabTitle = "内容搜索"; + static const IconData contentSearchTabIcon = Icons.search; + static const String contentSearchDefaultContent = ""; + static Future handleMenuAction(String value, BuildContext context) async { switch (value) { case MenuConstants.openFolder: await _openFolder(context); break; + case MenuConstants.contentSearch: // 新增内容搜索菜单项 + await _openContentSearch(context); + break; case MenuConstants.templateParser: await _openTemplateParser(context); break; @@ -38,20 +47,36 @@ class MenuActions { } } + static Future _openContentSearch(BuildContext context) async { + final tabManager = Provider.of(context, listen: false); + + // Create new tab with unique ID + final tabId = DateTime.now().millisecondsSinceEpoch.toString(); + + await tabManager.addTab( + tabId, + title: contentSearchTabTitle, + type: contentSearchTabType, + icon: contentSearchTabIcon, + content: contentSearchDefaultContent, + ); + } + static Future _openTemplateParser(BuildContext context) async { - final editorProvider = Provider.of(context, listen: false); + final tabManager = Provider.of(context, listen: false); // 使用 firstWhereOrNull 查找选项卡 - final existingTab = editorProvider.tabs.firstWhereOrNull( + final existingTab = tabManager.tabs.firstWhereOrNull( (tab) => tab.type == templateParserTabType, ); if (existingTab != null) { // 如果存在,激活该选项卡 - editorProvider.setActiveTab(existingTab.id); + tabManager.setActiveTab(existingTab.id); } else { - // 如果不存在,创建新选项卡 - await editorProvider.addTab( + final tabId = DateTime.now().millisecondsSinceEpoch.toString(); + await tabManager.addTab( + tabId, title: templateParserTabTitle, type: templateParserTabType, icon: templateParserTabIcon, diff --git a/win_text_editor/lib/app/menus/menu_constants.dart b/win_text_editor/lib/app/menus/menu_constants.dart index a9a5ee6..f937408 100644 --- a/win_text_editor/lib/app/menus/menu_constants.dart +++ b/win_text_editor/lib/app/menus/menu_constants.dart @@ -13,6 +13,7 @@ class MenuConstants { static const String exit = 'exit'; // 工具菜单项 + static const String contentSearch = "content_search"; static const String templateParser = 'template_parser'; // 编辑菜单项 diff --git a/win_text_editor/lib/app/models/tab_model.dart b/win_text_editor/lib/app/models/tab_model.dart index b4e6ef9..f990080 100644 --- a/win_text_editor/lib/app/models/tab_model.dart +++ b/win_text_editor/lib/app/models/tab_model.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; -class ContentTab { +class AppTab { final String id; final String title; final String? type; // 新增类型字段 @@ -8,7 +8,7 @@ class ContentTab { String content; String? fileName; - ContentTab({ + AppTab({ required this.id, required this.title, this.type, diff --git a/win_text_editor/lib/app/modules/template_parser/template_parser_controller.dart b/win_text_editor/lib/app/modules/template_parser/template_parser_controller.dart new file mode 100644 index 0000000..1fe1e83 --- /dev/null +++ b/win_text_editor/lib/app/modules/template_parser/template_parser_controller.dart @@ -0,0 +1,33 @@ +import 'package:flutter/material.dart'; +import 'package:win_text_editor/app/modules/template_parser/template_parser_service.dart'; + +class TemplateParserController with ChangeNotifier { + final TemplateParserService _service = TemplateParserService(); + + String _sourceContent = ''; + String _parsedContent = ''; + String _statusMessage = '准备就绪'; + + String get sourceContent => _sourceContent; + String get parsedContent => _parsedContent; + String get statusMessage => _statusMessage; + + set sourceContent(String value) { + _sourceContent = value; + notifyListeners(); + } + + Future parseTemplates() async { + try { + _statusMessage = '解析中...'; + notifyListeners(); + + _parsedContent = await _service.parse(_sourceContent); + _statusMessage = '解析完成'; + } catch (e) { + _statusMessage = '解析失败: $e'; + } finally { + notifyListeners(); + } + } +} diff --git a/win_text_editor/lib/app/modules/template_parser/template_parser_service.dart b/win_text_editor/lib/app/modules/template_parser/template_parser_service.dart new file mode 100644 index 0000000..251338f --- /dev/null +++ b/win_text_editor/lib/app/modules/template_parser/template_parser_service.dart @@ -0,0 +1,7 @@ +class TemplateParserService { + Future parse(String source) async { + // 实际的模板解析逻辑 + await Future.delayed(const Duration(seconds: 1)); // 模拟耗时操作 + return 'Parssed: $source'; + } +} diff --git a/win_text_editor/lib/app/widgets/template_parser_tab.dart b/win_text_editor/lib/app/modules/template_parser/template_parser_view.dart similarity index 91% rename from win_text_editor/lib/app/widgets/template_parser_tab.dart rename to win_text_editor/lib/app/modules/template_parser/template_parser_view.dart index e7ddf8a..89520c3 100644 --- a/win_text_editor/lib/app/widgets/template_parser_tab.dart +++ b/win_text_editor/lib/app/modules/template_parser/template_parser_view.dart @@ -1,19 +1,19 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -import 'package:win_text_editor/app/providers/tab_provider.dart'; +import 'package:win_text_editor/app/core/tab_manager.dart'; import 'package:win_text_editor/app/widgets/text_editor.dart'; -class TemplateParserTab extends StatefulWidget { +class TemplateParserView extends StatefulWidget { final String tabId; - const TemplateParserTab({super.key, required this.tabId}); + const TemplateParserView({super.key, required this.tabId}); @override - State createState() => TemplateParserTabState(); + State createState() => TemplateParserViewState(); } -class TemplateParserTabState extends State { - late TabProvider _provider; +class TemplateParserViewState extends State { + late TabManager _provider; String? _editor1FileName; String? _editor2FileName; String _editor1Content = ''; @@ -40,7 +40,7 @@ class TemplateParserTabState extends State { @override void initState() { super.initState(); - _provider = Provider.of(context, listen: false); + _provider = Provider.of(context, listen: false); _provider.registerTextTabController(widget.tabId, this); final tab = _provider.getTabById(widget.tabId); if (tab != null) { diff --git a/win_text_editor/lib/app/widgets/editor_pane.dart b/win_text_editor/lib/app/widgets/editor_pane.dart deleted file mode 100644 index d2a46f9..0000000 --- a/win_text_editor/lib/app/widgets/editor_pane.dart +++ /dev/null @@ -1,84 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:win_text_editor/app/providers/tab_provider.dart'; -import 'template_parser_tab.dart'; - -class EditorPane extends StatelessWidget { - const EditorPane({super.key}); - - @override - Widget build(BuildContext context) { - final provider = Provider.of(context); - - return Column( - children: [ - // 标签栏 - SizedBox( - height: 40, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: provider.tabs.length, - itemBuilder: (ctx, index) { - final tab = provider.tabs[index]; - return _TabItem( - title: tab.title, - icon: tab.icon, // 添加图标支持 - isActive: tab.id == provider.activeTabId, - onClose: () => provider.closeTab(tab.id), - onTap: () => provider.setActiveTab(tab.id), - ); - }, - ), - ), - // 内容区 - Expanded( - child: - provider.activeTabId != null && provider.tabs.any((t) => t.id == provider.activeTabId) - ? TemplateParserTab(tabId: provider.activeTabId!) - : const Center(child: Text('无活动标签页')), - ), - ], - ); - } -} - -class _TabItem extends StatelessWidget { - final String title; - final IconData? icon; // 添加图标 - final bool isActive; - final VoidCallback onClose; - final VoidCallback onTap; - - const _TabItem({ - required this.title, - this.icon, - required this.isActive, - required this.onClose, - required this.onTap, - }); - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: onTap, - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 16), - decoration: BoxDecoration( - color: isActive ? Colors.blue[100] : Colors.grey[200], - border: Border( - bottom: BorderSide(color: isActive ? Colors.blue : Colors.transparent, width: 2), - ), - ), - child: Row( - children: [ - if (icon != null) Icon(icon, size: 16), - if (icon != null) const SizedBox(width: 4), - Text(title), - const SizedBox(width: 8), - IconButton(icon: const Icon(Icons.close, size: 16), onPressed: onClose), - ], - ), - ), - ); - } -} diff --git a/win_text_editor/lib/main.dart b/win_text_editor/lib/main.dart index 3d3c53a..570b305 100644 --- a/win_text_editor/lib/main.dart +++ b/win_text_editor/lib/main.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:win_text_editor/app/core/app_scaffold.dart'; import 'package:window_manager/window_manager.dart'; -import 'app/app.dart'; import 'app/providers/logger.dart'; // 新增导入 void main() async { @@ -12,7 +12,7 @@ void main() async { WindowOptions windowOptions = const WindowOptions( size: Size(1200, 700), center: true, - title: '文本转换', + title: '升级工具', ); windowManager.waitUntilReadyToShow(windowOptions, () async { await windowManager.show(); @@ -36,7 +36,7 @@ class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( - title: '文本转换', + title: '升级工具', debugShowCheckedModeBanner: false, theme: ThemeData( primarySwatch: Colors.blue,