|
|
|
@ -1,7 +1,14 @@
@@ -1,7 +1,14 @@
|
|
|
|
|
import 'dart:ui'; |
|
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
|
import 'package:pluto_grid/pluto_grid.dart'; |
|
|
|
|
import 'package:provider/provider.dart'; |
|
|
|
|
import 'package:win_text_editor/framework/controllers/tab_items_controller.dart'; |
|
|
|
|
import 'package:win_text_editor/modules/code_creater/controllers/code_creater_controller.dart'; |
|
|
|
|
import 'package:win_text_editor/modules/outline/models/outline_node.dart'; |
|
|
|
|
import 'package:win_text_editor/shared/components/code_generation_components.dart'; |
|
|
|
|
import 'package:win_text_editor/shared/components/my_pluto_column.dart'; |
|
|
|
|
import 'package:win_text_editor/shared/components/my_pluto_configuration.dart'; |
|
|
|
|
|
|
|
|
|
class CodeCreaterView extends StatefulWidget { |
|
|
|
|
final String tabId; |
|
|
|
@ -14,9 +21,29 @@ class CodeCreaterView extends StatefulWidget {
@@ -14,9 +21,29 @@ class CodeCreaterView extends StatefulWidget {
|
|
|
|
|
class _CodeCreaterViewState extends State<CodeCreaterView> { |
|
|
|
|
late final CodeCreaterController _controller; |
|
|
|
|
bool _isControllerFromTabManager = false; |
|
|
|
|
PlutoGridStateManager? _stateManager; |
|
|
|
|
|
|
|
|
|
final List<String> operations = ['逻辑服务', '逻辑函数', '原子服务', '原子函数']; |
|
|
|
|
final TextEditingController _codeController = TextEditingController(); |
|
|
|
|
|
|
|
|
|
String? _selectedOperation = '原子函数'; |
|
|
|
|
|
|
|
|
|
get tabManager => Provider.of<TabItemsController>(context, listen: false); |
|
|
|
|
|
|
|
|
|
final ScrollController _scrollController = ScrollController(); |
|
|
|
|
|
|
|
|
|
// 动态计算表格宽度 |
|
|
|
|
double _calculateTableWidth() { |
|
|
|
|
const columnSpacing = 16.0; |
|
|
|
|
double totalWidth = 0; |
|
|
|
|
|
|
|
|
|
for (var column in _buildColumns()) { |
|
|
|
|
totalWidth += column.width + columnSpacing; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return totalWidth + 100; // 额外留白 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
void initState() { |
|
|
|
|
super.initState(); |
|
|
|
@ -30,18 +57,184 @@ class _CodeCreaterViewState extends State<CodeCreaterView> {
@@ -30,18 +57,184 @@ class _CodeCreaterViewState extends State<CodeCreaterView> {
|
|
|
|
|
_isControllerFromTabManager = false; |
|
|
|
|
tabManager.registerController(widget.tabId, _controller); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_controller.addListener(_handleControllerUpdate); // 添加监听 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void _handleControllerUpdate() { |
|
|
|
|
setState(() {}); // 控制器通知时刷新 UI |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
void dispose() { |
|
|
|
|
_controller.removeListener(_handleControllerUpdate); // 移除监听 |
|
|
|
|
_scrollController.dispose(); // 释放滚动控制器 |
|
|
|
|
if (!_isControllerFromTabManager) { |
|
|
|
|
_controller.dispose(); |
|
|
|
|
} |
|
|
|
|
_codeController.dispose(); |
|
|
|
|
|
|
|
|
|
super.dispose(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@override |
|
|
|
|
Widget build(BuildContext context) { |
|
|
|
|
return const Center(child: Text('demo')); |
|
|
|
|
return Row( |
|
|
|
|
children: [ |
|
|
|
|
// 左侧 PlutoGrid (40%) |
|
|
|
|
Expanded( |
|
|
|
|
flex: 4, |
|
|
|
|
child: Padding( |
|
|
|
|
padding: const EdgeInsets.all(8.0), |
|
|
|
|
child: ScrollConfiguration( |
|
|
|
|
behavior: ScrollConfiguration.of(context).copyWith( |
|
|
|
|
dragDevices: { |
|
|
|
|
PointerDeviceKind.touch, |
|
|
|
|
PointerDeviceKind.mouse, |
|
|
|
|
PointerDeviceKind.stylus, |
|
|
|
|
PointerDeviceKind.trackpad, |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
child: Scrollbar( |
|
|
|
|
controller: _scrollController, // 需要添加的控制器 |
|
|
|
|
thickness: 12.0, |
|
|
|
|
thumbVisibility: true, |
|
|
|
|
interactive: true, // Windows必须设置为true |
|
|
|
|
child: SingleChildScrollView( |
|
|
|
|
controller: _scrollController, // 使用同一个控制器 |
|
|
|
|
scrollDirection: Axis.horizontal, |
|
|
|
|
child: SizedBox( |
|
|
|
|
width: _calculateTableWidth(), // 动态计算宽度 |
|
|
|
|
child: PlutoGrid( |
|
|
|
|
key: ValueKey('pluto_grid_${_controller.members.length}'), |
|
|
|
|
configuration: MyPlutoGridConfiguration(), |
|
|
|
|
columns: _buildColumns(), |
|
|
|
|
mode: PlutoGridMode.normal, |
|
|
|
|
rows: _controller.members.isEmpty ? [] : _buildRows(_controller), |
|
|
|
|
noRowsWidget: const Center(child: Text('无大纲节点')), |
|
|
|
|
onLoaded: (PlutoGridOnLoadedEvent event) { |
|
|
|
|
_stateManager ??= event.stateManager; |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
// 右侧 CodeGenerationSection (60%) |
|
|
|
|
Expanded( |
|
|
|
|
flex: 6, |
|
|
|
|
child: Padding( |
|
|
|
|
padding: const EdgeInsets.all(4.0), |
|
|
|
|
child: CodeGenerationSection( |
|
|
|
|
title: '生成代码', |
|
|
|
|
codeController: _codeController, |
|
|
|
|
onNodeDropped: (node) => _controller.onDropOutlineNode(node), |
|
|
|
|
child: OperationRadioSection( |
|
|
|
|
operations: operations, |
|
|
|
|
selectedOperation: _selectedOperation, |
|
|
|
|
onOperationSelected: _selectOperation, |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
), |
|
|
|
|
], |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List<PlutoColumn> _buildColumns() { |
|
|
|
|
return [ |
|
|
|
|
MyPlutoColumn(title: '#', field: 'rowNum', width: 40), |
|
|
|
|
MyPlutoColumn(title: '成员', field: 'content', type: PlutoColumnType.text(), width: 300), |
|
|
|
|
MyPlutoColumn(title: '选择类型', field: 'type', editable: true, width: 200), |
|
|
|
|
MyPlutoColumn( |
|
|
|
|
title: '操作', |
|
|
|
|
field: 'action', |
|
|
|
|
width: 150, |
|
|
|
|
renderer: (rendererContext) { |
|
|
|
|
final result = rendererContext.row.cells['action']!.value as OutlineNode; |
|
|
|
|
final index = rendererContext.row.cells['rowNum']!.value - 1; |
|
|
|
|
final canMoveUp = index > 0; |
|
|
|
|
final canMoveDown = index < _controller.members.length - 1; |
|
|
|
|
|
|
|
|
|
return Row( |
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center, |
|
|
|
|
children: [ |
|
|
|
|
IconButton( |
|
|
|
|
icon: Icon( |
|
|
|
|
Icons.arrow_upward, |
|
|
|
|
size: 12, |
|
|
|
|
color: canMoveUp ? Colors.blue : Colors.grey, |
|
|
|
|
), |
|
|
|
|
onPressed: |
|
|
|
|
canMoveUp ? () => _moveMember(context, rendererContext.row, result, -1) : null, |
|
|
|
|
), |
|
|
|
|
IconButton( |
|
|
|
|
icon: Icon( |
|
|
|
|
Icons.arrow_downward, |
|
|
|
|
size: 12, |
|
|
|
|
color: canMoveDown ? Colors.blue : Colors.grey, |
|
|
|
|
), |
|
|
|
|
onPressed: |
|
|
|
|
canMoveDown ? () => _moveMember(context, rendererContext.row, result, 1) : null, |
|
|
|
|
), |
|
|
|
|
IconButton( |
|
|
|
|
icon: const Icon(Icons.delete_forever, size: 12, color: Colors.red), |
|
|
|
|
onPressed: () => _deleteMember(context, rendererContext.row, result), |
|
|
|
|
), |
|
|
|
|
], |
|
|
|
|
); |
|
|
|
|
}, |
|
|
|
|
), |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void _moveMember(BuildContext context, PlutoRow row, OutlineNode result, int direction) { |
|
|
|
|
final index = row.cells['rowNum']!.value - 1; |
|
|
|
|
final newIndex = index + direction; |
|
|
|
|
|
|
|
|
|
if (newIndex >= 0 && newIndex < _controller.members.length) { |
|
|
|
|
setState(() { |
|
|
|
|
final member = _controller.members.removeAt(index); |
|
|
|
|
_controller.members.insert(newIndex, member); |
|
|
|
|
_controller.notifyListeners(); // 通知监听器更新 |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
List<PlutoRow> _buildRows(CodeCreaterController controller) { |
|
|
|
|
return [ |
|
|
|
|
...controller.members.asMap().entries.map((entry) { |
|
|
|
|
final index = entry.key; |
|
|
|
|
final member = entry.value; |
|
|
|
|
return PlutoRow( |
|
|
|
|
key: ValueKey('${member.hashCode}_$index'), // 复合key确保唯一性 |
|
|
|
|
cells: { |
|
|
|
|
'rowNum': PlutoCell(value: index + 1), |
|
|
|
|
'content': PlutoCell(value: member.title), |
|
|
|
|
'type': PlutoCell(value: member.value), |
|
|
|
|
'action': PlutoCell(value: member), |
|
|
|
|
}, |
|
|
|
|
); |
|
|
|
|
}), |
|
|
|
|
]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void _selectOperation(String? operation) { |
|
|
|
|
setState(() { |
|
|
|
|
_selectedOperation = operation; |
|
|
|
|
_updateDisplay(); |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void _updateDisplay() { |
|
|
|
|
if (_selectedOperation != null) { |
|
|
|
|
_codeController.text = _controller.genCodeString([_selectedOperation!]) ?? ''; |
|
|
|
|
} else { |
|
|
|
|
_codeController.text = ''; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void _deleteMember(BuildContext context, PlutoRow row, OutlineNode result) {} |
|
|
|
|
} |
|
|
|
|