Skip to content

Instantly share code, notes, and snippets.

@PlugFox
Last active December 16, 2024 22:34

Revisions

  1. PlugFox revised this gist Jun 14, 2019. 2 changed files with 137 additions and 0 deletions.
    137 changes: 137 additions & 0 deletions dottedBorder.dart
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,137 @@
    import 'package:flutter_web/material.dart';
    import 'dart:math' as math;

    class DottedBorder extends StatelessWidget {
    final Color color;
    final double strokeWidth;
    final double gap;
    final Widget child;
    final EdgeInsets padding;

    DottedBorder({
    this.color = Colors.black,
    this.strokeWidth = 1.0,
    this.gap = 5.0,
    this.padding = const EdgeInsets.all(8.0),
    @required this.child,
    }) {
    assert(child != null);
    }

    @override
    Widget build(BuildContext context) {
    return Container(
    child: Padding(
    padding: EdgeInsets.all(strokeWidth / 2),
    child: Stack(
    children: <Widget>[
    Positioned.fill(
    child: CustomPaint(
    painter: _DashRectPainter(
    color: color,
    strokeWidth: strokeWidth,
    gap: gap,
    ),
    ),
    ),
    Padding(
    padding: padding,
    child: child,
    ),
    ],
    ),
    ),
    );
    }
    }

    class _DashRectPainter extends CustomPainter {
    double strokeWidth;
    Color color;
    double gap;

    _DashRectPainter({
    this.strokeWidth = 5.0,
    this.color = Colors.black,
    this.gap = 5.0,
    });

    @override
    void paint(Canvas canvas, Size size) {
    Paint dashedPaint = Paint()
    ..color = color
    ..strokeWidth = strokeWidth
    ..style = PaintingStyle.stroke;

    double x = size.width;
    double y = size.height;

    Path _topPath = getDashedPath(
    a: math.Point(0, 0),
    b: math.Point(x, 0),
    gap: gap,
    );

    Path _rightPath = getDashedPath(
    a: math.Point(x, 0),
    b: math.Point(x, y),
    gap: gap,
    );

    Path _bottomPath = getDashedPath(
    a: math.Point(0, y),
    b: math.Point(x, y),
    gap: gap,
    );

    Path _leftPath = getDashedPath(
    a: math.Point(0, 0),
    b: math.Point(0.001, y),
    gap: gap,
    );

    canvas.drawPath(_topPath, dashedPaint);
    canvas.drawPath(_rightPath, dashedPaint);
    canvas.drawPath(_bottomPath, dashedPaint);
    canvas.drawPath(_leftPath, dashedPaint);
    }

    Path getDashedPath({
    @required math.Point<double> a,
    @required math.Point<double> b,
    @required gap,
    }) {
    Size size = Size(b.x - a.x, b.y - a.y);
    Path path = Path();
    path.moveTo(a.x, a.y);
    bool shouldDraw = true;
    math.Point currentPoint = math.Point(a.x, a.y);

    num radians = math.atan(size.height / size.width);

    num dx = math.cos(radians) * gap < 0
    ? math.cos(radians) * gap * -1
    : math.cos(radians) * gap;

    num dy = math.sin(radians) * gap < 0
    ? math.sin(radians) * gap * -1
    : math.sin(radians) * gap;

    while (currentPoint.x <= b.x && currentPoint.y <= b.y) {
    shouldDraw
    ? path.lineTo(currentPoint.x, currentPoint.y)
    : path.moveTo(currentPoint.x, currentPoint.y);
    shouldDraw = !shouldDraw;
    currentPoint = math.Point(
    currentPoint.x + dx,
    currentPoint.y + dy,
    );
    }
    return path;
    }

    @override
    bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
    }
    }
    File renamed without changes.
  2. PlugFox revised this gist Jun 14, 2019. 1 changed file with 140 additions and 56 deletions.
    196 changes: 140 additions & 56 deletions main.dart
    Original file line number Diff line number Diff line change
    @@ -1,80 +1,164 @@
    import 'dart:async';
    import 'dart:html' as html;

    import 'package:flutter_web/cupertino.dart';
    import 'package:flutter_web/material.dart';
    import 'package:flutter_web_ui/ui.dart' as ui;

    Future<void> main() async {
    await ui.webOnlyInitializePlatform();

    runApp(App());
    }
    import 'dart:async';
    import 'dart:html';
    import './dottedBorder.dart';

    class App extends StatelessWidget {
    class DropzoneWidget extends StatefulWidget {
    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    home: HomePage(title: 'Flutter Web Home Page'),
    title: 'Flutter Web',
    );
    }
    _DropzoneWidgetState createState() => new _DropzoneWidgetState();
    }

    class HomePage extends StatefulWidget {
    const HomePage({Key key, this.title}) : super(key: key);
    class _DropzoneWidgetState extends State<DropzoneWidget> {
    StreamSubscription<MouseEvent> _onDragOverSubscription;
    StreamSubscription<MouseEvent> _onDropSubscription;
    StreamSubscription<MouseEvent> _onDragLeaveSubscription;
    StreamSubscription<Event> _fileSelectionSubscription;
    final StreamController<_DragState> _dragStateStreamController = new StreamController<_DragState>.broadcast();
    final StreamController<Point<double>> _pointStreamController = new StreamController<Point<double>>.broadcast();
    //FileUploadInputElement _inputElement;
    List<File> _files = <File>[];
    /*
    String get _dropZoneText => this._files.isEmpty
    ? 'DropZONE'
    : 'DropZONE\n(${this._files.length})'; //this._files.map<String>((File file) => file.name).join('\n');
    */

    final String title;
    void _onDragOver(MouseEvent value) {
    value.stopPropagation();
    value.preventDefault();
    this._pointStreamController.sink.add(Point<double>(value.layer.x.toDouble(), value.layer.y.toDouble()));
    this._dragStateStreamController.sink.add(_DragState.dragging);
    }

    @override
    HomePageState createState() => HomePageState();
    }
    void _onDrop(MouseEvent value) {
    value.stopPropagation();
    value.preventDefault();
    _pointStreamController.sink.add(null);
    _addFiles(value.dataTransfer.files);
    }

    class HomePageState extends State<HomePage> {
    String fileName;
    html.FileUploadInputElement inputElement;
    StreamSubscription subscription;
    void _onDragLeave(MouseEvent value) {
    this._dragStateStreamController.sink.add(_DragState.notDragging);
    }

    void _fileSelection(Event value) {
    print(value);
    //_addFiles((value.target as FileUploadInputElement).files);
    }

    void openFile() {
    inputElement.click();
    void _addFiles(List<File> newFiles) {
    this.setState(() {
    this._files = this._files..addAll(newFiles);
    print(this._files);
    });
    }

    @override
    void initState() {
    super.initState();

    inputElement = html.FileUploadInputElement()..style.display = 'none';
    subscription = inputElement.onChange.listen((e) {
    var input = e.target as html.FileUploadInputElement;

    setState(() {
    fileName = input.files.first.name;
    });
    });
    this._onDragOverSubscription = document.body.onDragOver.listen(_onDragOver);
    this._onDropSubscription = document.body.onDrop.listen(_onDrop);
    this._onDragLeaveSubscription = document.body.onDragLeave.listen(_onDragLeave);
    //this._inputElement = FileUploadInputElement();//..style.display = 'none';
    //this._fileSelectionSubscription = this._inputElement.onChange.listen(_fileSelection);
    }

    @override
    void deactivate() {
    subscription.cancel();
    inputElement.remove();
    super.deactivate();
    void dispose() {
    this._onDropSubscription.cancel();
    this._onDragOverSubscription.cancel();
    this._onDragLeaveSubscription.cancel();
    this._fileSelectionSubscription.cancel();
    this._dragStateStreamController.close();
    this._pointStreamController.close();
    super.dispose();
    }

    @override
    Widget build(BuildContext context) {
    return Scaffold(
    body: Center(
    child: Column(
    children: <Widget>[
    Text('File name: $fileName'),
    Widget build(BuildContext context)
    => LayoutBuilder(
    builder: (BuildContext context, BoxConstraints boxConstraints)
    => Stack(
    children: <Widget>[
    AnimatedContainer(
    curve: Curves.linear,
    duration: Duration(seconds: 1),
    width: double.infinity,
    height: double.infinity,
    color: this._files.isEmpty
    ? const Color(0xFF81d4fa)
    : const Color(0xFFff80ab),
    child:Padding(
    padding: const EdgeInsets.all(45),
    child: DottedBorder(
    color: const Color(0xFF263238),
    strokeWidth: 5.0,
    gap: 24.0,
    child: Center(
    child: Text(
    'DropZONE',
    maxLines: 1,
    overflow: TextOverflow.ellipsis,
    style: TextStyle(
    fontFamily: 'RobotoMono',
    fontSize: boxConstraints.maxWidth/20,
    fontWeight: FontWeight.bold,
    color: const Color(0xFF37474f),
    ),
    ),
    ),
    ),
    ),
    ),

    Positioned(
    top: 6,
    right: 6,
    width: 140,
    height: 140,
    child: IconButton(
    alignment: Alignment.center,
    icon: Icon(Icons.settings,),
    color: const Color(0xFF37474f),
    iconSize: 120,
    tooltip: 'Settings',
    onPressed: () async {
    //this._inputElement.click();

    await FileUploadInputElement().onChange.first;
    print('settings');
    },
    ),
    ),

    StreamBuilder(
    initialData: null,
    stream: this._pointStreamController.stream,
    builder: (BuildContext context, AsyncSnapshot<Point<double>> snapPoint)
    => (snapPoint.data == null || snapPoint.data is! Point<double> || snapPoint.data == const Point<double>(0.0, 0.0))
    ? Container()
    : StreamBuilder(
    initialData: null,
    stream: this._dragStateStreamController.stream,
    builder: (BuildContext context, AsyncSnapshot<_DragState> snapState)
    => (snapState.data == null || snapState.data is! _DragState || snapState.data == _DragState.notDragging)
    ? Container()
    : Positioned(
    height: 140,
    width: 140,
    left: snapPoint.data.x-65,
    top: snapPoint.data.y+10,
    child: const Icon(Icons.file_upload, size: 120, color: const Color(0xFFffa726),),
    ),
    ),
    ),
    ],
    mainAxisAlignment: MainAxisAlignment.center,
    ),
    ),
    floatingActionButton: FloatingActionButton(
    child: Icon(Icons.file_upload),
    onPressed: openFile,
    tooltip: 'Open file',
    ),
    );
    }
    }

    enum _DragState {
    dragging,
    notDragging,
    }
  3. @ykmnkmi ykmnkmi revised this gist Jun 13, 2019. 1 changed file with 0 additions and 1 deletion.
    1 change: 0 additions & 1 deletion main.dart
    Original file line number Diff line number Diff line change
    @@ -15,7 +15,6 @@ class App extends StatelessWidget {
    Widget build(BuildContext context) {
    return MaterialApp(
    home: HomePage(title: 'Flutter Web Home Page'),
    theme: ThemeData(fontFamily: 'MPlus'),
    title: 'Flutter Web',
    );
    }
  4. @ykmnkmi ykmnkmi created this gist Jun 13, 2019.
    81 changes: 81 additions & 0 deletions main.dart
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,81 @@
    import 'dart:async';
    import 'dart:html' as html;

    import 'package:flutter_web/material.dart';
    import 'package:flutter_web_ui/ui.dart' as ui;

    Future<void> main() async {
    await ui.webOnlyInitializePlatform();

    runApp(App());
    }

    class App extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    home: HomePage(title: 'Flutter Web Home Page'),
    theme: ThemeData(fontFamily: 'MPlus'),
    title: 'Flutter Web',
    );
    }
    }

    class HomePage extends StatefulWidget {
    const HomePage({Key key, this.title}) : super(key: key);

    final String title;

    @override
    HomePageState createState() => HomePageState();
    }

    class HomePageState extends State<HomePage> {
    String fileName;
    html.FileUploadInputElement inputElement;
    StreamSubscription subscription;

    void openFile() {
    inputElement.click();
    }

    @override
    void initState() {
    super.initState();

    inputElement = html.FileUploadInputElement()..style.display = 'none';
    subscription = inputElement.onChange.listen((e) {
    var input = e.target as html.FileUploadInputElement;

    setState(() {
    fileName = input.files.first.name;
    });
    });
    }

    @override
    void deactivate() {
    subscription.cancel();
    inputElement.remove();
    super.deactivate();
    }

    @override
    Widget build(BuildContext context) {
    return Scaffold(
    body: Center(
    child: Column(
    children: <Widget>[
    Text('File name: $fileName'),
    ],
    mainAxisAlignment: MainAxisAlignment.center,
    ),
    ),
    floatingActionButton: FloatingActionButton(
    child: Icon(Icons.file_upload),
    onPressed: openFile,
    tooltip: 'Open file',
    ),
    );
    }
    }