Skip to content
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

Move selection to another page #1085

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
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
13 changes: 13 additions & 0 deletions lib/data/editor/editor_history.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ class EditorHistoryItem {
EditorHistoryItem({
required this.type,
required this.pageIndex,
this.pageIndexStart,
required this.strokes,
required this.images,
this.offset,
Expand All @@ -124,6 +125,8 @@ class EditorHistoryItem {
this.colorChange,
}) : assert(type != EditorHistoryItemType.move || offset != null,
'Offset must be provided for move'),
assert(type != EditorHistoryItemType.move || pageIndexStart != null,
'pageIndexStart must be provided for move'),
assert(type != EditorHistoryItemType.deletePage || page != null,
'Page must be provided for deletePage'),
assert(type != EditorHistoryItemType.insertPage || page != null,
Expand All @@ -141,6 +144,14 @@ class EditorHistoryItem {

final EditorHistoryItemType type;
final int pageIndex;

/// Original page of selected items before being moved to another one.
///
/// This can be the same as [pageIndex]
/// if the items were moved within the same page.
///
/// See also: [SelectResult.pageIndexStart]
final int? pageIndexStart;
final List<Stroke> strokes;
final List<EditorImage> images;
final Rect? offset;
Expand All @@ -151,6 +162,7 @@ class EditorHistoryItem {
EditorHistoryItem copyWith({
EditorHistoryItemType? type,
int? pageIndex,
int? pageIndexStart,
List<Stroke>? strokes,
List<EditorImage>? images,
Rect? offset,
Expand All @@ -161,6 +173,7 @@ class EditorHistoryItem {
return EditorHistoryItem(
type: type ?? this.type,
pageIndex: pageIndex ?? this.pageIndex,
pageIndexStart: pageIndexStart ?? this.pageIndexStart,
strokes: strokes ?? this.strokes,
images: images ?? this.images,
offset: offset ?? this.offset,
Expand Down
8 changes: 8 additions & 0 deletions lib/data/tools/select.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class Select extends Tool {
strokes: const [],
images: const [],
path: Path(),
pageIndexStart: -1,
);
bool doneSelecting = false;

Expand Down Expand Up @@ -57,6 +58,7 @@ class Select extends Tool {
strokes: [],
images: [],
path: Path(),
pageIndexStart: pageIndex,
);
selectResult.path.moveTo(position.dx, position.dy);
onDragUpdate(position);
Expand Down Expand Up @@ -128,11 +130,15 @@ class SelectResult {
final List<EditorImage> images;
Path path;

/// The page index when the items were selected.
int pageIndexStart;

SelectResult({
required this.pageIndex,
required this.strokes,
required this.images,
required this.path,
required this.pageIndexStart,
});

bool get isEmpty {
Expand All @@ -144,12 +150,14 @@ class SelectResult {
List<Stroke>? strokes,
List<EditorImage>? images,
Path? path,
int? pageIndexStart,
}) {
return SelectResult(
pageIndex: pageIndex ?? this.pageIndex,
strokes: strokes ?? this.strokes,
images: images ?? this.images,
path: path ?? this.path,
pageIndexStart: pageIndexStart ?? this.pageIndexStart,
);
}
}
176 changes: 166 additions & 10 deletions lib/pages/editor/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -420,13 +420,20 @@ class EditorState extends State<Editor> {
-item.offset!.left,
-item.offset!.top,
));
if (item.pageIndex != item.pageIndexStart) {
moveStrokeToPage(stroke, item.pageIndex, item.pageIndexStart!);
}
}
Select select = Select.currentSelect;
if (select.doneSelecting) {
select.selectResult.path = select.selectResult.path.shift(Offset(
-item.offset!.left,
-item.offset!.top,
));
if (item.pageIndex != item.pageIndexStart) {
// move selection area to the original page
select.selectResult.pageIndex = item.pageIndexStart!;
}
}
for (EditorImage image in item.images) {
image.dstRect = Rect.fromLTRB(
Expand All @@ -435,6 +442,9 @@ class EditorState extends State<Editor> {
image.dstRect.right - item.offset!.right,
image.dstRect.bottom - item.offset!.bottom,
);
if (item.pageIndex != item.pageIndexStart) {
moveImageToPage(image, item.pageIndex, item.pageIndexStart!);
}
}

case EditorHistoryItemType.quillChange:
Expand Down Expand Up @@ -473,12 +483,16 @@ class EditorState extends State<Editor> {
undo(item.copyWith(type: EditorHistoryItemType.deletePage));
case EditorHistoryItemType.move:
undo(item.copyWith(
offset: Rect.fromLTRB(
-item.offset!.left,
-item.offset!.top,
-item.offset!.right,
-item.offset!.bottom,
)));
// swap pageIndex and pageIndexStart
pageIndex: item.pageIndexStart,
pageIndexStart: item.pageIndex,
offset: Rect.fromLTRB(
-item.offset!.left,
-item.offset!.top,
-item.offset!.right,
-item.offset!.bottom,
),
));
case EditorHistoryItemType.quillChange:
undo(item.copyWith(type: EditorHistoryItemType.quillUndoneChange));
case EditorHistoryItemType.quillUndoneChange: // this will never happen
Expand Down Expand Up @@ -549,6 +563,10 @@ class EditorState extends State<Editor> {
}
}

/// When the selection is dragged this far past the top/bottom of the page,
/// the selection will be moved to the previous/next page.
static const changePageThreshold = 50.0;

void onDrawStart(ScaleStartDetails details) {
final page = coreInfo.pages[dragPageIndex!];
final position = page.renderBox!.globalToLocal(details.focalPoint);
Expand Down Expand Up @@ -600,9 +618,13 @@ class EditorState extends State<Editor> {
}

void onDrawUpdate(ScaleUpdateDetails details) {
if (dragPageIndex==null){
// cursor is somewhere between pages, do not respond until its page will be recognized
return;
}
final page = coreInfo.pages[dragPageIndex!];
final position = page.renderBox!.globalToLocal(details.focalPoint);
final offset = position - previousPosition;
Offset position = page.renderBox!.globalToLocal(details.focalPoint);
Offset offset = position - previousPosition;

if (PencilSound.isPlaying) PencilSound.update(offset.distance);

Expand All @@ -619,13 +641,62 @@ class EditorState extends State<Editor> {
} else if (currentTool is Select) {
Select select = currentTool as Select;
if (select.doneSelecting) {
int pageOffset = 0; // between -1 and 1
if (position.dy > page.size.height + changePageThreshold) {
// Selection is dragged past the bottom of the original page
if (coreInfo.pages.length > select.selectResult.pageIndex + 1) {
offset = Offset(
offset.dx,
offset.dy - (page.size.height + changePageThreshold),
);
pageOffset = 1;
}
} else if (position.dy < -changePageThreshold) {
// Selection is dragged past the top of the original page
if (select.selectResult.pageIndex > 0) {
offset = Offset(
offset.dx,
offset.dy + (page.size.height + changePageThreshold),
);
pageOffset = -1;
}
}

for (Stroke stroke in select.selectResult.strokes) {
stroke.shift(offset);
}
for (EditorImage image in select.selectResult.images) {
image.dstRect = image.dstRect.shift(offset);
}
select.selectResult.path = select.selectResult.path.shift(offset);

if (pageOffset != 0) {
offset = position - previousPosition; // and put real offset back
// before page redraw we need to move selected entities to another page
// this page will be redrawn later
//log.info('Moving selected item to new page and deleting them from original page');
selectionOffsetPage(
pageOffset); // move entities to new page and remove them from current one

// now handle new page, cursor position and another things
// change index of drag page
dragPageIndex = onWhichPageIsFocalPoint(
details.focalPoint); // update page and create paint rectangle
if (dragPageIndex == null) {
return; // page does not exist
}
final pageNew = coreInfo.pages[dragPageIndex!];
// recalculate position according new drag page
position = pageNew.renderBox!.globalToLocal(details.focalPoint);
//log.info('New page rect $rectTop to $rectBottom. Position on new page is $cursorPosition');
// recalculate the offset as if the selection were always moving to one page. Important for undo/redo
offset = Offset(
offset.dx,
offset.dy -
pageOffset * (page.size.height + changePageThreshold));
// setState(() {}); // force update of builder so movement of selection to another page is taken into account
pageNew.redrawStrokes(); // and finally redraw new page
}
} else {
select.onDragUpdate(position);
}
Expand All @@ -634,11 +705,91 @@ class EditorState extends State<Editor> {
(currentTool as LaserPointer).onDragUpdate(position);
page.redrawStrokes();
}

previousPosition = position;
moveOffset += offset;
moveOffset += offset; // this value is keeped due to Undo/redo
}

bool moveStrokeToPage(Stroke stroke, int pageIndexOrig, int pageIndexDest) {
// move stroke from page pageIndexOrig to pageIndexDest
// setState must be called before use to track changes
if (pageIndexOrig == pageIndexDest ||
pageIndexOrig == -1 ||
pageIndexDest == -1) {
return false; // no page change
}
if (pageIndexOrig < 0 || pageIndexOrig > coreInfo.pages.length - 1) {
return false;
}
if (pageIndexDest < 0 || pageIndexDest > coreInfo.pages.length - 1) {
return false;
}
final pageOrig = coreInfo.pages[pageIndexOrig];
final pageDest = coreInfo.pages[pageIndexDest];
// remove from original page
pageOrig.strokes.remove(stroke);
// add to new page
pageDest.strokes.add(stroke);
return true;
}

bool moveImageToPage(
EditorImage image, int pageIndexOrig, int pageIndexDest) {
// move image from page pageIndexOrig to pageIndexDest
// setState must be called before use to track changes
if (pageIndexOrig == pageIndexDest ||
pageIndexOrig == -1 ||
pageIndexDest == -1) {
return false; // no page change
}
if (pageIndexOrig < 0 || pageIndexOrig > coreInfo.pages.length - 1) {
return false;
}
if (pageIndexDest < 0 || pageIndexDest > coreInfo.pages.length - 1) {
return false;
}
final pageOrig = coreInfo.pages[pageIndexOrig];
final pageDest = coreInfo.pages[pageIndexDest];
// remove from original page
pageOrig.images.remove(image);
// add to new page
pageDest.images.add(image);
return true;
}

void selectionOffsetPage(int pageOffset) {
// selected items should be moved to another page
Select select = currentTool as Select;
// test if pages exist
final int oldPage = select.selectResult.pageIndex;
final int newPage = select.selectResult.pageIndex + pageOffset;
if (oldPage < 0 || oldPage > coreInfo.pages.length - 1) {
return;
}
if (newPage < 0 || newPage > coreInfo.pages.length - 1) {
return;
}
final strokes = select.selectResult.strokes;
final images = select.selectResult.images;

setState(() {
// remove from original page
for (Stroke stroke in strokes) {
moveStrokeToPage(stroke, oldPage, newPage);
}
for (EditorImage image in images) {
moveImageToPage(image, oldPage, newPage);
}
// move selection to new page
select.selectResult.pageIndex += pageOffset;
});
}

void onDrawEnd(ScaleEndDetails details) {
if (dragPageIndex==null){
// page cannot be determined from cursor position
return;
}
final page = coreInfo.pages[dragPageIndex!];
bool shouldSave = true;
if (PencilSound.isPlaying) PencilSound.pause();
Expand Down Expand Up @@ -682,7 +833,10 @@ class EditorState extends State<Editor> {
if (select.doneSelecting) {
history.recordChange(EditorHistoryItem(
type: EditorHistoryItemType.move,
pageIndex: dragPageIndex!,
pageIndexStart: select.selectResult
.pageIndexStart, // use page index of page where entities were aat start of movement
pageIndex: select.selectResult
.pageIndex, // use page index of page where entities are now
strokes: select.selectResult.strokes,
images: select.selectResult.images,
offset: Rect.fromLTRB(
Expand All @@ -692,6 +846,7 @@ class EditorState extends State<Editor> {
moveOffset.dy,
),
));
select.selectResult.pageIndexStart=select.selectResult.pageIndex; // set starting page index to current page
} else {
shouldSave = false;
select.onDragEnd(page.strokes, page.images);
Expand Down Expand Up @@ -747,6 +902,7 @@ class EditorState extends State<Editor> {
history.recordChange(EditorHistoryItem(
type: EditorHistoryItemType.move,
pageIndex: image.pageIndex,
pageIndexStart: image.pageIndex,
strokes: [],
images: [image],
offset: offset,
Expand Down
1 change: 0 additions & 1 deletion metadata/ar/changelogs/210403.txt

This file was deleted.

1 change: 1 addition & 0 deletions metadata/ar/changelogs/210403.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
metadata/ar/changelogs/21040.txt
1 change: 0 additions & 1 deletion metadata/ar/changelogs/220003.txt

This file was deleted.

1 change: 1 addition & 0 deletions metadata/ar/changelogs/220003.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
metadata/ar/changelogs/22000.txt
1 change: 0 additions & 1 deletion metadata/ar/changelogs/230003.txt

This file was deleted.

1 change: 1 addition & 0 deletions metadata/ar/changelogs/230003.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
metadata/ar/changelogs/23000.txt
1 change: 0 additions & 1 deletion metadata/ar/changelogs/230103.txt

This file was deleted.

1 change: 1 addition & 0 deletions metadata/ar/changelogs/230103.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
metadata/ar/changelogs/23010.txt
1 change: 0 additions & 1 deletion metadata/ar/changelogs/230203.txt

This file was deleted.

1 change: 1 addition & 0 deletions metadata/ar/changelogs/230203.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
metadata/ar/changelogs/23020.txt
1 change: 0 additions & 1 deletion metadata/ar/changelogs/230303.txt

This file was deleted.

1 change: 1 addition & 0 deletions metadata/ar/changelogs/230303.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
metadata/ar/changelogs/23030.txt
1 change: 0 additions & 1 deletion metadata/cs/changelogs/210403.txt

This file was deleted.

Loading
Loading