Placing caption in the top left corner (instead of center)

Oct 10, 2012 at 8:42 AM

Hi,

In my custom shape, derived from standard Box shape, the caption must be located in the top left corner (and not in the center) and must have maximum width equal to the shape's width.

Which of the methods should I override? -

  • GetCaptionBounds
  • GetCaptionTextBounds
  • CalcCaptionBounds

And which coordinates system should be used when setting those bounds? (shape or design surface)

Thank you.

Coordinator
Oct 10, 2012 at 9:39 AM

First of all:
You should consider deriving your shape from RectangleBase instead of Box. This would require only a reference to Dataweb.NShape.dll and you could remove the reference to Dataweb.NShape.GeneralShapes.dll.

The position of the text inside the text layout area ("caption bounds") is determined by the ParagraphStyle. It defines the text alignment, the text margins and other layout related behavior.

In order to extend the layout area of the text, override GetCaptionBounds. The rectangle calculated by this method defines the basic layout area related to the untransformed (unrotated and placed at the center of origin) shape. The other two methods refer to the actual size and position of the text used for hit testing and drawing of text borders. These two methods should be handled by the base class.

Oct 10, 2012 at 1:11 PM

Thank you again for the feedback.

I override the GetCaptionBounds() method as you recommend:

public override bool GetCaptionBounds(int index, out Point topLeft, out Point topRight, out Point bottomRight, out Point bottomLeft)
{
    int captionHeight = 20;

    Rectangle rect = this.GetBoundingRectangle(true);

    topLeft = new Point(rect.X + 10, rect.Y + 10);
    topRight = new Point(rect.X + rect.Width - 10, rect.Y + 10);
    bottomRight = new Point(rect.X + rect.Width - 10, rect.Y + 10 + captionHeight);
    bottomLeft = new Point(rect.X + 10, rect.Y + 10 + captionHeight);
    
    return true;
}

Also, in the InitializeToDefault() method override I changed ParagraphStyle to the style having Alignment = ContentAlignment.TopLeft.

However, this seems to be not enough: when I drop my shape on the design surface, the text area is shown as a standard small square in the center of the shape. Only when I double click it - it turns into a rectangle located where I need (i.e. in the top left corner, with a 10px offset - see my GetCaptionBounds method above). After I finish entering caption text and click mouse somewhere, the text "jumps" 10px up and 10px left - so it "sticks" to the top left corner. But should I double-click the text to enter "editing mode" - the text area moves to where it is expected to be (i.e. in the top left corner, with a 10px offset). Besides, if I delete the text, the text area again turns into a standard small square in the center of the shape.

This is not very consistent. I expected that text area (even when it's empty) will reside in the same place regardless of whether I'm in editing mode or not, and that after I finished editing, the text will reside in the same boundaries as the text area. In other words - I expected that there will be no central square, no text "jumping".

What am I doing wrong?

Coordinator
Oct 10, 2012 at 3:46 PM

This behavior is by design:
When moving the mouse over a shape's text a 'text area' indicator is drawn around the text - only around the text. We try to minimize the area occupied by the text in order to make it easier for the user to select a shape without entering the 'edit text' mode (especially when cycling through overlapping shapes).

If the caption contains no text, a small rectangle is displayed in the center of the layout area. So if the layout area (nearly) equals the size of the shape (default for most shapes), the text indicator for empty captions is drawn in the center. For ImageBasedShapes, which display their captions at the bottom, the 'empty caption indicator' is drawn at the bottom because the text's layout area is limited to one line.

You can experiment with the "GetCaptionBounds" and "GetCaptionTextBounds" methods if you want to override this behavior. Both methods return the transformed (rotated and at the shape's location) bounds of the text in diagram coordinates. "GetCaptionBounds" returns the (transformed) layout area whereas "GetCaptionTextBounds" returns the (transformed) area occupied by the caption's text.

Oct 11, 2012 at 5:32 AM

Thank you for the answer.