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

          Line data    Source code
       1             : import 'dart:convert';
       2             : import 'dart:typed_data';
       3             : import 'dart:ui' as ui;
       4             : import 'package:flutter/material.dart';
       5             : import 'package:flutter/rendering.dart';
       6             : import 'package:image/image.dart' as img;
       7             : import 'package:flutter_ume/flutter_ume.dart';
       8             : import 'icon.dart' as icon;
       9             : 
      10             : class ColorSucker extends StatefulWidget implements Pluggable {
      11             :   final double scale;
      12             :   final Size size;
      13             : 
      14           1 :   const ColorSucker({
      15             :     Key? key,
      16             :     this.scale = 10.0,
      17             :     this.size = const Size(100, 100),
      18           1 :   }) : super(key: key);
      19             : 
      20           1 :   @override
      21           1 :   _ColorSuckerState createState() => _ColorSuckerState();
      22             : 
      23           1 :   @override
      24             :   Widget buildWidget(BuildContext? context) => this;
      25             : 
      26           1 :   @override
      27             :   String get name => 'ColorSucker';
      28             : 
      29           0 :   @override
      30             :   String get displayName => 'ColorSucker';
      31             : 
      32           1 :   @override
      33             :   void onTrigger() {}
      34             : 
      35           1 :   @override
      36             :   ImageProvider<Object> get iconImageProvider =>
      37           2 :       MemoryImage(base64Decode(icon.iconData));
      38             : }
      39             : 
      40             : class _ColorSuckerState extends State<ColorSucker> {
      41             :   late Size _magnifierSize;
      42             :   double? _scale;
      43             :   BorderRadius? _radius;
      44             :   Color _currentColor = Colors.white;
      45             :   img.Image? _snapshot;
      46             :   Offset _magnifierPosition = Offset.zero;
      47             :   double _toolBarY = 60.0;
      48             :   Matrix4 _matrix = Matrix4.identity();
      49             :   late Size _windowSize;
      50             :   bool _excuting = false;
      51             : 
      52           1 :   @override
      53             :   void initState() {
      54           6 :     _windowSize = ui.window.physicalSize / ui.window.devicePixelRatio;
      55           3 :     _magnifierSize = widget.size;
      56           3 :     _scale = widget.scale;
      57           4 :     _radius = BorderRadius.circular(_magnifierSize.longestSide);
      58           5 :     _matrix = Matrix4.identity()..scale(widget.scale);
      59           1 :     _magnifierPosition =
      60           5 :         _windowSize.center(Offset.zero) - _magnifierSize.center(Offset.zero);
      61           1 :     super.initState();
      62             :   }
      63             : 
      64           0 :   @override
      65             :   void didUpdateWidget(ColorSucker oldWidget) {
      66           0 :     if (oldWidget.size != widget.size) {
      67           0 :       _magnifierSize = widget.size;
      68           0 :       _radius = BorderRadius.circular(_magnifierSize.longestSide);
      69             :     }
      70           0 :     if (oldWidget.scale != widget.scale) {
      71           0 :       _scale = widget.scale;
      72           0 :       _matrix = Matrix4.identity()..scale(_scale);
      73             :     }
      74           0 :     super.didUpdateWidget(oldWidget);
      75             :   }
      76             : 
      77           1 :   void _onPanUpdate(DragUpdateDetails dragDetails) {
      78           1 :     _magnifierPosition =
      79           4 :         dragDetails.globalPosition - _magnifierSize.center(Offset.zero);
      80           2 :     double newX = dragDetails.globalPosition.dx;
      81           2 :     double newY = dragDetails.globalPosition.dy;
      82           1 :     final Matrix4 newMatrix = Matrix4.identity()
      83           1 :       ..translate(newX, newY)
      84           3 :       ..scale(_scale, _scale)
      85           3 :       ..translate(-newX, -newY);
      86           1 :     _matrix = newMatrix;
      87           2 :     _searchPixel(dragDetails.globalPosition);
      88           2 :     setState(() {});
      89             :   }
      90             : 
      91           1 :   void _toolBarPanUpdate(DragUpdateDetails dragDetails) {
      92           4 :     _toolBarY = dragDetails.globalPosition.dy - 40;
      93           2 :     setState(() {});
      94             :   }
      95             : 
      96           1 :   void _onPanStart(DragStartDetails dragDetails) async {
      97           3 :     if (_snapshot == null && _excuting == false) {
      98           1 :       _excuting = true;
      99           2 :       await _captureScreen();
     100             :     }
     101             :   }
     102             : 
     103           1 :   void _onPanEnd(DragEndDetails dragDetails) {
     104           1 :     _snapshot = null;
     105             :   }
     106             : 
     107           1 :   void _searchPixel(Offset globalPosition) {
     108           1 :     _calculatePixel(globalPosition);
     109             :   }
     110             : 
     111           1 :   Future<void> _captureScreen() async {
     112             :     try {
     113             :       RenderRepaintBoundary boundary =
     114           3 :           rootKey.currentContext!.findRenderObject() as RenderRepaintBoundary;
     115           0 :       ui.Image image = await boundary.toImage();
     116             :       ByteData? byteData =
     117           0 :           await image.toByteData(format: ui.ImageByteFormat.png);
     118             :       if (byteData == null) {
     119             :         return;
     120             :       }
     121           0 :       Uint8List pngBytes = byteData.buffer.asUint8List();
     122           0 :       _snapshot = img.decodeImage(pngBytes);
     123           0 :       _excuting = false;
     124           0 :       image.dispose();
     125             :     } catch (e) {
     126           3 :       debugPrint(e.toString());
     127             :     }
     128             :   }
     129             : 
     130           1 :   void _calculatePixel(Offset globalPosition) {
     131           1 :     if (_snapshot == null) return;
     132           0 :     double px = globalPosition.dx;
     133           0 :     double py = globalPosition.dy;
     134           0 :     int pixel32 = _snapshot!.getPixelSafe(px.toInt(), py.toInt());
     135           0 :     int hex = _abgrToArgb(pixel32);
     136           0 :     _currentColor = Color(hex);
     137             :   }
     138             : 
     139           0 :   int _abgrToArgb(int argbColor) {
     140           0 :     int r = (argbColor >> 16) & 0xFF;
     141           0 :     int b = argbColor & 0xFF;
     142           0 :     return (argbColor & 0xFF00FF00) | (b << 16) | r;
     143             :   }
     144             : 
     145           1 :   @override
     146             :   Widget build(BuildContext context) {
     147           2 :     if (_windowSize.isEmpty) {
     148           0 :       _windowSize = MediaQuery.of(context).size;
     149           0 :       _magnifierPosition =
     150           0 :           _windowSize.center(Offset.zero) - _magnifierSize.center(Offset.zero);
     151             :     }
     152           1 :     Widget toolBar = Container(
     153           4 :       width: MediaQuery.of(context).size.width - 32,
     154           1 :       decoration: BoxDecoration(
     155             :           color: Colors.white,
     156           1 :           borderRadius: BorderRadius.circular(16),
     157           1 :           boxShadow: [
     158             :             const BoxShadow(
     159             :                 color: Colors.black26, blurRadius: 6, offset: Offset(2, 2))
     160             :           ]),
     161             :       margin: const EdgeInsets.only(left: 16, right: 16),
     162           1 :       child: Row(
     163           1 :         children: <Widget>[
     164           1 :           Container(
     165             :             margin: const EdgeInsets.only(left: 16, top: 10, bottom: 10),
     166             :             width: 60,
     167             :             height: 60,
     168           1 :             decoration: BoxDecoration(
     169             :                 shape: BoxShape.circle,
     170           1 :                 color: _currentColor,
     171           1 :                 border: Border.all(width: 2.0, color: Colors.white),
     172           1 :                 boxShadow: [
     173             :                   const BoxShadow(
     174             :                       color: Colors.black12,
     175             :                       blurRadius: 4,
     176             :                       offset: Offset(2, 2))
     177             :                 ]),
     178             :           ),
     179           1 :           Container(
     180             :             margin: const EdgeInsets.only(left: 40, right: 16),
     181             :             child:
     182           6 :                 Text("#${_currentColor.value.toRadixString(16).substring(2)}",
     183             :                     style: const TextStyle(
     184             :                       fontSize: 25,
     185             :                       color: Colors.grey,
     186             :                     )),
     187             :           ),
     188             :         ],
     189             :       ),
     190             :     );
     191             : 
     192           1 :     return Stack(
     193             :       alignment: Alignment.center,
     194           1 :       children: [
     195           1 :         Positioned(
     196             :             left: 0,
     197           1 :             top: _toolBarY,
     198           1 :             child: GestureDetector(
     199           1 :                 onVerticalDragUpdate: _toolBarPanUpdate, child: toolBar)),
     200           1 :         Positioned(
     201           2 :           left: _magnifierPosition.dx,
     202           2 :           top: _magnifierPosition.dy,
     203           1 :           child: ClipRRect(
     204           1 :             borderRadius: _radius,
     205           1 :             child: GestureDetector(
     206           1 :               onPanStart: _onPanStart,
     207           1 :               onPanEnd: _onPanEnd,
     208           1 :               onPanUpdate: _onPanUpdate,
     209           1 :               child: BackdropFilter(
     210           3 :                 filter: ui.ImageFilter.matrix(_matrix.storage,
     211             :                     filterQuality: FilterQuality.none),
     212           1 :                 child: Container(
     213           1 :                   child: Center(
     214           1 :                     child: Container(
     215             :                       height: 1,
     216             :                       width: 1,
     217             :                       decoration: const BoxDecoration(
     218             :                           color: Colors.grey, shape: BoxShape.circle),
     219             :                     ),
     220             :                   ),
     221           2 :                   height: _magnifierSize.height,
     222           2 :                   width: _magnifierSize.width,
     223           1 :                   decoration: BoxDecoration(
     224           1 :                       borderRadius: _radius,
     225           1 :                       border: Border.all(color: Colors.grey, width: 3)),
     226             :                 ),
     227             :               ),
     228             :             ),
     229             :           ),
     230             :         )
     231             :       ],
     232             :     );
     233             :   }
     234             : }

Generated by: LCOV version 1.15