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

BREAKING(Object Stacking): 🔙 refactor logic to support Group 🔝 #8461

Merged
merged 52 commits into from
Dec 29, 2022
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
4b46dd6
init
ShaMan123 Nov 21, 2022
4fc4319
Update collection.mixin.ts
ShaMan123 Nov 21, 2022
84a75de
types
ShaMan123 Nov 21, 2022
339e8c1
Update object_interactivity.mixin.ts
ShaMan123 Nov 21, 2022
76f26d6
Update object.class.ts
ShaMan123 Nov 21, 2022
82ded9b
Update collection.mixin.ts
ShaMan123 Nov 21, 2022
a97d170
Update group.class.ts
ShaMan123 Nov 21, 2022
b4e85c2
Update group.js
ShaMan123 Nov 21, 2022
305e9bd
Update CHANGELOG.md
ShaMan123 Nov 21, 2022
07fbc40
Update group.class.ts
ShaMan123 Nov 21, 2022
9f187cb
Squashed commit of the following:
ShaMan123 Nov 21, 2022
4fe445f
Update group.class.ts
ShaMan123 Nov 21, 2022
c36121d
migrate AS
ShaMan123 Nov 21, 2022
9ac6ec3
Update active_selection.class.ts
ShaMan123 Nov 21, 2022
a77f803
Update activeselection.js
ShaMan123 Nov 21, 2022
69f5c38
Update active_selection.class.ts
ShaMan123 Nov 21, 2022
4e8db1a
remove redundant deep clone
ShaMan123 Nov 21, 2022
2061e5b
Revert "Squashed commit of the following:"
ShaMan123 Nov 21, 2022
3523a0b
rename
ShaMan123 Nov 21, 2022
7510e6c
Update active_selection.class.ts
ShaMan123 Nov 21, 2022
05b7968
init
ShaMan123 Nov 23, 2022
099489c
typo
ShaMan123 Nov 23, 2022
18b85b3
Squashed commit of the following:
ShaMan123 Nov 23, 2022
45abc34
TS complaining
ShaMan123 Nov 23, 2022
806b6e7
fix(): `_onAfterObjectsChange`
ShaMan123 Nov 23, 2022
13f6613
port group changes from #7878
ShaMan123 Nov 23, 2022
2205224
Update CHANGELOG.md
ShaMan123 Nov 23, 2022
b3fb13e
Merge branch 'master' into ts-group
ShaMan123 Nov 25, 2022
68d2280
fix merge conflict
ShaMan123 Nov 25, 2022
7b33323
more cleanup
ShaMan123 Nov 25, 2022
971c4d3
cleanup
ShaMan123 Nov 25, 2022
6525025
Merge branch 'ts-group' into collection-stacking
ShaMan123 Nov 25, 2022
cf82a83
temporary fix
ShaMan123 Nov 25, 2022
e1cb367
checkout patternBrush
ShaMan123 Nov 25, 2022
c8b15fb
Merge branch 'ts-group' into collection-stacking
ShaMan123 Nov 25, 2022
e3de06a
Merge branch 'master' into collection-stacking
ShaMan123 Nov 26, 2022
da869a9
Merge branch 'master' into collection-stacking
ShaMan123 Nov 27, 2022
dac93c4
adapt tests
ShaMan123 Nov 27, 2022
3971f4f
not private
ShaMan123 Nov 27, 2022
c490d23
stupid TS
ShaMan123 Nov 27, 2022
ff8f040
Merge branch 'master' into collection-stacking
ShaMan123 Nov 29, 2022
aa63f84
dep(): object stacking
ShaMan123 Nov 29, 2022
53693f7
Merge branch 'master' into collection-stacking
ShaMan123 Dec 5, 2022
97195e7
cleanup merge
ShaMan123 Dec 5, 2022
b9fecd1
Merge branch 'master' into collection-stacking
ShaMan123 Dec 9, 2022
3ff4106
Merge branch 'master' into collection-stacking
ShaMan123 Dec 12, 2022
f39ae71
Merge branch 'master' into collection-stacking
ShaMan123 Dec 18, 2022
a766702
fix conflict
ShaMan123 Dec 18, 2022
098c9d7
fix typo that wasn't found by tests
ShaMan123 Dec 18, 2022
a5035fc
test intersecting
ShaMan123 Dec 18, 2022
1dc1b34
Merge branch 'master' into collection-stacking
ShaMan123 Dec 19, 2022
044d619
fixed conflicts
asturur Dec 29, 2022
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## [next]

- fix(Object Stacking): 🔙 refactor logic to support Group 🔝
- chore(TS): migrate Group/ActiveSelection [#8455](https://github.com/fabricjs/fabric.js/pull/8455)
- chore(TS): Move object classes #8511
- chore(TS): polish text [#8489](https://github.com/fabricjs/fabric.js/pull/8489)
- chore(TS): fix import cycle, extract `groupSVGElements` [#8506](https://github.com/fabricjs/fabric.js/pull/8506)
Expand Down
1 change: 0 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import './src/mixins/canvas_gestures.mixin'; // optional gestures
import './src/mixins/canvas_animation.mixin'; // optional animation
import './src/mixins/canvas_straightening.mixin'; // optional animation
import './src/shapes/Object/FabricObject';
import './src/mixins/object_stacking.mixin'; // removed in #8461
import './src/mixins/stateful.mixin'; // will die soon
import './src/shapes/line.class';
import './src/shapes/circle.class';
Expand Down
152 changes: 152 additions & 0 deletions src/mixins/collection.mixin.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { fabric } from '../../HEADER';
import type { FabricObject } from '../shapes/Object/FabricObject';
import type { Constructor } from '../typedefs';
import { removeFromArray } from '../util/internals';

export function createCollectionMixin<TBase extends Constructor>(Base: TBase) {
class Collection extends Base {
Expand All @@ -19,6 +20,11 @@ export function createCollectionMixin<TBase extends Constructor>(Base: TBase) {
// subclasses should override this method
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
_onStackOrderChanged(object: FabricObject) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

we can if we want send the indexes (from ,to) to this method. For now nothing uses it.
Perhaps for an event...

// subclasses should override this method
}

/**
* Adds objects to collection
* Objects should be instances of (or inherit from) FabricObject
Expand Down Expand Up @@ -152,6 +158,152 @@ export function createCollectionMixin<TBase extends Constructor>(Base: TBase) {
return memo;
}, 0);
}

/**
* Moves an object or the objects of a multiple selection
* to the bottom of the stack of drawn objects
* @param {fabric.Object} object Object to send to back
* @returns {boolean} true if change occurred
*/
sendObjectToBack(object: FabricObject) {
if (!object || object === this._objects[0]) {
return false;
}
removeFromArray(this._objects, object);
this._objects.unshift(object);
this._onStackOrderChanged(object);
return true;
}

/**
* Moves an object or the objects of a multiple selection
* to the top of the stack of drawn objects
* @param {fabric.Object} object Object to send
* @returns {boolean} true if change occurred
*/
bringObjectToFront(object: FabricObject) {
if (!object || object === this._objects[this._objects.length - 1]) {
return false;
}
removeFromArray(this._objects, object);
this._objects.push(object);
this._onStackOrderChanged(object);
return true;
}

/**
* Moves an object or a selection down in stack of drawn objects
* An optional parameter, `intersecting` allows to move the object in behind
* the first intersecting object. Where intersection is calculated with
* bounding box. If no intersection is found, there will not be change in the
* stack.
* @param {fabric.Object} object Object to send
* @param {boolean} [intersecting] If `true`, send object behind next lower intersecting object
* @returns {boolean} true if change occurred
*/
sendObjectBackwards(object: FabricObject, intersecting?: boolean) {
if (!object) {
return false;
}
const idx = this._objects.indexOf(object);
if (idx !== 0) {
// if object is not on the bottom of stack
const newIdx = this.findNewLowerIndex(object, idx, intersecting);
removeFromArray(this._objects, object);
this._objects.splice(newIdx, 0, object);
this._onStackOrderChanged(object);
return true;
}
return false;
}

/**
* Moves an object or a selection up in stack of drawn objects
* An optional parameter, intersecting allows to move the object in front
* of the first intersecting object. Where intersection is calculated with
* bounding box. If no intersection is found, there will not be change in the
* stack.
* @param {fabric.Object} object Object to send
* @param {boolean} [intersecting] If `true`, send object in front of next upper intersecting object
* @returns {boolean} true if change occurred
*/
bringObjectForward(object: FabricObject, intersecting?: boolean) {
if (!object) {
return false;
}
const idx = this._objects.indexOf(object);
if (idx !== this._objects.length - 1) {
// if object is not on top of stack (last item in an array)
const newIdx = this.findNewUpperIndex(object, idx, intersecting);
removeFromArray(this._objects, object);
this._objects.splice(newIdx, 0, object);
this._onStackOrderChanged(object);
return true;
}
return false;
}

/**
* Moves an object to specified level in stack of drawn objects
* @param {fabric.Object} object Object to send
* @param {number} index Position to move to
* @returns {boolean} true if change occurred
*/
moveObjectTo(object: FabricObject, index: number) {
if (object === this._objects[index]) {
return false;
}
removeFromArray(this._objects, object);
this._objects.splice(index, 0, object);
this._onStackOrderChanged(object);
return true;
}

findNewLowerIndex(
object: FabricObject,
idx: number,
intersecting?: boolean
) {
let newIdx;

if (intersecting) {
newIdx = idx;
// traverse down the stack looking for the nearest intersecting object
for (let i = idx - 1; i >= 0; --i) {
if (object.isOverlapping(this._objects[i])) {
newIdx = i;
break;
}
}
} else {
newIdx = idx - 1;
}

return newIdx;
}

findNewUpperIndex(
object: FabricObject,
idx: number,
intersecting?: boolean
) {
let newIdx;

if (intersecting) {
newIdx = idx;
// traverse up the stack looking for the nearest intersecting object
for (let i = idx + 1; i < this.objects.length; ++i) {
if (object.isOverlapping(this.objects[i])) {
newIdx = i;
break;
}
}
} else {
newIdx = idx + 1;
}

return newIdx;
}
}

// https://github.com/microsoft/TypeScript/issues/32080
Expand Down
90 changes: 0 additions & 90 deletions src/mixins/object_stacking.mixin.ts

This file was deleted.

22 changes: 15 additions & 7 deletions src/shapes/Object/ObjectGeometry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,8 @@ export class ObjectGeometry<
intersectsWithRect(
pointTL: Point,
pointBR: Point,
absolute: boolean,
calculate: boolean
absolute?: boolean,
calculate?: boolean
): boolean {
const coords = this.getCoords(absolute, calculate),
intersection = Intersection.intersectPolygonRectangle(
Expand Down Expand Up @@ -341,8 +341,8 @@ export class ObjectGeometry<
isContainedWithinRect(
pointTL: Point,
pointBR: Point,
absolute: boolean,
calculate: boolean
absolute?: boolean,
calculate?: boolean
): boolean {
const boundingRect = this.getBoundingRect(absolute, calculate);
return (
Expand All @@ -353,6 +353,14 @@ export class ObjectGeometry<
);
}

isOverlapping<T extends ObjectGeometry>(other: T): boolean {
return (
this.intersectsWithObject(other) ||
this.isContainedWithinObject(other) ||
other.isContainedWithinObject(this)
);
}

/**
* Checks if point is inside the object
* @param {Point} point Point to check against
Expand Down Expand Up @@ -417,7 +425,7 @@ export class ObjectGeometry<
private _containsCenterOfCanvas(
pointTL: Point,
pointBR: Point,
calculate: boolean
calculate?: boolean
): boolean {
// worst case scenario the object is so big that contains the screen
const centerPoint = pointTL.midPointFrom(pointBR);
Expand All @@ -429,7 +437,7 @@ export class ObjectGeometry<
* @param {Boolean} [calculate] use coordinates of current position instead of stored ones
* @return {Boolean} true if object is partially contained within canvas
*/
isPartiallyOnScreen(calculate: boolean): boolean {
isPartiallyOnScreen(calculate?: boolean): boolean {
if (!this.canvas) {
return false;
}
Expand Down Expand Up @@ -583,7 +591,7 @@ export class ObjectGeometry<
* @param {Boolean} absolute ignore viewport
* @return {void}
*/
scaleToWidth(value: number, absolute: boolean) {
scaleToWidth(value: number, absolute?: boolean) {
// adjust to bounding rect factor so that rotated shapes would fit as well
const boundingRectFactor =
this.getBoundingRect(absolute).width / this.getScaledWidth();
Expand Down
1 change: 0 additions & 1 deletion src/shapes/active_selection.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export class ActiveSelection extends Group {
* @param {FabricObject[]} targets
*/
_onAfterObjectsChange(type: 'added' | 'removed', targets: FabricObject[]) {
// @TODO figure out this change. This part wasn't here before migration.
super._onAfterObjectsChange(type, targets);
const groups: Group[] = [];
targets.forEach((object) => {
Expand Down
4 changes: 4 additions & 0 deletions src/shapes/group.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,10 @@ export class Group extends createCollectionMixin(FabricObject<GroupEvents>) {
this._set('dirty', true);
}

_onStackOrderChanged() {
this._set('dirty', true);
}

/**
* @private
* @param {string} key
Expand Down
Loading