Skip to content

Commit

Permalink
Implemented moving selection across pages. Undo/redo works.
Browse files Browse the repository at this point in the history
In Select  added pageIndexStart holding original page of selection.
In EditorHistory added pageIndexStart - important only for move

Solving issue saber-notes#932
  • Loading branch information
QubaB authored and adil192 committed Feb 27, 2024
1 parent 81a8a5d commit 41f605f
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 21 deletions.
6 changes: 6 additions & 0 deletions lib/data/editor/editor_history.dart
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,11 @@ class EditorHistoryItem {
this.page,
this.quillChange,
this.colorChange,
this.pageIndexStart, // original page of selection before it was moved to another page
}) : 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,7 @@ class EditorHistoryItem {

final EditorHistoryItemType type;
final int pageIndex;
final int? pageIndexStart; // original page of selected items before moved to another one
final List<Stroke> strokes;
final List<EditorImage> images;
final Rect? offset;
Expand All @@ -151,6 +155,7 @@ class EditorHistoryItem {
EditorHistoryItem copyWith({
EditorHistoryItemType? type,
int? pageIndex,
int? pageIndexStart,
List<Stroke>? strokes,
List<EditorImage>? images,
Rect? offset,
Expand All @@ -161,6 +166,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
6 changes: 6 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, // page index when selection was created
);
bool doneSelecting = false;

Expand Down Expand Up @@ -57,6 +58,7 @@ class Select extends Tool {
strokes: [],
images: [],
path: Path(),
pageIndexStart: pageIndex, // page index when selection was created
);
selectResult.path.moveTo(position.dx, position.dy);
onDragUpdate(position);
Expand Down Expand Up @@ -127,12 +129,14 @@ class SelectResult {
final List<Stroke> strokes;
final List<EditorImage> images;
Path path;
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 +148,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,
);
}
}
97 changes: 76 additions & 21 deletions lib/pages/editor/editor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -411,18 +411,28 @@ class EditorState extends State<Editor> {
}

case EditorHistoryItemType.move:
// all movement of selection was on one page
for (Stroke stroke in item.strokes) {
stroke.shift(Offset(
-item.offset!.left,
-item.offset!.top,
));
if (item.pageIndex!=item.pageIndexStart) {
// stroke must be on original page when selection movements started
int pageIndexStart = item.pageIndexStart ?? -1;
moveStrokeToPage(stroke, item.pageIndex, 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) {
int pageIndexStart = item.pageIndexStart ?? -1;
select.selectResult.pageIndex=pageIndexStart;
}
}
for (EditorImage image in item.images) {
image.dstRect = Rect.fromLTRB(
Expand All @@ -431,6 +441,11 @@ class EditorState extends State<Editor> {
image.dstRect.right - item.offset!.right,
image.dstRect.bottom - item.offset!.bottom,
);
if (item.pageIndex!=item.pageIndexStart) {
// image must be on original page when selection movements started
int pageIndexStart = item.pageIndexStart ?? 0;
moveImageToPage(image, item.pageIndex, pageIndexStart);
}
}

case EditorHistoryItemType.quillChange:
Expand Down Expand Up @@ -469,6 +484,8 @@ class EditorState extends State<Editor> {
undo(item.copyWith(type: EditorHistoryItemType.deletePage));
case EditorHistoryItemType.move:
undo(item.copyWith(
pageIndex: item.pageIndexStart, // exchange page and Start page
pageIndexStart: item.pageIndex,
offset: Rect.fromLTRB(
-item.offset!.left,
-item.offset!.top,
Expand Down Expand Up @@ -638,7 +655,9 @@ class EditorState extends State<Editor> {
}
// shift also selection path
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');
Expand Down Expand Up @@ -666,15 +685,57 @@ class EditorState extends State<Editor> {
position = pageNew.renderBox!.globalToLocal(details.focalPoint);
double rectBottom=pageNew.size.height;
//log.info('New page rect $rectTop to $rectBottom. Position on new page is $cursorPosition');
offset=Offset(offset.dx,offset.dy-pageOffset*(rectBottom+distOffset)); // put offset to original page
setState(() {}); // force update of builder so movement of selection to another page is taken into account
// recalculate the offset as if the selection were always moving to one page. Important for undo/redo
offset=Offset(offset.dx,offset.dy-pageOffset*(rectBottom+distOffset));
// setState(() {}); // force update of builder so movement of selection to another page is taken into account
pageNew.redrawStrokes(); // and finally redraw new page
}

previousPosition = position;
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;
Expand All @@ -687,27 +748,20 @@ class EditorState extends State<Editor> {
if (newPage<0 || newPage>coreInfo.pages.length-1){
return;
}
final pageOld = coreInfo.pages[oldPage];
final pageNew = coreInfo.pages[newPage];
final strokes = select.selectResult.strokes;
final images = select.selectResult.images;

// remove from original page
for (Stroke stroke in strokes) {
pageOld.strokes.remove(stroke);
}
for (EditorImage image in images) {
pageOld.images.remove(image);
}
// add to new page
for (Stroke stroke in strokes) {
pageNew.strokes.add(stroke);
}
for (EditorImage image in images) {
pageNew.images.add(image);
}
// move selection to new page
select.selectResult.pageIndex+=pageOffset;
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) {
Expand Down Expand Up @@ -745,7 +799,8 @@ 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 Down

0 comments on commit 41f605f

Please sign in to comment.