| Summary: | Refactor ITransformableContentPart, IResizableContentPart, IBendableContentPart, and related policies. | ||
|---|---|---|---|
| Product: | [Tools] GEF | Reporter: | Matthias Wienand <matthias.wienand> |
| Component: | GEF MVC | Assignee: | gef-inbox <gef-inbox> |
| Status: | RESOLVED FIXED | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | nyssen |
| Version: | 1.0.0 | ||
| Target Milestone: | 5.0.0 (Oxygen) M3 | ||
| Hardware: | All | ||
| OS: | All | ||
| Whiteboard: | |||
Once bug 496248 has been resolved, the IDoableVisualPart, IFXDoableVisualPart, and IFXDoableContentPart interfaces can be removed, and the combined functionality can be provided by IDoableContentPart. It seems the abstractions are not wisely cut yet. For me, Bendable seems to be a specialization of Transformable and Resizable. This is also reflected by having specializations of TransformPolicy and ResizePolicy for Connection (Bendable). As we have now reduced the concepts to ITransformableContentPart, IResizableContentPart, and IBendableContentPart, we need to ensure that all policies and operations properly use the newly introduced interfaces. I changed the contract for the interface methods so that the type of the object that determines the transformation, size, or bend-points is the same for the visual and the content. I also renamed the methods to match regular getters and setters. Thus, the ITransformableContentPart interface, for example, does now offer the following methods: + getContentTransform():Affine // no default / needs to be implemented + setContentTransform(Affine) // no default / needs to be implemented + getVisualTransform():Affine // default + setVisualTransform(Affine) // default Therefore, refreshing the visualization based on the model can now be written as: setVisualTransform(getContentTransform()), setVisualSize(getContentSize()), and setVisualBendPoints(getContentBendPoints()). The IBendableContentPart interface does now extend ITransformableContentPart and IResizableContentPart. The transformation and size are determined using the bend-points, as follows: - The transformation is computed as the translation to the offset of the bounds around the unattached bend-points. - The size is computed as the size of the bounds around the unattached bend-points. These changes allow removing the TransformBendablePolicy and ResizeBendablePolicy classes as the TransformPolicy and ResizePolicy can now be used for IBendableContentParts per default. However, this led me to think about the various Bounds/Outline-Provider implementations (ShapeBoundsProvider, GeometricBoundsProvider, ShapeOutlineProvider, GeometricOutlineProvider) which need to be aligned to the functionality that is executed when dragging handles that are placed on the bounds. Imho, we should provide a TransformableResizableBoundsProvider that uses the transformation and the size as returned by the part-API (ITransformableContentPart#getVisualTransform(), IResizableContentPart#getVisualSize()) in order to determine the bounds rather than using the visual bounds as returned by JavaFX. When a handle that is placed on such bounds is dragged, the change in translation and/or size can be expressed by corresponding calls to setVisualTransform()/setVisualSize(), which is not true for changes to the real visual bounds. Moreover, before resolving this ticket, we should investigate if the refreshing of ITransformable*, IResizable*, and IBendable* should be done per default within AbstractContentPart#doRefreshVisual(), making an explicit implementation unnecessary if only transform, size, and/or bend-points need to be adjusted. I added a bounds and an outline geometry provider based-on the IResizableContentPart and ITransformableContentPart interfaces: ResizableTransformableBoundsProvider and ResizableTransformableOutlineProvider. These can be used to compute the bounds according to IResizableContentPart#getVisualSize() and ITransformableContentPart#getVisualTransform() within the local coordinate system of the part's visual. Currently, they fallback to the JavaFX bounds-in-local property of the part's visual, but already access #getVisualSize() and #getVisualTransform() to determine the bounds for IBendableContentParts. The ResizableTransformableBoundsProvider is used internally within ResizeTransformSelectionOnHandleDragPolicy and DefaultSelectionHandlePartFactory for computing the individual bounds of the selected parts. I also fixed the regression regarding transformed shapes in the MVC Logo example, so that handles for a multi selection containing transformed shapes are now positioned closely around the transformed shapes and stay under the mouse cursor during TransformResize. Moreover, I reverted the feedback for curves within the MVC Logo example. The code is published on the master branch. Further adjusting the feedback and automatically refreshing ITransformableContentPart, IResizableContentPart, and IBendableContentPart should imho be implemented in the context of subsequent Bugzilla tickets. Therefore, I resolve this ticket as fixed for 5.0.0 M3. |
Currently, the interfaces ITransformableContentPart, IResizableContentPart, and IBendableContentPart provide methods that can be used to modifiy the underlying content of the implementing IContentPart with regards to applied transformations, dimensions/size, and bend-points/way-points. However, the interfaces do not provide methods to query the currently applied transformations, the current dimensions, and the current bend-points, respectively. Therefore, such functionality is currently implemented within the different policy implementations. As a result, the policies need to be exchanged if the default computation needs to be adjusted (as is often the case for FXResizePolicy). In order to reduce the situations in which policies need to be replaced, as well as making the overall mechanisms more flexible, the interface hierarchy should be refined and default implementations should be provided for JavaFX visuals, as follows: IDoableVisualPart (abstract functionality) ^ ^ | | IDoableContentPart (content functionality) ^ | | IFXDoableVisualPart (default functionality) \ ^ \ / IFXDoableContentPart (combined default functionality and content functionality) For the current use cases, this results in the following interfaces: Resize: - IResizableVisualPart: abstract visual resize functionality - IResizableContentPart extends IRVP: abstract content resize functionality - IFXResizableVisualPart: default visual resize functionality for JavaFX - IFXResizableContentPart: combines IRCP and IFXRVP Transform: - ITransformableVisualPart: abstract visual transform functionality - ITransformableContentPart extends ITVP: abstract content transform functionality - IFXTransformableVisualPart: default visual transform functionality for JavaFX - IFXTransformableContentPart: combines ITCP and IFXTVP Bend: - IBendableVisualPart: abstract visual bend functionality - IBendableContentPart extends IBVP: abstract content bend functionality - IFXBendableVisualPart: default visual bend functionality for JavaFX - IFXBendableContentPart: combines IBCP and IFXBVP The default functionality can be extracted from the respective policies and operations, and provided by the default implementations within the interfaces. Furthermore, refreshing the visualization of a content-part w.r.t. the respective aspect (transformation, bend-points, size) can be automated by providing corresponding methods in the IDoableContentPart and IFXDoableContentPart interfaces, for example, doRefreshVisualSize() and getContentSize() for IResizableContentPart. During this refactoring, the contracts for modifications should be aligned, i.e. the final transformation should be passed-in to the #transformVisual() and #transformContent() methods, because the final state is also passed-in to the modification methods in the case of bending or resizing.