LCOV - code coverage report
Current view: top level - components/widget_detail_inspector - widget_detail_inspector.dart (source / functions) Hit Total Coverage
Test: new_lcov.info Lines: 142 155 91.6 %
Date: 2021-11-22 14:23:42 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:async';
       2             : import 'dart:convert';
       3             : import 'dart:math';
       4             : import 'package:flutter/material.dart';
       5             : import 'package:flutter_ume_kit_ui/components/hit_test.dart';
       6             : import 'package:flutter_ume/flutter_ume.dart';
       7             : import 'search_bar.dart';
       8             : import 'icon.dart' as icon;
       9             : 
      10             : class WidgetDetailInspector extends StatelessWidget implements Pluggable {
      11           2 :   const WidgetDetailInspector({Key? key}) : super(key: key);
      12             : 
      13           1 :   @override
      14             :   Widget build(BuildContext context) {
      15           1 :     return MaterialApp(
      16           1 :       theme: ThemeData(primaryColor: Colors.white),
      17           1 :       home: _DetailPage(),
      18             :     );
      19             :   }
      20             : 
      21           1 :   @override
      22             :   Widget buildWidget(BuildContext? context) => this;
      23             : 
      24           1 :   @override
      25             :   ImageProvider<Object> get iconImageProvider =>
      26           2 :       MemoryImage(base64Decode(icon.iconData));
      27             : 
      28           1 :   @override
      29             :   String get name => 'WidgetDetail';
      30             : 
      31           0 :   @override
      32             :   String get displayName => 'WidgetDetail';
      33             : 
      34           1 :   @override
      35             :   void onTrigger() {}
      36             : }
      37             : 
      38             : class _DetailPage extends StatefulWidget {
      39           2 :   const _DetailPage({Key? key}) : super(key: key);
      40             : 
      41           1 :   @override
      42           1 :   _DetailPageState createState() => _DetailPageState();
      43             : }
      44             : 
      45             : class _DetailPageState extends State<_DetailPage> with WidgetsBindingObserver {
      46           3 :   _DetailPageState() : selection = WidgetInspectorService.instance.selection;
      47             : 
      48             :   final window = WidgetsBinding.instance!.window;
      49             : 
      50             :   Offset? _lastPointerLocation;
      51             : 
      52             :   final InspectorSelection selection;
      53             : 
      54           1 :   void _inspectAt(Offset? position) {
      55           1 :     final List<RenderObject> selected = HitTest.hitTest(position);
      56           2 :     setState(() {
      57           2 :       selection.candidates = selected;
      58             :     });
      59             :   }
      60             : 
      61           1 :   void _handlePanDown(DragDownDetails event) {
      62           2 :     _lastPointerLocation = event.globalPosition;
      63           2 :     _inspectAt(event.globalPosition);
      64             :   }
      65             : 
      66           1 :   void _handleTap() {
      67           1 :     if (_lastPointerLocation != null) {
      68           2 :       _inspectAt(_lastPointerLocation);
      69             :     }
      70           3 :     Future.delayed(Duration(milliseconds: 100), () {
      71           5 :       Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
      72           1 :         return _InfoPage(
      73           3 :             elements: selection.currentElement!.debugGetDiagnosticChain());
      74             :       }));
      75             :     });
      76             :   }
      77             : 
      78           1 :   @override
      79             :   void initState() {
      80           1 :     super.initState();
      81           2 :     selection.clear();
      82             :   }
      83             : 
      84           1 :   @override
      85             :   Widget build(BuildContext context) {
      86           1 :     List<Widget> children = <Widget>[];
      87           1 :     GestureDetector gesture = GestureDetector(
      88           1 :       onTap: _handleTap,
      89           1 :       onPanDown: _handlePanDown,
      90             :       behavior: HitTestBehavior.translucent,
      91           1 :       child: IgnorePointer(
      92           1 :         child: Container(
      93           3 :             width: MediaQuery.of(context).size.width,
      94           3 :             height: MediaQuery.of(context).size.height),
      95             :       ),
      96             :     );
      97           1 :     children.add(gesture);
      98           2 :     children.add(InspectorOverlay(
      99           1 :         selection: selection, needDescription: false, needEdges: false));
     100           1 :     return Stack(children: children, textDirection: TextDirection.ltr);
     101             :   }
     102             : }
     103             : 
     104             : class _DetailModel {
     105             :   List<int> colors = [
     106             :     Random().nextInt(256),
     107             :     Random().nextInt(256),
     108             :     Random().nextInt(256)
     109             :   ];
     110             :   Element element;
     111           1 :   _DetailModel(this.element);
     112             : }
     113             : 
     114             : class _InfoPage extends StatefulWidget {
     115           1 :   const _InfoPage({Key? key, required this.elements})
     116           0 :       : assert(elements != null),
     117           1 :         super(key: key);
     118             : 
     119             :   final List<Element> elements;
     120             : 
     121           1 :   @override
     122           1 :   __InfoPageState createState() => __InfoPageState();
     123             : }
     124             : 
     125             : class __InfoPageState extends State<_InfoPage> {
     126             :   List<_DetailModel> _showList = <_DetailModel>[];
     127             :   late List<_DetailModel> _originalList;
     128             : 
     129           1 :   @override
     130             :   void initState() {
     131           1 :     super.initState();
     132           4 :     widget.elements.forEach((f) {
     133           3 :       _showList.add(_DetailModel(f));
     134             :     });
     135           2 :     _originalList = _showList;
     136             :   }
     137             : 
     138           1 :   Widget _dot(List<int> colors) {
     139           4 :     Color randomColor = Color.fromARGB(255, colors[0], colors[1], colors[2]);
     140           1 :     return Container(
     141           1 :       decoration: BoxDecoration(
     142             :         shape: BoxShape.circle,
     143             :         color: randomColor,
     144             :       ),
     145             :       width: 10,
     146             :       height: 10,
     147             :     );
     148             :   }
     149             : 
     150           1 :   Widget _cell(_DetailModel model, BuildContext context) {
     151           1 :     return GestureDetector(
     152           1 :       onTap: () {
     153           4 :         Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
     154           1 :           return Scaffold(
     155           2 :               body: _DetailContent(element: model.element),
     156           1 :               appBar: PreferredSize(
     157           2 :                   child: AppBar(elevation: 0.0, title: Text("widget_detail")),
     158           1 :                   preferredSize: Size.fromHeight(44)));
     159             :         }));
     160             :       },
     161           1 :       child: Container(
     162             :         margin: const EdgeInsets.only(top: 6, bottom: 6, left: 12, right: 12),
     163           1 :         child: Row(
     164           1 :           children: [
     165           1 :             Padding(
     166             :                 padding: const EdgeInsets.only(right: 12),
     167           2 :                 child: _dot(model.colors)),
     168           1 :             Expanded(
     169           1 :                 child: Text(
     170           4 :               "${model.element.widget.toStringShort()}",
     171           1 :               style: TextStyle(fontSize: 15),
     172             :             ))
     173             :           ],
     174             :         ),
     175             :       ),
     176             :     );
     177             :   }
     178             : 
     179           0 :   void _textChange(String query) {
     180           0 :     query = query.trim();
     181           0 :     List<_DetailModel> infoList = [];
     182           0 :     _originalList.forEach((_DetailModel model) {
     183           0 :       var regExp = RegExp("$query", caseSensitive: false);
     184           0 :       if (regExp.hasMatch(model.element.widget.toStringShort())) {
     185           0 :         infoList.add(model);
     186             :       }
     187             :     });
     188           0 :     setState(() {
     189           0 :       _showList = infoList;
     190             :     });
     191             :   }
     192             : 
     193           1 :   @override
     194             :   Widget build(BuildContext context) {
     195           1 :     return Scaffold(
     196             :         resizeToAvoidBottomInset: false,
     197           1 :         body: Container(
     198           1 :           child: Column(
     199           1 :             children: <Widget>[
     200           1 :               Padding(
     201             :                 padding: const EdgeInsets.only(
     202             :                     left: 12, right: 12, top: 10, bottom: 10),
     203           1 :                 child: SearchBar(
     204           1 :                     placeHolder: '请输入要搜索的widget', onChangeHandle: _textChange),
     205             :               ),
     206           1 :               Expanded(
     207           1 :                 child: GestureDetector(
     208           1 :                   onPanDown: (_) {
     209           3 :                     FocusScope.of(context).requestFocus(FocusNode());
     210             :                   },
     211           1 :                   child: ListView.builder(
     212           1 :                       physics: BouncingScrollPhysics(),
     213           1 :                       itemBuilder: (_, index) {
     214           2 :                         _DetailModel model = _showList[index];
     215           1 :                         return _cell(model, context);
     216             :                       },
     217           2 :                       itemCount: _showList.length),
     218             :                 ),
     219             :               ),
     220             :             ],
     221             :           ),
     222             :         ),
     223           1 :         appBar: PreferredSize(
     224           1 :             child: AppBar(
     225             :                 elevation: 0.0,
     226           1 :                 title: RichText(
     227           1 :                   text: TextSpan(
     228             :                     text: 'widget_build_chain',
     229           1 :                     style: TextStyle(
     230             :                         color: Colors.black,
     231             :                         fontSize: 19,
     232             :                         fontWeight: FontWeight.w500,
     233             :                         fontFamily: "PingFang SC"),
     234           1 :                     children: <TextSpan>[
     235           1 :                       TextSpan(
     236           4 :                           text: '  depth: ${widget.elements.length}',
     237           1 :                           style: TextStyle(color: Colors.black, fontSize: 11)),
     238             :                     ],
     239             :                   ),
     240             :                 )),
     241           1 :             preferredSize: Size.fromHeight(44)));
     242             :   }
     243             : }
     244             : 
     245             : class _DetailContent extends StatelessWidget {
     246           1 :   const _DetailContent({Key? key, required this.element})
     247           0 :       : assert(element != null),
     248           1 :         super(key: key);
     249             : 
     250             :   final Element element;
     251             : 
     252           1 :   Widget _titleWidget(String title) {
     253           1 :     return Padding(
     254             :       padding: const EdgeInsets.only(top: 12, left: 12),
     255           1 :       child: Text(
     256             :         title,
     257             :         style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
     258             :       ),
     259             :     );
     260             :   }
     261             : 
     262           1 :   Future<List<String>> getInfo() async {
     263           1 :     Completer<List<String>> completer = Completer();
     264           3 :     String string = element.renderObject!.toStringDeep();
     265           1 :     List<String> list = string.split("\n");
     266           1 :     completer.complete(list);
     267           1 :     return completer.future;
     268             :   }
     269             : 
     270           1 :   @override
     271             :   Widget build(BuildContext context) {
     272           1 :     return FutureBuilder(
     273           1 :         future: getInfo(),
     274           1 :         builder: (_, snapshot) {
     275           2 :           if (snapshot.connectionState == ConnectionState.waiting) {
     276           1 :             return Center(
     277           1 :                 child: CircularProgressIndicator(
     278           1 :                     valueColor: AlwaysStoppedAnimation<Color>(Colors.red)));
     279           2 :           } else if (snapshot.connectionState == ConnectionState.done) {
     280           1 :             return Container(
     281           1 :               child: Column(
     282             :                 crossAxisAlignment: CrossAxisAlignment.start,
     283           1 :                 children: [
     284           1 :                   _titleWidget("Widget Description"),
     285           1 :                   Container(
     286           1 :                       constraints: BoxConstraints(maxHeight: 200),
     287             :                       padding:
     288             :                           const EdgeInsets.only(top: 12, left: 12, right: 12),
     289           1 :                       child: SingleChildScrollView(
     290           4 :                           child: Text(element.widget.toStringDeep()))),
     291           1 :                   _titleWidget("RenderObject Description"),
     292           1 :                   Expanded(
     293           1 :                       child: Padding(
     294             :                           padding: const EdgeInsets.only(
     295             :                               top: 12, right: 12, left: 12),
     296           1 :                           child: ListView.builder(
     297           1 :                               physics: BouncingScrollPhysics(),
     298           1 :                               itemBuilder: (_, index) {
     299           1 :                                 return SingleChildScrollView(
     300           1 :                                     child: Text(
     301           2 :                                         (snapshot.data as List<String>)[index]),
     302             :                                     scrollDirection: Axis.horizontal);
     303             :                               },
     304             :                               itemCount:
     305           2 :                                   (snapshot.data as List<String>).length))),
     306             :                 ],
     307             :               ),
     308             :             );
     309             :           } else {
     310           0 :             return Container();
     311             :           }
     312             :         });
     313             :   }
     314             : }

Generated by: LCOV version 1.15