Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions lib/src/controllers/notifications/is_drawing_state_changed.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'notification.dart';

/// A notification that is dispatched when the user starts or stops freehand painting
class DrawableIsDrawingStateChangedNotification
extends FlutterPainterNotification {
bool isDrawing;

/// Creates a [DrawableIsDrawingStateChangedNotification]. Supplies the current Drawable and also if the user started or stopped
DrawableIsDrawingStateChangedNotification(this.isDrawing);
}
63 changes: 38 additions & 25 deletions lib/src/views/widgets/flutter_painter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_painter/src/controllers/notifications/is_drawing_state_changed.dart';
import '../../controllers/events/selected_object_drawable_removed_event.dart';
import '../../controllers/helpers/renderer_check/renderer_check.dart';
import '../../controllers/drawables/drawable.dart';
Expand Down Expand Up @@ -54,6 +55,9 @@ class FlutterPainter extends StatelessWidget {
/// Callback when the [PainterSettings] of [PainterController] are updated internally.
final ValueChanged<PainterSettings>? onPainterSettingsChanged;

/// Callback when a [FreeStyleDrawable] starts or stops being drawn
final ValueChanged<bool>? onIsDrawingStateChanged;

/// The builder used to build this widget.
///
/// Using the default constructor, it will default to returning the [_FlutterPainterWidget].
Expand All @@ -63,29 +67,31 @@ class FlutterPainter extends StatelessWidget {
final FlutterPainterBuilderCallback _builder;

/// Creates a [FlutterPainter] with the given [controller] and optional callbacks.
const FlutterPainter(
{Key? key,
required this.controller,
this.onDrawableCreated,
this.onDrawableDeleted,
this.onSelectedObjectDrawableChanged,
this.onPainterSettingsChanged})
: _builder = _defaultBuilder,
const FlutterPainter({
Key? key,
required this.controller,
this.onDrawableCreated,
this.onDrawableDeleted,
this.onSelectedObjectDrawableChanged,
this.onPainterSettingsChanged,
this.onIsDrawingStateChanged,
}) : _builder = _defaultBuilder,
super(key: key);

/// Creates a [FlutterPainter] with the given [controller], [builder] and optional callbacks.
///
/// Using this constructor, the [builder] will be called any time the [controller] updates.
/// It is useful if you want to build UI that automatically rebuilds on updates from [controller].
const FlutterPainter.builder(
{Key? key,
required this.controller,
required FlutterPainterBuilderCallback builder,
this.onDrawableCreated,
this.onDrawableDeleted,
this.onSelectedObjectDrawableChanged,
this.onPainterSettingsChanged})
: _builder = builder,
const FlutterPainter.builder({
Key? key,
required this.controller,
required FlutterPainterBuilderCallback builder,
this.onDrawableCreated,
this.onDrawableDeleted,
this.onSelectedObjectDrawableChanged,
this.onPainterSettingsChanged,
this.onIsDrawingStateChanged,
}) : _builder = builder,
super(key: key);

@override
Expand All @@ -105,6 +111,7 @@ class FlutterPainter extends StatelessWidget {
onPainterSettingsChanged: onPainterSettingsChanged,
onSelectedObjectDrawableChanged:
onSelectedObjectDrawableChanged,
onIsDrawingStateChanged: onIsDrawingStateChanged,
));
}),
);
Expand Down Expand Up @@ -133,15 +140,19 @@ class _FlutterPainterWidget extends StatelessWidget {
/// Callback when the [PainterSettings] of [PainterController] are updated internally.
final ValueChanged<PainterSettings>? onPainterSettingsChanged;

/// Callback when a [FreeStyleDrawable] starts or stops being drawn
final ValueChanged<bool>? onIsDrawingStateChanged;

/// Creates a [_FlutterPainterWidget] with the given [controller] and optional callbacks.
const _FlutterPainterWidget(
{Key? key,
required this.controller,
this.onDrawableCreated,
this.onDrawableDeleted,
this.onSelectedObjectDrawableChanged,
this.onPainterSettingsChanged})
: super(key: key);
const _FlutterPainterWidget({
Key? key,
required this.controller,
this.onDrawableCreated,
this.onDrawableDeleted,
this.onSelectedObjectDrawableChanged,
this.onPainterSettingsChanged,
this.onIsDrawingStateChanged,
}) : super(key: key);

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -197,6 +208,8 @@ class _FlutterPainterWidget extends StatelessWidget {
onSelectedObjectDrawableChanged?.call(notification.drawable);
} else if (notification is SettingsUpdatedNotification) {
onPainterSettingsChanged?.call(notification.settings);
} else if (notification is DrawableIsDrawingStateChangedNotification) {
onIsDrawingStateChanged?.call(notification.isDrawing);
}
return true;
}
Expand Down
23 changes: 23 additions & 0 deletions lib/src/views/widgets/free_style_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class _FreeStyleWidgetState extends State<_FreeStyleWidget> {
onHorizontalDragDown: _handleHorizontalDragDown,
onHorizontalDragUpdate: _handleHorizontalDragUpdate,
onHorizontalDragUp: _handleHorizontalDragUp,
onHorizontalDragCancel: _handleHorizontalDragCancel,
),
(_) {},
),
Expand Down Expand Up @@ -82,6 +83,9 @@ class _FreeStyleWidgetState extends State<_FreeStyleWidget> {

// Set the drawable as the current drawable
this.drawable = drawable;

// notify that we now start drawing
DrawableIsDrawingStateChangedNotification(true).dispatch(context);
}

/// Callback when the user moves, rotates or scales the pointer(s).
Expand All @@ -105,11 +109,24 @@ class _FreeStyleWidgetState extends State<_FreeStyleWidget> {
/// Callback when the user removes all pointers from the widget.
void _handleHorizontalDragUp() {
DrawableCreatedNotification(drawable).dispatch(context);
// notify that we now start drawing
DrawableIsDrawingStateChangedNotification(false).dispatch(context);

/// Reset the current drawable for the user to draw a new one next time
drawable = null;
}

/// Callback when the pointer event was falsely directed to us.
/// E.g. when the wrist was layed on the pad, but then a pen is recognized.
/// => the painting input of the wrist is invalid!
void _handleHorizontalDragCancel() {
if (drawable != null && drawable is PathDrawable) {
PainterController.of(context).removeDrawable(drawable!);
}
drawable = null;
DrawableIsDrawingStateChangedNotification(false).dispatch(context);
}

Offset _globalToLocal(Offset globalPosition) {
final getBox = context.findRenderObject() as RenderBox;

Expand All @@ -123,11 +140,13 @@ class _DragGestureDetector extends OneSequenceGestureRecognizer {
required this.onHorizontalDragDown,
required this.onHorizontalDragUpdate,
required this.onHorizontalDragUp,
required this.onHorizontalDragCancel,
});

final ValueSetter<Offset> onHorizontalDragDown;
final ValueSetter<Offset> onHorizontalDragUpdate;
final VoidCallback onHorizontalDragUp;
final VoidCallback onHorizontalDragCancel;

bool _isTrackingGesture = false;

Expand All @@ -152,6 +171,10 @@ class _DragGestureDetector extends OneSequenceGestureRecognizer {
onHorizontalDragUp();
stopTrackingPointer(event.pointer);
_isTrackingGesture = false;
} else if (event is PointerCancelEvent) {
onHorizontalDragCancel();
stopTrackingPointer(event.pointer);
_isTrackingGesture = false;
}
}

Expand Down