You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.2 KiB
113 lines
3.2 KiB
import 'package:flutter/material.dart'; |
|
import 'package:provider/provider.dart'; |
|
import 'package:win_text_editor/shared/components/text_editor.dart'; |
|
import 'package:win_text_editor/frame/widgets/tab_manager.dart'; |
|
import 'package:win_text_editor/frame/models/tab_model.dart'; |
|
import 'package:win_text_editor/modules/content_search/widgets/content_search_view.dart'; |
|
|
|
class TabView extends StatelessWidget { |
|
final List<AppTab> 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<TabManager>().closeTab(tab.id), |
|
onTap: () => context.read<TabManager>().setActiveTab(tab.id), |
|
); |
|
}, |
|
), |
|
); |
|
} |
|
|
|
Widget _buildTabContent(AppTab tab) { |
|
return IndexedStack( |
|
index: tabs.indexWhere((tab) => tab.id == currentTabId).clamp(0, tabs.length - 1), |
|
children: |
|
tabs.map((tab) { |
|
return findActiveView(tab); |
|
}).toList(), |
|
); |
|
} |
|
|
|
// 查找当前活动的视图 |
|
Widget findActiveView(AppTab tab) { |
|
switch (tab.type) { |
|
case 'content_search': |
|
return ContentSearchView(tabId: tab.id); |
|
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), |
|
], |
|
), |
|
), |
|
); |
|
} |
|
}
|
|
|