-
-
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(Group, LayoutManager) Correctly dispose LayoutManager when disposing the Group #9787
base: master
Are you sure you want to change the base?
Conversation
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
let me see what dispose does because i do not know. |
i ll try to write it here as sort of loud thinking. In the case of groups i do not see any difference. For activeSelections it may be a little bit different ( description to follow ) |
You're right, I didn't notice ActiveSelectionLayoutManager has its peculiar subscriptions. I tried to do this: dispose(): void {
this.unsubscribeTargets({
targets: this.getObjects(),
target: this,
});
super.dispose()
} But I'm missing the ActiveSelection reference from the LayoutManager |
Yes but we could have left a bug here or there. if the current group code is better than dispose, it should become the dispose code. |
I m not sure this is worth anyone time if you don't have a bug in your hands. |
I have a LayoutManager subclass that has listeners to dispose of, that's why I'd like But I can call |
This would fix the problem without regressions: // Group.ts
dispose() {
this.layoutManager.unsubscribeTargets({
targets: this.getObjects(),
target: this,
});
this.layoutManager.dispose()
} What do you think? |
i m trying to understand why the
is not calling the disposal part for you. |
What do you mean? It's not calling export class MyLayoutManager {
constructor(strategy) {
super(strategy)
this.disposers = [
canvas.on("something", () => { ... })
]
}
dispose() {
this.disposers = []
}
} So my issue is being with |
it seems to me that when we call unsubscribe targets with all the objects as targets, we effectively wipe away all the disposers. don't we? |
How do you clear the custom disposers? |
i do not know i think your change is fine, i m just trying to catch up with this usage. I'm trying to find out why that is not the case. |
so please add the part you deleted from the group inside the layout manager dispose method. try to wrap your case in a jest test if possible, try to represent your use case if possible rather than a generic function test, and write inside dispose why we do both unsubscribe and an extra run on the disposers |
Done, I've added a test as well but didn't do my use case. My use case was basically this: when dragging an object over a Group, I want the Group to resize automatically to fit including the dragged object. So I need to add an extra listener |
Yes also it would have required a full e2e test and since is not a functionality supported out of the box we can't really test for that. |
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.
For the mentioned use case: why not calling triggerLayout? I might be missing out on something.
I don't think we should merge this, see comment
@@ -582,6 +582,9 @@ export class Group | |||
targets: this.getObjects(), | |||
target: this, | |||
}); | |||
// dispose additional listeners that may have been | |||
// added by the developer on the layoutManager #9787 | |||
this.layoutManager.dispose(); |
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.
My only thought about this is that the layout manager isn't bound to a single group so if an app uses a single layout manager for multiple groups this will break it so this PR forces a unique layout manager for each group but that is not strictly necessary, I designed it to be decoupled.
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 never knew about sharing LayoutManager. How would one dispose it then?
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.
If you mean to leave disposing to the app-level, then dispose
in LayoutManager should be noop
and have a comment explaining that the developer should do it accordingly to their needs, e.g. whether to dispose it on group disposal or canvas disposal.
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.
My only thought about this is that the layout manager isn't bound to a single group so if an app uses a single layout manager for multiple groups this will break it so this PR forces a unique layout manager for each group but that is not strictly necessary, I designed it to be decoupled.
The sharing part was one of the contested parts of the design.
The group didn't have the layout manager, it had a bunch of methods to do the work of the layoutManager.
I asked if we could put those methods in a scoped box because with all the different ideas of layouts and functionality they were growing out of hand, and it was supposed to be a way to reduce clutter in the group. Period. The sharing between group is something that was added while you implemented the layoutManager but the usefulness of being shared isn't really clarified. It adds a lot of constrain to how this code should behave but what does it adds?
Indeed one of the first changes was to make every group generate its own layoutManager.
Can you make a case for the sharing part?
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.
This is the same as controls.
I did it like this because I know that is important for you.
class Group {
static ownDefaults = {
layoutManager: new LayoutManager() // shared across all instances
}
}
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.
Indeed one of the first changes was to make every group generate its own layoutManager.
I surfaced this when that happened IIRC
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.
It is not important for me, and i think it adds complexity both to signatures and usage.
The layout manager is just the group logic tucked away in a class. I don't see any need for sharing it across instances.
That's not the point, it's just an example. Think about the fact that you have a |
If I'm not wrong, it seems that
LayoutManager.dispose
is never called actually. Disposing of the layout manager completely is safer than unsubscribing the Group objects:dispose
in an extendedLayoutManager
class takes care of disposing other things