none
Transformations on AdornedElement are also applied to Adorner?!

    Question

  • Hi,

    I´m using Adorners on shapes and other controls.

    I´ve noticed that the Adorner is scaled, when the AdornedElement contains a transformation with a scale transform. But I don't want the Thumbs and the bounding rectangle in the Adorner to be scaled also.

    Is there an easy way around this, or do I manually have to scale these back again. In ArrangeOverride I might be able to scale down the Thumb accordingly if I find that there is a scale transform applied to the AdornedElement. It might not be that easy with the pen used to draw the bounding rectangle though, since it's no likely that it should be scaled down equally on all sides.

    Thanks in advance!

    / Joel
    Wednesday, June 14, 2006 6:17 AM

Answers

  • You'll need to override Adorner.GetDesiredTransform() and modify the passed transform to remove the scaling.  From the documentation for this method:

    Adorners don't always want to be transformed in the same way as the elements they adorn.  Adorners which adorn points, such as resize handles, want to be translated and rotated but not scaled.  Adorners adorning an object, like a marquee, may want all transforms.  This method is called by AdornerLayer to allow the adorner to filter out the transforms it doesn't want and return a new transform with just the transforms it wants applied.  An adorner can also add an additional translation transform at this time, allowing it to be positioned somewhere other than the upper left corner of its adorned element.

    There is no magic wand to wave to remove the scaling.  If there was more than one transform applied, the transform passed to GetDesiredTransform will often be a GeneralTransformGroup and you'll need to iterate across all the transforms in its Children collection to find the ScaleTransforms.  If there's only one transform, the GeneralTransform passed to GetDesiredTransform may be a ScaleTransform, in which case you can return Transform.Identity.

    Note that it's also possible to get a MatrixTransform that aggregates multiple transforms into a single matrix, rather than in a nice, iterable collection.  In that case you'd need to analyze the matrix to determine if there's a scaling factor.

    Of course, if the adorner for some reason already knows it's been scaled, you can just add an inverse scaling transform.

      - Peter

    Friday, July 28, 2006 8:42 PM

All replies

  • You'll need to override Adorner.GetDesiredTransform() and modify the passed transform to remove the scaling.  From the documentation for this method:

    Adorners don't always want to be transformed in the same way as the elements they adorn.  Adorners which adorn points, such as resize handles, want to be translated and rotated but not scaled.  Adorners adorning an object, like a marquee, may want all transforms.  This method is called by AdornerLayer to allow the adorner to filter out the transforms it doesn't want and return a new transform with just the transforms it wants applied.  An adorner can also add an additional translation transform at this time, allowing it to be positioned somewhere other than the upper left corner of its adorned element.

    There is no magic wand to wave to remove the scaling.  If there was more than one transform applied, the transform passed to GetDesiredTransform will often be a GeneralTransformGroup and you'll need to iterate across all the transforms in its Children collection to find the ScaleTransforms.  If there's only one transform, the GeneralTransform passed to GetDesiredTransform may be a ScaleTransform, in which case you can return Transform.Identity.

    Note that it's also possible to get a MatrixTransform that aggregates multiple transforms into a single matrix, rather than in a nice, iterable collection.  In that case you'd need to analyze the matrix to determine if there's a scaling factor.

    Of course, if the adorner for some reason already knows it's been scaled, you can just add an inverse scaling transform.

      - Peter

    Friday, July 28, 2006 8:42 PM
  • Okay, but what if I want the adorner itself to be scaled, but not its visual children.

    I have an adorner, where I draw a bounding rectangle around the adorned element. I also have some thumbs visible for resizing purposes. If I remove the scale in GetDesiredTransform, the Thumbs will not be scaled, which is very good. Now the problem is that they will not be positioned in the corners of the adorner element anymore, since the bounding box of the adorner is not scaled, i.e. the size of the adorner is not the same as that of the adorned element of course.

    Is there a standard way to let the adorner be scaled, but not its visual children, or do I have to inverse the scale on the children myself?

    / Joel
    Tuesday, August 01, 2006 8:23 AM
  • There's nothing magical about how an adorner is rendered-- it works just like any other UIElement.  If you apply a transform to the adorner, all its visual children will be affected by the transform.  You'll need to invert the scale on the children yourself (but you'll want to transform the position of each handle through the original scaling transform to make sure you put it in the right place).

      - Peter

    Thursday, August 03, 2006 7:43 PM