Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 306886

Summary: Rework org.eclipse.draw2d.geometry.Translatable & org.eclipse.draw2d.geometry.Transform.
Product: [Tools] GEF Reporter: Alexander Nyßen <nyssen>
Component: GEF-Legacy Draw2dAssignee: gef-inbox <gef-inbox>
Status: RESOLVED INVALID QA Contact:
Severity: enhancement    
Priority: P3    
Version: unspecified   
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard:

Description Alexander Nyßen CLA 2010-03-23 18:14:48 EDT
Build Identifier:  M20090917-0800

Out of the three conceptual types of linear transformations (translation, scaling, and rotation) org.eclipse.draw2d.geometry.Translatable actually supports two (and not just translation, as the name could imply), namely translation and scaling. This seems to be misleading and I would thus propose to rename Translatable into Transformable to make it clearer that the interface does not limit itself to translations. While doing so I would indeed also augment it with a performRotate method. This would not only make it conceptually complete, it would also allow to e.g. use rotation also within translateToRelative/translateToAbsolute/translateToParent/translateFromParent, which could be quite useful when coming up with a more decent support for rotated figures.

org.eclipse.draw2d.geometry.Transform could be reworked in this context as well, generalizing its getTransformed(Point) method into a getTransformed(Transformable) and in this turn reimplementing it by delegating to the respective performXXX() Transformable interface methods. This way Transform could indeed encapsulate an arbitrary linear transformation to be performed on an arbitrary Transformable. As such it could in this context be renamed to Transformation as well, to better point out that it encapsulates such an operation.

Reproducible: Always
Comment 1 Alexander Nyßen CLA 2010-03-23 19:28:45 EDT
Adding support for rotation would have rather wide-ranging effects. In case of Dimension, rotation e.g. makes no sense at all. Further, where it is supported, it can of course not always be performed in a "type-preserving" manner (e.g. on Rectangles), and a performRotate method would thus have to return a more general geometric shape (e.g. PointList or a newly introduced Polygon) as its return value (indeed it would rather have to be a getRotated() rather than a performRotate() method due to this). This in turn would make it necessary to generalize figure's getBounds() from Rectangle to PointList/Polygon as well (in case rotation would have to be performed during coordinate system calculations between child and parent figures, similar to as it currently done for scaling). While this seems to be the prerequisite to a more decent handling of rotated figures (e.g. in layout manager, where the rotated bounds could then be evaluated) it obviously comes at the cost of a severe API change and would therefore need decent planning and a detailed migration plan. 

Coming back to Dimension, translation actually does not seem to be a valid transformation  as well (up to now it is simply ignored by implementing performTranslate() with an empty body). 

As such it could be an option to introduce three separate interfaces (Translatable, Rotatable, Scalable) to address the different transformation types. Transformable could then be defined as a common super interface (as a starting point, maybe only of Translatable and Scalable) that could be used in the coordinate system related calculations (translateToRelative, etc.).
Comment 2 Alexander Nyßen CLA 2010-03-24 17:41:07 EDT
As this may be misunderstood, let me clarify what I meant with that rotation could not be performed type-safe on rectangles: 

What I actually was referring to is that the current Rectangle implementation does not support alike, as it does not take into account a rotation angle and its intersection and union operations thus guarantee to return Rectangles again, which would not be possible in case a rotation angle would have to be taken into account. Of course it would be an option to re-implement Rectangle (and other geometric shapes) to this extend and to then offer a performRotate() method as indicated before. I just wanted to point out that this would mean to revise those kind of operations, and to further re-implement much of the existing other methods to take a rotation angle into account. Yet, it might probably the cleanest solution, even if more costly than the simple getRotated() approach sketched before.
Comment 3 Alexander Nyßen CLA 2010-03-27 04:46:05 EDT
Having reconsidered this, I think the best (and simplest solution) would probably be to define rotation only on PointLists (while generalizing them to paths) and leave the other geometric shapes untouched. 

A migration scenario could be as follows:

1) Splitting the Translatable and Scalable interfaces and introducing a new Transformable interface to combine the two (to be used in all coordinate system related calculations) is reasonable, as it would allow to limit those operations to the respective geometric types that actually support them. It could be achieved with minor effort, yet it would still mean to break API.

2) Introduction of a new Rotatable interface could then be a next step. A Path could be introduced as a generalization of PointList, being then the only type to implement the complete set of interfaces, i.e. Transformable(Translatable, Scalable) and Rotatable. Transform could be generalized to work with those Paths instead of only points.

3) As a last step, Transformable could be generalized to also subsume rotation (i.e. implement Rotatable). This however would mean to also generalize figure's bounds to paths, as coordinate system related calculations (i.e. translateToRelative, ...) would only be supported on Paths (being the only Transformables then).

While 1) and 2) could be something for the next larger release, 3) will have to be intensively discussed and planned, as it would mean to revise a lot of the existing API. I will thus close this one and raise two respective bugzillas to address the topics individually.