Browse Source

模板解析框架ok

master
hejl 2 months ago
parent
commit
7791466235
  1. 22
      win_text_editor/lib/framework/controllers/tab_items_controller.dart
  2. 5
      win_text_editor/lib/framework/widgets/tab_view.dart
  3. 3
      win_text_editor/lib/modules/content_search/widgets/content_search_view.dart
  4. 85
      win_text_editor/lib/modules/template_parser/controllers/template_parser_controller.dart
  5. 130
      win_text_editor/lib/modules/template_parser/widgets/template_parser_view.dart

22
win_text_editor/lib/framework/controllers/tab_items_controller.dart

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:win_text_editor/framework/models/tab_model.dart';
import 'package:win_text_editor/modules/content_search/controllers/content_search_controller.dart';
import 'package:win_text_editor/modules/template_parser/controllers/template_parser_controller.dart';
import 'package:win_text_editor/shared/base/base_content_controller.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
@ -56,15 +57,28 @@ class TabItemsController with ChangeNotifier { @@ -56,15 +57,28 @@ class TabItemsController with ChangeNotifier {
switch (tab.type) {
case 'content_search':
return ContentSearchController();
case 'template_parser':
return TemplateParserController();
default:
return null;
}
}
BaseContentController? get activeContentController {
if (_activeTabId == null) return null;
if (_activeTabId == null) {
Logger().error("没有活动的选项卡ID", source: 'TabItemsController');
return null;
}
final controller = _contentControllers[_activeTabId];
return controller is BaseContentController ? controller : null;
if (controller == null) {
Logger().error("没有活动的内容控制器,activeTabId:$_activeTabId", source: 'TabItemsController');
return null;
}
if (controller is! BaseContentController) {
Logger().error("活动内容控制器不是BaseContentController类型", source: 'TabItemsController');
return null;
}
return controller;
}
void closeTab(String tabId) {
@ -103,6 +117,10 @@ class TabItemsController with ChangeNotifier { @@ -103,6 +117,10 @@ class TabItemsController with ChangeNotifier {
}
void handleFileDoubleTap(String filePath) {
if (activeContentController == null) {
Logger().error("没有活动的内容控制器", source: 'TabItemsController');
return;
}
activeContentController?.onOpenFile(filePath);
}
}

5
win_text_editor/lib/framework/widgets/tab_view.dart

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/modules/template_parser/widgets/template_parser_view.dart';
import 'package:win_text_editor/shared/components/text_editor.dart';
import 'package:win_text_editor/framework/controllers/tab_items_controller.dart';
import 'package:win_text_editor/framework/models/tab_model.dart';
@ -58,7 +59,9 @@ class _TabViewState extends State<TabView> { @@ -58,7 +59,9 @@ class _TabViewState extends State<TabView> {
Widget _buildTabItem(AppTab tab, ChangeNotifier? controller) {
switch (tab.type) {
case 'content_search':
return ContentSearchView(tabId: tab.id, controller: controller);
return ContentSearchView(tabId: tab.id);
case 'template_parser':
return TemplateParserView(tabId: tab.id);
default:
return TextEditor(tabId: tab.id, initialContent: tab.content);
}

3
win_text_editor/lib/modules/content_search/widgets/content_search_view.dart

@ -7,9 +7,8 @@ import 'search_settings.dart'; @@ -7,9 +7,8 @@ import 'search_settings.dart';
import 'results_view.dart';
class ContentSearchView extends StatefulWidget {
final ChangeNotifier? controller;
final String tabId;
const ContentSearchView({super.key, required this.tabId, this.controller});
const ContentSearchView({super.key, required this.tabId});
@override
ContentSearchViewState createState() => ContentSearchViewState();

85
win_text_editor/lib/modules/template_parser/controllers/template_parser_controller.dart

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
// template_parser_controller.dart
import 'package:file_picker/file_picker.dart';
import 'package:win_text_editor/framework/controllers/logger.dart';
import 'package:win_text_editor/shared/base/base_content_controller.dart';
class TemplateParserController extends BaseContentController {
String _filePath = '';
List<TemplateNode> _treeNodes = [];
List<TemplateItem> _templateItems = [];
// Getters
String get filePath => _filePath;
List<TemplateNode> get treeNodes => _treeNodes;
List<TemplateItem> get templateItems => _templateItems;
Future<void> pickFile() async {
final result = await FilePicker.platform.pickFiles();
if (result != null) {
_filePath = result.files.single.path!;
_loadTemplateData(); // Simulate loading data
notifyListeners();
}
}
void setFilePath(String path) {
_filePath = path;
_loadTemplateData(); // Simulate loading data
notifyListeners();
}
void selectTreeNode(TemplateNode node) {
// Simulate loading items when a tree node is selected
_templateItems = List.generate(
10,
(index) => TemplateItem(id: index + 1, content: 'Content for ${node.name} item ${index + 1}'),
);
notifyListeners();
}
void _loadTemplateData() {
// Simulate loading tree data
_treeNodes = [
TemplateNode('Section 1', [
TemplateNode('Subsection 1.1', []),
TemplateNode('Subsection 1.2', []),
]),
TemplateNode('Section 2', [
TemplateNode('Subsection 2.1', []),
TemplateNode('Subsection 2.2', []),
]),
];
// Simulate loading initial items
_templateItems = List.generate(
15,
(index) => TemplateItem(id: index + 1, content: 'Initial template content ${index + 1}'),
);
}
@override
void onOpenFile(String filePath) {
Logger().info('File selected: $filePath');
setFilePath(filePath);
}
@override
void onOpenFolder(String folderPath) {
// TODO: implement onOpenFolder
}
}
class TemplateNode {
final String name;
final List<TemplateNode> children;
TemplateNode(this.name, this.children);
}
class TemplateItem {
final int id;
final String content;
TemplateItem({required this.id, required this.content});
}

130
win_text_editor/lib/modules/template_parser/widgets/template_parser_view.dart

@ -0,0 +1,130 @@ @@ -0,0 +1,130 @@
// template_parser_view.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:win_text_editor/framework/controllers/tab_items_controller.dart';
import 'package:win_text_editor/modules/template_parser/controllers/template_parser_controller.dart';
class TemplateParserView extends StatefulWidget {
final String tabId;
const TemplateParserView({super.key, required this.tabId});
@override
State<TemplateParserView> createState() => _TemplateParserViewState();
}
class _TemplateParserViewState extends State<TemplateParserView> {
late final TemplateParserController _controller;
get tabManager => Provider.of<TabItemsController>(context, listen: false);
@override
void initState() {
super.initState();
_controller = tabManager.getController(widget.tabId) ?? TemplateParserController();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider.value(
value: _controller,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
_buildFilePathInput(),
const SizedBox(height: 8),
Expanded(child: _buildMainContent()),
],
),
),
);
}
Widget _buildFilePathInput() {
return Consumer<TemplateParserController>(
builder: (context, controller, _) {
return TextField(
decoration: InputDecoration(
labelText: 'Template File',
hintText: 'Select a template file',
suffixIcon: IconButton(
icon: const Icon(Icons.folder_open),
onPressed: controller.pickFile,
),
border: const OutlineInputBorder(),
),
controller: TextEditingController(text: controller.filePath),
readOnly: true,
);
},
);
}
Widget _buildMainContent() {
return Consumer<TemplateParserController>(
builder: (context, controller, _) {
return Row(
children: [
// Tree view (30% width)
SizedBox(
width: MediaQuery.of(context).size.width * 0.3,
child: Card(child: _buildTreeView(controller.treeNodes)),
),
const SizedBox(width: 8),
// Grid view (70% width)
Expanded(child: Card(child: _buildGridView(controller.templateItems))),
],
);
},
);
}
Widget _buildTreeView(List<TemplateNode> nodes) {
return ListView.builder(
itemCount: nodes.length,
itemBuilder: (context, index) {
return _buildTreeNode(nodes[index]);
},
);
}
Widget _buildTreeNode(TemplateNode node) {
return ExpansionTile(
title: Text(node.name),
children: node.children.map((child) => _buildTreeNode(child)).toList(),
onExpansionChanged: (expanded) {
if (expanded) {
Provider.of<TemplateParserController>(context, listen: false).selectTreeNode(node);
}
},
);
}
Widget _buildGridView(List<TemplateItem> items) {
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 5,
),
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [Text('ID: ${item.id}'), Text('Content: ${item.content}')],
),
),
);
},
);
}
}
Loading…
Cancel
Save