123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- import 'dart:math';
- import 'package:flutter/material.dart';
- import 'package:grpc/grpc_web.dart';
- import 'package:cyclop/cyclop.dart';
- import 'src/color_ref.dart';
- import 'src/connection/ws.dart';
- import 'src/widget/square.dart';
- class TransformationsDemo extends StatefulWidget {
- const TransformationsDemo({Key? key}) : super(key: key);
- @override
- State<TransformationsDemo> createState() => _TransformationsDemoState();
- }
- class _TransformationsDemoState extends State<TransformationsDemo>
- with TickerProviderStateMixin {
- final GlobalKey _targetKey = GlobalKey();
- Map<Point<int>, Widget> elements = <Point<int>, Widget>{};
- Color appbarColor = Colors.blueGrey;
- Set<Color> swatches = Colors.primaries.map((e) => Color(e.value)).toSet();
- double minScale = 2;
- ColorRef cc = ColorRef();
- final TransformationController _transformationController =
- TransformationController();
- Animation<Matrix4>? _animationReset;
- late AnimationController _controllerReset;
- Matrix4? _homeMatrix;
- final channel = GrpcWebClientChannel.xhr(Uri.parse('http://localhost:8080'));
- @override
- void initState() {
- super.initState();
- WebRTCChannels().connect((x) {});
- // _controllerReset = AnimationController(
- // vsync: this,
- // );
- }
- @override
- Widget build(BuildContext context) {
- // The scene is drawn by a CustomPaint, but user interaction is handled by
- // the InteractiveViewer parent widget.
- return Scaffold(
- backgroundColor: Theme.of(context).colorScheme.primary,
- // appBar: AppBar(
- // automaticallyImplyLeading: false,
- // title: const Text('title'),
- // ),
- body: Container(
- color: Colors.white,
- child: LayoutBuilder(
- builder: (context, constraints) {
- // Start the first render, start the scene centered in the viewport.
- if (_homeMatrix == null) {
- _homeMatrix = Matrix4.identity() * minScale
- ..translate(0, 0);
- _transformationController.value = _homeMatrix!;
- elements = _start(
- context: context,
- channel: channel,
- transformationController: _transformationController);
- // _onUpdate(context: context);
- }
- return ClipRect(
- child: MouseRegion(
- cursor: SystemMouseCursors.click,
- child: GestureDetector(
- behavior: HitTestBehavior.opaque,
- // onTapUp: _onTapUp,
- child: InteractiveViewer(
- constrained: false,
- key: _targetKey,
- transformationController: _transformationController,
- boundaryMargin: EdgeInsets.all(0),
- minScale: minScale,
- maxScale: 30,
- // onInteractionStart: _onScaleStart,
- onInteractionUpdate: _onInteractionUpdate,
- onInteractionEnd: _onInteractionEnd,
- child: SizedBox(
- width: 256 * 90,
- height: 256 * 53,
- child: Stack(children: elements.values.toList()),
- ),
- ),
- ),
- ),
- );
- },
- ),
- ),
- // persistentFooterButtons: [],
- floatingActionButton: ColorButton(
- darkMode: true,
- key: const Key('c2'),
- color: appbarColor,
- boxShape: BoxShape.circle,
- swatches: swatches,
- size: 64,
- config: const ColorPickerConfig(
- enableOpacity: false,
- enableLibrary: true,
- ),
- onColorChanged: (value) => setState(() {
- appbarColor = value;
- cc.setColor(appbarColor);
- }),
- onSwatchesChanged: (newSwatches) =>
- setState(() => swatches = newSwatches),
- ),
- );
- }
- @override
- void dispose() {
- // _controllerReset.dispose();
- super.dispose();
- }
- void _onInteractionUpdate(ScaleUpdateDetails details) {
- _onUpdate();
- }
- void _onUpdate({BuildContext? context}) {
- var context2 = context ?? _targetKey.currentContext!;
- setState(() {
- _start(
- context: context2,
- channel: channel,
- transformationController: _transformationController,
- elements: elements);
- });
- }
- Map<Point<int>, Widget> _start(
- {required BuildContext context,
- required GrpcWebClientChannel channel,
- required TransformationController transformationController,
- Map<Point<int>, Widget>? elements}) {
- var bounds = MediaQuery.of(context).size;
- var topLeft = transformationController.toScene(bounds.topLeft(Offset.zero));
- var bottomRight =
- transformationController.toScene(bounds.bottomRight(Offset.zero));
- var newSet = <Point<int>>{};
- var rec = Rectangle<int>.fromPoints(
- _offsetToIndex(topLeft), _offsetToIndex(bottomRight));
- for (var i = rec.left; i <= rec.right; i++) {
- for (var j = rec.top; j <= rec.bottom; j++) {
- newSet.add(Point<int>(i, j));
- }
- }
- var elements2 = elements ?? <Point<int>, Widget>{};
- newSet
- .difference(Set.from(elements2.keys))
- .forEach((point) => elements2[point] ??= Container(
- margin:
- EdgeInsets.only(left: 256.0 * point.x, top: 256.0 * point.y),
- child: SquareComponent(point, cc),
- ));
- Set.from(elements2.keys).difference(newSet).forEach(
- (point) => elements2.remove(point),
- );
- // print(elements2.length);
- // WebRTCChannels().connect();
- return elements2;
- }
- void _onInteractionEnd(ScaleEndDetails details) => _onUpdate();
- }
- Point<int> _offsetToIndex(Offset offset) {
- offset = offset / 256.0;
- var x = offset.dx.floor();
- var y = offset.dy.floor();
- if (x < 0) x = 0;
- if (y < 0) y = 0;
- return Point<int>(x, y);
- }
|