This commit is contained in:
toly
2023-10-24 15:52:15 +08:00
parent 9c91d7d7f3
commit 39c38ca975
14 changed files with 231 additions and 338 deletions

View File

@@ -113,6 +113,7 @@ class _DropSelectableWidgetState extends State<DropSelectableWidget>
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(
width: _focused ?1:1/View.of(context).devicePixelRatio,
color: _focused ? Colors.blue : widget.disableColor,
)),
child: Row(

View File

@@ -98,8 +98,7 @@ class AppRouterDelegate extends RouterDelegate<Object> with ChangeNotifier {
child = const CounterPage();
}
if (path == kDestinationsPaths[2]) {
child = LayoutBuilder(
builder: (_,cts)=> SortPage(size: Size(cts.maxWidth,cts.maxHeight),));
child = SortPage();
}
if (path == kDestinationsPaths[3]) {
child = const UserPage();

View File

@@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:iroute/v5/pages/sort/bloc/sort_config.dart';
import '../../../pages/sort/sort_setting.dart';
import '../router/app_router_delegate.dart';
import 'app_navigation_rail.dart';
@@ -13,7 +12,7 @@ class AppNavigation extends StatelessWidget {
double px1 = 1/View.of(context).devicePixelRatio;
return Scaffold(
endDrawer: Drawer(
child: SortSettings(config: sortConfig.value,),
child: SortSettings(),
),
body: Row(
children: [

View File

@@ -2,8 +2,9 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:iroute/components/toly_ui/button/hover_icon_button.dart';
import 'package:iroute/components/toly_ui/popable/drop_selectable_widget.dart';
import 'package:iroute/v5/pages/sort/bloc/sort_config.dart';
import '../../../pages/sort/functions.dart';
import '../../../pages/sort/views/sort_bar.dart';
import '../../../pages/sort/views/sort_button.dart';
import '../router/app_router_delegate.dart';
class AppRouterEditor extends StatefulWidget {
@@ -28,6 +29,9 @@ class _AppRouterEditorState extends State<AppRouterEditor> {
void _onRouteChange() {
_controller.text=router.path;
setState(() {
});
}
@override
@@ -39,58 +43,37 @@ class _AppRouterEditorState extends State<AppRouterEditor> {
@override
Widget build(BuildContext context) {
print(router.path);
if(router.path=='/sort'){
return SortBar();
}
return Row(
children: [
DropSelectableWidget(
fontSize: 12,
data: sortNameMap.values.toList(),
iconSize: 20,
height: 30,
width: 200,
disableColor: const Color(0xff1F425F),
onDropSelected: (int index) async {
sortName.value=sortNameMap.keys.toList()[index];
// curveAnim = CurvedAnimation(
// parent: _ctrl, curve: maps.values.toList()[index]);
// _startAnim();
},
),
const SizedBox(width: 10,),
GestureDetector(
onTap: (){
Scaffold.of(context).openEndDrawer();
// showDialog(
// useRootNavigator: false,
// context: context, builder: (ctx)=>AlertDialog());
},
child: const Icon(Icons.settings))
],
);
return Stack(
alignment: Alignment.centerRight,
children: [
SizedBox(
child: CupertinoTextField(
controller: _controller,
style: TextStyle(fontSize: 14),
padding: EdgeInsets.only(left:12,top: 6,bottom: 6,right: 32),
placeholder: '输入路由地址导航',
onSubmitted: widget.onSubmit,
decoration: BoxDecoration(color: Color(0xffF1F2F3),borderRadius: BorderRadius.circular(6)),
return SizedBox(
width: 250,
child: Stack(
alignment: Alignment.centerRight,
children: [
SizedBox(
child: CupertinoTextField(
controller: _controller,
style: TextStyle(fontSize: 14),
padding: EdgeInsets.only(left:12,top: 6,bottom: 6,right: 32),
placeholder: '输入路由地址导航',
onSubmitted: widget.onSubmit,
decoration: BoxDecoration(color: Color(0xffF1F2F3),borderRadius: BorderRadius.circular(6)),
),
),
),
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: HoverIconButton(
icon: Icons.directions_outlined,
defaultColor: Color(0xff68696B),
onPressed:()=>widget.onSubmit?.call(_controller.text),
size: 20
),
)
],
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: HoverIconButton(
icon: Icons.directions_outlined,
defaultColor: Color(0xff68696B),
onPressed:()=>widget.onSubmit?.call(_controller.text),
size: 20
),
)
],
),
);
}
}

View File

@@ -1,5 +1,5 @@
import 'package:flutter/material.dart';
import '../pages/sort/bloc/state.dart';
import '../pages/sort/provider/state.dart';
import 'navigation/router/app_router_delegate.dart';
import 'navigation/views/app_navigation.dart';
import 'navigation/views/app_navigation_rail.dart';

View File

@@ -1,19 +0,0 @@
import 'dart:ui';
import 'package:flutter/material.dart';
class SortConfig {
final int count;
final int seed;
final Duration duration;
final String name;
SortConfig(this.count, this.duration,this.seed,this.name);
}
final ValueNotifier<SortConfig> sortConfig = ValueNotifier(
SortConfig(-1, const Duration(microseconds: 1500),-1,'quick'),
);
final ValueNotifier<String> sortName = ValueNotifier('quick');

View File

@@ -0,0 +1,31 @@
import 'dart:ui';
import 'package:flutter/material.dart';
class SortConfig {
final int count;
final int seed;
final Duration duration;
final String name;
SortConfig({
this.count = 100,
this.duration = const Duration(microseconds: 1500),
this.seed = -1,
this.name = 'insertion',
});
SortConfig copyWith({
int? count,
int? seed,
Duration? duration,
String? name,
}) =>
SortConfig(
count:count??this.count,
seed:seed??this.seed,
duration:duration??this.duration,
name:name??this.name,
);
}

View File

@@ -13,35 +13,37 @@ enum SortStatus{
class SortState with ChangeNotifier{
SortState(){
reset();
}
SortStatus status = SortStatus.none;
List<int> data = [];
List<int> stepData = [];
SortConfig _config = SortConfig(-1, const Duration(microseconds: 1500),-1,'quick');
SortConfig _config = SortConfig();
SortConfig get config => _config;
Random random = Random();
set config(SortConfig config){
_config = config;
reset(_zoneSize);
reset();
notifyListeners();
}
Size _zoneSize = Size.zero;
void reset(Size zoneSize){
_zoneSize = zoneSize;
status = SortStatus.sorting;
void reset(){
data.clear();
status = SortStatus.none;
notifyListeners();
int count = config.count;
if(count==-1){
count = zoneSize.width~/2;
}
if(config.seed!=-1){
random = Random(config.seed);
}
for (int i = 0; i < count; i++) {
//
data.add(random.nextInt(zoneSize.height.toInt()));
data.add(random.nextInt(1000));
}
}
@@ -53,7 +55,6 @@ class SortState with ChangeNotifier{
if(sortFunction!=null){
await sortFunction(data,(arr) async {
await Future.delayed(config.duration);
data = arr;
notifyListeners();
});
}

View File

@@ -1,34 +1,38 @@
import 'package:flutter/material.dart';
import 'bloc/sort_config.dart';
import 'provider/sort_config.dart';
import 'provider/state.dart';
class SortSettings extends StatefulWidget {
final SortConfig config;
const SortSettings({super.key,required this.config});
const SortSettings({super.key,});
@override
State<SortSettings> createState() => _SortSettingsState();
}
class _SortSettingsState extends State<SortSettings> {
late TextEditingController _count =
TextEditingController();
late TextEditingController _duration = TextEditingController();
late TextEditingController _seed =
TextEditingController();
late TextEditingController _count = TextEditingController(
text:sortConfig.value.count.toString()
);
late TextEditingController _duration = TextEditingController(
text:sortConfig.value.duration.inMicroseconds.toString()
);
late TextEditingController _seed = TextEditingController(
text:sortConfig.value.seed.toString()
);
@override
void initState() {
// TODO: implement initState
super.initState();
}
@override
void didChangeDependencies() {
print('========_SortSettingsState#didChangeDependencies=============');
super.didChangeDependencies();
SortState state = SortStateScope.of(context);
_count.text = state.config.count.toString();
_duration.text = state.config.duration.inMicroseconds.toString();
_seed.text = state.config.seed.toString();
}
@override
Widget build(BuildContext context) {
return Scaffold(
@@ -50,8 +54,11 @@ class _SortSettingsState extends State<SortSettings> {
Row(
children: [
Text('数据数量(个数):'),
const SizedBox(width: 20,),
Expanded(child: TextField(
const SizedBox(
width: 20,
),
Expanded(
child: TextField(
controller: _count,
)),
],
@@ -59,8 +66,11 @@ class _SortSettingsState extends State<SortSettings> {
Row(
children: [
Text('时间间隔(微秒):'),
const SizedBox(width: 20,),
Expanded(child: TextField(
const SizedBox(
width: 20,
),
Expanded(
child: TextField(
controller: _duration,
)),
],
@@ -68,21 +78,29 @@ class _SortSettingsState extends State<SortSettings> {
Row(
children: [
Text('随机种子:'),
const SizedBox(width: 20,),
Expanded(child: TextField(
const SizedBox(
width: 20,
),
Expanded(
child: TextField(
controller: _seed,
)),
],
),
Spacer(),
ElevatedButton(onPressed: (){
sortConfig.value = SortConfig(int.parse(_count.text), Duration(
microseconds: int.parse(_duration.text),
),int.parse(_seed.text),sortConfig.value.name);
Navigator.of(context).pop();
}, child: Text('确定设置'))
ElevatedButton(
onPressed: () {
SortState state = SortStateScope.of(context);
state.config =state.config.copyWith(
count: int.parse(_count.text),
duration: Duration(
microseconds: int.parse(_duration.text),
),
seed: int.parse(_seed.text)
);
Navigator.of(context).pop();
},
child: Text('确定设置'))
],
),
),

View File

@@ -19,23 +19,23 @@ class DataPainter extends CustomPainter{
for(int i=0;i<data.length;i++){
int value = data[i];
if (value < height * .10) {
if (value < 1000 * .10) {
paint.color = Colors.blue.shade100;
} else if (value < height * .20) {
} else if (value < 1000 * .20) {
paint.color = Colors.blue.shade200;
} else if (value < height * .30) {
} else if (value < 1000 * .30) {
paint.color = Colors.blue.shade300;
} else if (value < height * .40) {
} else if (value < 1000 * .40) {
paint.color = Colors.blue.shade400;
} else if (value < height * .50) {
} else if (value < 1000 * .50) {
paint.color = Colors.blue.shade500;
} else if (value < height * .60) {
} else if (value < 1000 * .60) {
paint.color = Colors.blue.shade600;
} else if (value < height * .70) {
} else if (value < 1000 * .70) {
paint.color = Colors.blue.shade700;
} else if (value < height * .80) {
} else if (value < 1000 * .80) {
paint.color = Colors.blue.shade800;
} else if (value < height * .90) {
} else if (value < 1000 * .90) {
paint.color = Colors.blue.shade900;
} else {
paint.color = const Color(0xFF011E51);
@@ -44,7 +44,7 @@ class DataPainter extends CustomPainter{
Offset(i * itemWidth+itemWidth/2, 0),
Offset(
i * itemWidth+itemWidth/2,
value.ceilToDouble(),
size.height*(value/1000),
),
paint);
}

View File

@@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:iroute/components/components.dart';
import '../provider/state.dart';
import '../functions.dart';
import 'sort_button.dart';
class SortBar extends StatelessWidget {
const SortBar({super.key});
@override
Widget build(BuildContext context) {
return Row(
children: [
const SortButton(),
const SizedBox(width: 10,),
DropSelectableWidget(
fontSize: 12,
data: sortNameMap.values.toList(),
iconSize: 20,
height: 28,
width: 200,
disableColor: const Color(0xff1F425F),
onDropSelected: (int index) async {
SortState state = SortStateScope.of(context);
state.config =state.config.copyWith(
name: sortNameMap.keys.toList()[index]
);
// curveAnim = CurvedAnimation(
// parent: _ctrl, curve: maps.values.toList()[index]);
// _startAnim();
},
),
const SizedBox(width: 10,),
GestureDetector(
onTap: (){
Scaffold.of(context).openEndDrawer();
// showDialog(
// useRootNavigator: false,
// context: context, builder: (ctx)=>AlertDialog());
},
child: const Icon(Icons.settings))
],
);
}
}

View File

@@ -0,0 +1,40 @@
import 'package:flutter/material.dart';
import '../provider/state.dart';
class SortButton extends StatelessWidget {
const SortButton({super.key});
@override
Widget build(BuildContext context) {
SortState state = SortStateScope.of(context);
VoidCallback? action;
IconData icon;
Color color;
switch (state.status) {
case SortStatus.none:
icon = Icons.not_started_outlined;
color = Colors.green;
action = state.sort;
break;
case SortStatus.sorting:
icon = Icons.stop_circle_outlined;
color = Colors.grey;
action = null;
break;
case SortStatus.sorted:
icon = Icons.refresh;
color = Colors.black;
action = state.reset;
break;
}
return GestureDetector(
onTap: action,
child: Icon(
icon,
color: color,
),
);
}
}

View File

@@ -1,228 +1,22 @@
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import '../bloc/state.dart';
import '../functions.dart';
import '../bloc/sort_config.dart';
import '../provider/state.dart';
import 'data_painter.dart';
class SortPage extends StatefulWidget {
final Size size;
const SortPage({Key? key, required this.size}) : super(key: key);
@override
State<SortPage> createState() => _SortPageState();
}
class _SortPageState extends State<SortPage> {
//存放随机数组
List<int> numbers = [];
//订阅流
StreamController<List<int>> streamController = StreamController();
String get currentSort => sortName.value;
//柱子的数量 -> 生成排序数组的长度
double sampleSize = 0;
//是否排序
bool isSorted = false;
//是否在排序中
bool isSorting = false;
reset() {
isSorted = false;
setSize(sortConfig.value.count);
streamController.add(numbers);
}
Duration getDuration() {
return sortConfig.value.duration;
}
checkAndResetIfSorted() async {
if (isSorted) {
reset();
await Future.delayed(const Duration(milliseconds: 200));
}
}
sort() async {
setState(() {
isSorting = true;
});
await checkAndResetIfSorted();
Stopwatch stopwatch = Stopwatch()..start();
SortFunction? sortFunction = sortFunctionMap[currentSort];
if(sortFunction!=null){
await sortFunction(numbers,(arr) async {
await Future.delayed(getDuration());
streamController.add(arr);
});
}
stopwatch.stop();
print("Sorting completed in ${stopwatch.elapsed.inMilliseconds} ms.");
setState(() {
isSorting = false;
isSorted = true;
});
}
@override
void initState() {
super.initState();
// reset();
print(widget.size);
setSize(sortConfig.value.count);
sortConfig.addListener(_onSortConfigChange);
sortName.addListener(reset);
}
Random random = Random();
void setSize(int count){
int s = count;
numbers.clear();
if(count==-1){
s = widget.size.width~/2;
}
if(sortConfig.value.seed!=-1){
random = Random(sortConfig.value.seed);
}
for (int i = 0; i < s; i++) {
//随机往数组中填值
numbers.add(random.nextInt(widget.size.height.toInt()));
}
setState(() {});
}
@override
void dispose() {
streamController.close();
super.dispose();
}
class SortPage extends StatelessWidget{
@override
Widget build(BuildContext context) {
List<int> numbers = SortStateScope.of(context).data;
SortState state = SortStateScope.of(context);
List<int> numbers = state.data;
return Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.run_circle_outlined),
onPressed: (){
sort();
},
body: CustomPaint(
painter: DataPainter(data: numbers),
child: ConstrainedBox(constraints: BoxConstraints.expand()),
),
body: StreamBuilder<Object>(
initialData: numbers,
stream: streamController.stream,
builder: (context, snapshot) {
List<int> numbers = snapshot.data as List<int>;
return CustomPaint(
size: widget.size,
painter: DataPainter(data: numbers),
);
},
),
// bottomNavigationBar: BottomAppBar(
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceAround,
// children: <Widget>[
// ElevatedButton(
// onPressed: isSorting
// ? null
// : () {
// reset();
// setSort(currentSort);
// },
// child: const Text("重置")),
// ElevatedButton(
// onPressed: isSorting ? null : sort, child: const Text("开始排序")),
// ElevatedButton(
// onPressed: isSorting ? null : changeSpeed,
// child: Text(
// "${speed + 1}x",
// style: const TextStyle(fontSize: 20),
// ),
// ),
// ],
// ),
// ),
);
}
void _onSortConfigChange() {
setSize(sortConfig.value.count);
}
}
class BarPainter extends CustomPainter {
//宽度
final double width;
final double height;
//高度(数组中对应的值)
final int value;
//位置索引
final int index;
BarPainter({required this.width, required this.height,required this.value, required this.index});
@override
void paint(Canvas canvas, Size size) {
Paint paint = Paint();
// double rate = value/height;
// print(rate);
// paint.color = Colors.blue.withOpacity(rate);
if (value < 500 * .10) {
paint.color = Colors.blue.shade100;
} else if (value < height * .20) {
paint.color = Colors.blue.shade200;
} else if (value < height * .30) {
paint.color = Colors.blue.shade300;
} else if (value < height * .40) {
paint.color = Colors.blue.shade400;
} else if (value < height * .50) {
paint.color = Colors.blue.shade500;
} else if (value < height * .60) {
paint.color = Colors.blue.shade600;
} else if (value < height * .70) {
paint.color = Colors.blue.shade700;
} else if (value < height * .80) {
paint.color = Colors.blue.shade800;
} else if (value < height * .90) {
paint.color = Colors.blue.shade900;
} else {
paint.color = const Color(0xFF011E51);
}
paint.strokeWidth = width;
paint.strokeCap = StrokeCap.round;
canvas.drawLine(
Offset(index * width+width/2, 0),
Offset(
index * width+width/2,
value.ceilToDouble(),
),
paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return true;
}
}

View File

@@ -26,7 +26,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
FlutterWindow window(project);
Win32Window::Point origin(10, 10);
Win32Window::Size size(640, 360);
Win32Window::Size size(1600, 1200);
if (!window.Create(L"iroute", origin, size)) {
return EXIT_FAILURE;
}