Skip to content

PAINTROID-759: Add Text Tool #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
12 changes: 11 additions & 1 deletion lib/core/commands/command_factory/command_factory.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import 'dart:ui';
import 'package:flutter/material.dart';

import 'package:paintroid/core/commands/command_implementation/graphic/line_command.dart';
import 'package:paintroid/core/commands/command_implementation/graphic/path_command.dart';
import 'package:paintroid/core/commands/command_implementation/graphic/shape/circle_shape_command.dart';
import 'package:paintroid/core/commands/command_implementation/graphic/shape/square_shape_command.dart';
import 'package:paintroid/core/commands/path_with_action_history.dart';

import 'package:paintroid/core/commands/command_implementation/add_text_command.dart';

class CommandFactory {
const CommandFactory();

@@ -38,4 +40,12 @@ class CommandFactory {
Offset center,
) =>
CircleShapeCommand(paint, radius, center);

AddTextCommand createAddTextCommand(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be just TextCommand and createTextCommand

Offset point,
String text,
TextStyle style,
Paint paint,
) =>
AddTextCommand(point, text, style, paint);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be just TextCommand

}
49 changes: 49 additions & 0 deletions lib/core/commands/command_implementation/add_text_command.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import 'package:flutter/cupertino.dart';
import 'package:paintroid/core/commands/command_implementation/graphic/graphic_command.dart';
import 'package:paintroid/core/json_serialization/converter/paint_converter.dart';
import 'package:equatable/equatable.dart';

class AddTextCommand extends GraphicCommand with EquatableMixin {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be just TextCommand

final Offset point;
final String text;
final TextStyle style;

AddTextCommand(
this.point,
this.text,
this.style,
Paint paint,
) : super(paint);

@override
void call(Canvas canvas) {
final textPainter = TextPainter(
text: TextSpan(text: text, style: style),
textDirection: TextDirection.ltr,
);

textPainter.layout(minWidth: 0, maxWidth: double.infinity);
final textOffset =
point - Offset(textPainter.width / 2, textPainter.height / 2);
textPainter.paint(canvas, textOffset);
}

void undo(Canvas canvas) {
// TODO
Copy link
Contributor

@bakicelebi bakicelebi Aug 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commands dont have undo method or rather should not have one. Please use the override in the specific tool, in this case text tool.

}

@override
List<Object?> get props => [point, text, paint];

@override
bool? get stringify => true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why nullable?


@override
Copy link
Contributor

@bakicelebi bakicelebi Aug 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not the way this project uses serialization. Please have a look at other commands. They are using a version strategy design pattern and we should use it in every command.

Map<String, dynamic> toJson() {
return {
'point': {'dx': point.dx, 'dy': point.dy},
'text': text,
'paint': const PaintConverter().toJson(paint),
};
}
}
3 changes: 3 additions & 0 deletions lib/core/commands/command_manager/command_manager.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:ui';

import 'package:paintroid/core/commands/command_implementation/add_text_command.dart';
import 'package:paintroid/core/commands/command_implementation/command.dart';
import 'package:paintroid/core/commands/command_implementation/graphic/graphic_command.dart';
import 'package:paintroid/core/commands/command_implementation/graphic/line_command.dart';
@@ -109,6 +110,8 @@ class CommandManager {
return ToolData.SHAPES;
} else if (command.runtimeType == CircleShapeCommand) {
return ToolData.SHAPES;
} else if (command.runtimeType == AddTextCommand) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be TextCommand

return ToolData.TEXT;
} else {
return ToolData.BRUSH;
}
3 changes: 3 additions & 0 deletions lib/core/commands/command_painter.dart
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import 'package:paintroid/core/providers/state/paint_provider.dart';
import 'package:paintroid/core/providers/state/toolbox_state_provider.dart';
import 'package:paintroid/core/tools/implementation/shapes_tool/shapes_tool.dart';
import 'package:paintroid/core/tools/line_tool/line_tool.dart';
import 'package:paintroid/core/tools/text_tool/text_tool.dart';
import 'package:paintroid/core/tools/tool.dart';

class CommandPainter extends CustomPainter {
@@ -32,6 +33,8 @@ class CommandPainter extends CustomPainter {
..drawShape(canvas, ref.read(paintProvider))
..drawGuides(canvas);
break;
case ToolType.TEXT:
(currentTool as TextTool).drawGuides(canvas);
default:
commandManager.executeLastCommand(canvas);
break;
14 changes: 14 additions & 0 deletions lib/core/commands/graphic_factory/graphic_factory.dart
Original file line number Diff line number Diff line change
@@ -16,6 +16,20 @@ class GraphicFactory {
..color = const Color.fromARGB(220, 117, 117, 117)
..style = PaintingStyle.fill;

static Paint boundingBoxPaint = Paint()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please merge develop to get the changes from shapes tool PR. There these are already written/implemented

..color = const Color.fromARGB(121, 55, 55, 55)
..style = PaintingStyle.stroke
..strokeWidth = 10;

static Paint circumferencePaint = Paint()
..color = const Color.fromARGB(121, 55, 55, 55)
..style = PaintingStyle.stroke
..strokeWidth = 10;

static Paint anchorPointPaint = Paint()
..color = const Color.fromARGB(121, 117, 117, 117)
..style = PaintingStyle.fill;

PathWithActionHistory createPathWithActionHistory() =>
PathWithActionHistory();

27 changes: 8 additions & 19 deletions lib/core/database/project_database.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/core/extensions/offset_extension.dart
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@ extension OffsetExtensions on Offset {

Offset moveTowards({
required Offset towards,
required double distance,
required double distance,
Offset? from,
double rotation = 0,
}) =>
40 changes: 40 additions & 0 deletions lib/core/providers/object/tools/text_tool_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import 'dart:ui';

import 'package:paintroid/core/commands/graphic_factory/graphic_factory_provider.dart';
import 'package:paintroid/core/enums/tool_types.dart';
import 'package:paintroid/core/providers/state/canvas_state_provider.dart';
import 'package:paintroid/core/tools/text_tool/bounding_box.dart';
import 'package:paintroid/core/tools/text_tool/text_tool.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:paintroid/core/commands/command_factory/command_factory_provider.dart';
import 'package:paintroid/core/commands/command_manager/command_manager_provider.dart';

part 'text_tool_provider.g.dart';

@riverpod
class TextToolProvider extends _$TextToolProvider {
@override
TextTool build() {
Rect initialBoundingBox = Rect.fromCenter(
center: ref.read(canvasStateProvider).size.center(Offset.zero),
width: 300,
height: 200,
);
return TextTool(
graphicFactory: ref.watch(graphicFactoryProvider),
commandManager: ref.watch(commandManagerProvider),
commandFactory: ref.watch(commandFactoryProvider),
type: ToolType.TEXT,
boundingBox: BoundingBox(
initialBoundingBox.topLeft,
initialBoundingBox.topRight,
initialBoundingBox.bottomLeft,
initialBoundingBox.bottomRight,
),
);
}

void updateText(String newText) {
state.currentText = newText;
}
Copy link
Contributor

@bakicelebi bakicelebi Aug 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't do side effects directly from this provider. I also realized this in my shapes tool implementation it caused me lots of headaches. Instead wherever you need it, use something like this:

final textTool = ref.read(toolBoxStateProvider).currentTool as TextTool;
textTool.currentText = newText

This was an example I think there should be a new provider to control the text of text tool to update the UI. So the newTextcan be retrieved from that new provider. Maybe a ShapesToolOptionsStateProvider ?

}
26 changes: 26 additions & 0 deletions lib/core/providers/object/tools/text_tool_provider.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions lib/core/providers/state/toolbox_state_provider.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:ui';
import 'package:paintroid/core/providers/object/canvas_painter_provider.dart';
import 'package:paintroid/core/providers/object/tools/shapes_tool_provider.dart';
import 'package:paintroid/core/providers/object/tools/text_tool_provider.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:paintroid/core/commands/command_manager/command_manager_provider.dart';
import 'package:paintroid/core/enums/tool_types.dart';
@@ -64,6 +65,9 @@ class ToolBoxStateProvider extends _$ToolBoxStateProvider {
state = state.copyWith(currentTool: ref.read(shapesToolProvider));
ref.read(canvasPainterProvider.notifier).repaint();
break;
case ToolType.TEXT:
state = state.copyWith(currentTool: ref.read(textToolProvider));
break;
default:
state = state.copyWith(currentTool: ref.read(brushToolProvider));
break;
Loading