Monday, April 23, 2007 1:17 PM Olaf Conijn

Creating cool DSL Shapes using GDI and Fonts

The DSL Toolkit knows a concept called shape (the thing that represents an element and is drawn on the modeling surface) and allows to define these shapes in 3 basic flavors:

1.)    Geometry Shapes. Either a Rectangle, Rounded rectangle, Ellipse or Circle
2.)    Image Shapes. An imported image
3.)    Compartment Shapes. Either a Rectangle or Rounded rectangle which contains compartments.

The “Geometry shape” has some advantages over the “Image shape”, it can be scaled and its style can be configured. The Geometry shape also features a shadow and cool highlight when hovering over it.
Geometry shapes are slightly harder to customize, though.... You should draw them in code using GDI.

Now, if you want to create your own geometry shapes it might be worth your while to have a look at some of the fonts (especially wingdings or webdings) on your system.
GDI you to import the structure of these fonts and draw them on a surface (DSL model?).



The way this works is:

1.) Place a “Geometry Shape” on your Dsl designer (mine is called “AlienShape”).
2.) In the property grid, Specify that a double derived class should be generated and set the Geometry property to “Circle”.
3.) After transforming the templates you should be able to derive from a class called “AlienShapeBase” and override its ShapeGeometry property to return your own.

public partial class AlienShape : AlienShapeBase
{
public override Microsoft.VisualStudio.Modeling.Diagrams.ShapeGeometry ShapeGeometry
{
get
{
FontShapeGeometry myShape = new FontShapeGeometry();
myShape.CharCode = (char)0x85;
myShape.FontName = "Webdings";

return myShape;
}
}
}

The FontShapeGeometry class uses the specified character and font to import this in a GDI structure, then manipulate it to fit your shape.
The implementation below, stretches the character to a Rectangularal shape. Since we derive from RectangleShapeGeomtery all the hit-testing, grabhandles, zooming and scaling should already be taken care of.

public class FontShapeGeometry : RectangleShapeGeometry
{
char c;
public char CharCode
{
get { return c; }
set { c = value; }
}

string fontName;
public string FontName
{
get { return fontName; }
set { fontName = value; }
}

public override System.Drawing.Drawing2D.GraphicsPath GetPath(IGeometryHost geometryHost)
{
RectangleF targetRect = RectangleD.ToRectangleF(geometryHost.GeometryBoundingBox);

GraphicsPath path = base.UninitializedPath;
path.Reset();

//draw the character in the GrpahicsPath on 1.1
path.AddString(new String(c, 1), new FontFamily(FontName), 1, 1, new RectangleF(0, 0, targetRect.Width, targetRect.Height), StringFormat.GenericDefault);

//Calculate the bounds of the drawn character, calculate whether we should scale it.
RectangleF currentBounds = path.GetBounds();
float scaleX = targetRect.Width / currentBounds.Width;
float scaleY = targetRect.Height / currentBounds.Height;

//Scale it
Matrix scaleTransform = new Matrix();
scaleTransform.Scale(scaleX, scaleY);
path.Transform(scaleTransform);

//Calculate the bounds of the scaled character, calculate the offset and apply this.
currentBounds = path.GetBounds();
Matrix translationTransform = new Matrix();
translationTransform.Translate(targetRect.Left - currentBounds.Left, targetRect.Top - currentBounds.Top);
path.Transform(translationTransform);

//return the path.
return path;
}
}



Filed under: , ,

# Cool shapes with DSL Tools

Friday, June 01, 2007 12:28 PM by stuart kent's blog

Olaf has an interesting post on how you can use fonts as shapes in a DSL Tool using a little bit of custom

# MSDN Blog Postings · Cool shapes with DSL Tools

Friday, June 01, 2007 3:12 PM by MSDN Blog Postings · Cool shapes with DSL Tools

Pingback from  MSDN Blog Postings · Cool shapes with DSL Tools