-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
fix(ActiveSelection): reset positioning when cleared #9088
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
7b27055
fix(ActiveSelection): reset positioning on `removeAll`
ShaMan123 799d65d
update CHANGELOG.md
github-actions[bot] 5a37333
Update ActiveSelection.spec.ts
ShaMan123 b45bf90
extensive
ShaMan123 77cd615
really fix
ShaMan123 92e0c5e
Update ActiveSelection.ts
ShaMan123 dad97ae
update CHANGELOG.md
github-actions[bot] 2fd0aa0
m
ShaMan123 6deed1c
Merge branch 'master' into fix-selection-9087
ShaMan123 a093193
test
ShaMan123 d7efde7
Merge branch 'master' into fix-selection-9087
asturur 9bbf3c3
updated tests
asturur 4254c95
with files renamed
asturur fcbdbe2
i was supposed to build before regenerating
asturur File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { expect, test } from '@playwright/test'; | ||
import { CanvasUtil } from '../../../utils/CanvasUtil'; | ||
|
||
import '../../../setup'; | ||
|
||
test('selection stale state #9087', async ({ page }) => { | ||
await test.step('select', async () => { | ||
await page.mouse.move(20, 20); | ||
await page.mouse.down(); | ||
await page.mouse.move(600, 600, { steps: 20 }); | ||
await page.mouse.up(); | ||
}); | ||
await test.step('rotate', async () => { | ||
await page.mouse.move(400, 150); | ||
await page.mouse.down(); | ||
await page.mouse.move(570, 150, { steps: 20 }); | ||
await page.mouse.up(); | ||
}); | ||
await test.step('deselect', async () => { | ||
await page.mouse.move(20, 20); | ||
await page.mouse.down(); | ||
await page.mouse.up(); | ||
}); | ||
await test.step('select', async () => { | ||
await page.mouse.move(20, 20); | ||
await page.mouse.down(); | ||
await page.mouse.move(600, 600, { steps: 20 }); | ||
await page.mouse.up(); | ||
}); | ||
expect(await new CanvasUtil(page).screenshot()).toMatchSnapshot(); | ||
}); |
Binary file added
BIN
+12.5 KB
.../selection/stale-state/index.spec.ts-snapshots/selection-stale-state-9087-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { Rect } from 'fabric'; | ||
import { beforeAll } from '../../test'; | ||
|
||
beforeAll( | ||
(canvas) => { | ||
const centerPoint = canvas.getCenterPoint(); | ||
const rect1 = new Rect({ | ||
width: 75, | ||
height: 75, | ||
top: centerPoint.y - 75, | ||
left: centerPoint.x - 75, | ||
originX: 'center', | ||
originY: 'center', | ||
}); | ||
const rect2 = new Rect({ | ||
width: 75, | ||
height: 75, | ||
top: centerPoint.y + 75, | ||
left: centerPoint.x + 75, | ||
originX: 'center', | ||
originY: 'center', | ||
}); | ||
canvas.add(rect1, rect2); | ||
canvas.on('mouse:down', ({ pointer, absolutePointer }) => | ||
console.log(pointer, absolutePointer) | ||
); | ||
canvas.on('mouse:up', ({ pointer, absolutePointer }) => | ||
console.log(pointer, absolutePointer) | ||
); | ||
return { rect1, rect2 }; | ||
}, | ||
{ enableRetinaScaling: false } | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { ActiveSelection } from './ActiveSelection'; | ||
import { FabricObject } from './Object/FabricObject'; | ||
|
||
describe('ActiveSelection', () => { | ||
it('clearing active selection objects resets transform', () => { | ||
const obj = new FabricObject({ | ||
left: 100, | ||
top: 100, | ||
width: 100, | ||
height: 100, | ||
}); | ||
const selection = new ActiveSelection([obj], { | ||
left: 200, | ||
top: 200, | ||
angle: 45, | ||
skewX: 0.5, | ||
skewY: -0.5, | ||
}); | ||
selection.remove(obj); | ||
expect(selection).toMatchObject({ | ||
left: 0, | ||
top: 0, | ||
angle: 0, | ||
scaleX: 1, | ||
scaleY: 1, | ||
skewX: 0, | ||
skewY: 0, | ||
flipX: false, | ||
flipY: false, | ||
_objects: [], | ||
}); | ||
}); | ||
|
||
it('deselect removes all objects and resets transform', () => { | ||
const selection = new ActiveSelection([], { | ||
left: 200, | ||
top: 100, | ||
angle: 45, | ||
}); | ||
const spy = jest.spyOn(selection, 'removeAll'); | ||
selection.onDeselect(); | ||
expect(spy).toHaveBeenCalled(); | ||
expect(selection).toMatchObject({ | ||
left: 0, | ||
top: 0, | ||
angle: 0, | ||
scaleX: 1, | ||
scaleY: 1, | ||
skewX: 0, | ||
skewY: 0, | ||
flipX: false, | ||
flipY: false, | ||
_objects: [], | ||
}); | ||
selection.add(new FabricObject({ left: 50, top: 50, strokeWidth: 0 })); | ||
expect(selection.item(0).getCenterPoint()).toEqual({ x: 50, y: 50 }); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a reason why resetting and not doing
new ActiveSelection([])
?In this way the reset becomes an ActiveSelection issue, while creating it is a canvas issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To keep the ref so we can listen to events etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also if somrone subclasses they can set the ref and it will remain as is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that this is an evidence that keeping the same reference for ActiveSelection is a bad breaking change and design. It causes bugs and workarounds for things that were more natural behaviour, e.g. #9066.
What's an use case for listening events on the ActiveSelection? Is there an alternative that doesn't require keeping the same reference?
Not clear to me, can you make an example of use case + code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enterGroup
when group is rotated.multiSelectAdd
). Also toggling selectablility of objects, responding visually to stuff etc.multiSelectAdd
to block objects that should not be selected from being added to the selection (formerly_createActiveSelection
,_updateActiveSelection
)ActiveSelection
was_createActiveSelection
.Activeselection
protected - that will help devs see the change.setActiveObject
if they must continue creating active selections:I do think it makes sense holding the ref but I am not fixed on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Legit point of view
I am agnostic
It is a breaking change, and the worst kind because it is silent
However we want to publish with as less changes as possible at this point
@asturur I know you didn't like the const ref either. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i forgot to update myself on this. i ll do and let's clear this out soon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First question, is there any reason why here we do this manual change while in _discardActiveObject we call the util
resetObjectTransform
?We could extend resetObjectTransform to handle top and left since seems clear to me that in both cases we use resetObjectTransform we don't care for survival of top/left.
My general idea is that is late to remove this reference activeSelection even if i don't like it at all, it would be nice to reuse resetObjectTransform to save code duplication.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as fabric does not create instances of active selection I am ok with dropping the ref.
A bit late, but fine. Lets take advantage of beta.
Second, the resetting should occur in group in terms of expectation, not only active selection.
I do not remeber why I didn't use resetObjectTransform but I do remember considering it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only reason why i don't want to remove the ref is because i don't like go back and forth on choices.
We made this, let's move forward with this. If some issue will arise we will have to reconsider and we will do a breaking change.
i will try to reuse resetObject trasform in a separate PR, i can't see any reason for it to be a problem.