Page Index Toggle Pages: 1 Send TopicPrint
Hot Topic (More than 10 Replies) IconNode's Text not Rendering Correctly (Read 7334 times)
SWATalk
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 15
Joined: Oct 23rd, 2005
IconNode's Text not Rendering Correctly
Sep 12th, 2013 at 3:33am
Print Post  
Software version: 6.0.4
Diagram.DynamicLinks = true;
Diagram.MeasureUnit = Pixel;

I have created a custom node class (IconNode) based on the sample provided and the label property of the custom node does not render correctly. When the chart is small, the text does not appear but the link text does appear so it would appear there is a problem with how I am drawing the label for the IconNode. When I zoom in, the text property starts to appear but part of the top and bottom is cut off. As the diagram gets closer to 100%, the text is rendered correctly. I tried using labelBound.Inflate(5, 5) and then increased it to labelBound.inflate(100, 100) and that seem to work but the links aren’t rendered correctly at 100, 100. How can I resolve this issue?

My second issue involves laying out the custom nodes. If I use SpringLayout, it lays the nodes in one continuance line. When I change the layout to FractalLayout or TreeLayout (Radial), it displays the nodes correctly but the dynamic links do not work. I have also tried using FractalLayout with SpringLayout but that does not fix the dynamic links problem. Any ideas?

Custom Node class:

Code
Select All
 [Serializable]
    public class IconNode : DiagramNode
    {
        private Image m_Icon;
        private string m_Label;
        private StringFormat m_StringFormat;

        private static Image m_DefaultIcon;

        static IconNode()
        {
            m_DefaultIcon = new Bitmap(48, 48);

            Graphics g = Graphics.FromImage(m_DefaultIcon);
            Font f = new Font("Segoe UI", 48, FontStyle.Bold, GraphicsUnit.Pixel);

            g.FillRectangle(Brushes.Transparent, 0, 0, 48, 48);
            g.DrawString("?", f, Brushes.Black, 0, 0);

            f.Dispose();
            g.Dispose();
        }

        public IconNode(Diagram diagram)
            : base(diagram)
        {
            m_Icon = m_DefaultIcon;
            m_Label = "Label";

            m_StringFormat = new StringFormat();
            m_StringFormat.Alignment = StringAlignment.Center;
            m_StringFormat.LineAlignment = StringAlignment.Center;

            Bounds = new RectangleF(Bounds.Location, CalculateSize());
        }

        /// <summary>
        /// Gets or sets the image for the node.
        /// </summary>
        public Image Icon
        {
            get { return m_Icon; }
            set
            {
                m_Icon = value;
                Bounds = new RectangleF(Bounds.Location, CalculateSize());
            }
        }

        /// <summary>
        /// Gets or sets the label for a node.
        /// </summary>
        public string Label
        {
            get { return m_Label; }
            set
            {
                m_Label = value;
                Bounds = new RectangleF(Bounds.Location, CalculateSize());
            }
        }

        public override void DrawLocal(IGraphics graphics, RenderOptions options)
        {
            Rectangle iconSizePixels = new Rectangle(0, 0, m_Icon.Width, m_Icon.Height);
            RectangleF imageSize = MindFusion.Utilities.DeviceToDoc(graphics, iconSizePixels);

            RectangleF localBounds = GetLocalBounds();

            // Draw the icon at the top-middle
            graphics.DrawImage(m_Icon, localBounds.X + localBounds.Width / 2 - imageSize.Width / 2, localBounds.Y);

            // Draw the label at the bottom
            RectangleF labelBounds = RectangleF.FromLTRB(localBounds.X, localBounds.Y + imageSize.Height, localBounds.Right, localBounds.Bottom);
            labelBounds.Inflate(10, 10);
            graphics.DrawString(m_Label, EffectiveFont, Brushes.Black, labelBounds, m_StringFormat);
        }

        public override void DrawShadowLocal(IGraphics graphics, RenderOptions options) { }

        private SizeF CalculateSize()
        {
            Bitmap tempImage = new Bitmap(1, 1);
            Graphics graphics = Graphics.FromImage(tempImage);
            IGraphics measureGraphics = new GdiGraphics(graphics);

            measureGraphics.PageUnit = Parent.MeasureUnit;
            Rectangle iconSizePixels = new Rectangle(0, 0, m_Icon.Width, m_Icon.Height);
            RectangleF imageSize = MindFusion.Utilities.DeviceToDoc(measureGraphics, iconSizePixels);

            measureGraphics.Dispose();
            tempImage.Dispose();

            SizeF textSize = Parent.MeasureString(m_Label, EffectiveFont, int.MaxValue, m_StringFormat);

            return new SizeF(Math.Max(imageSize.Width, textSize.Width), imageSize.Height + textSize.Height);
        }

        protected override void UpdateCreate(PointF current)
        {
            base.UpdateCreate(current);
            Bounds = new RectangleF(current, CalculateSize());
        }

        protected override void SaveTo(BinaryWriter writer, PersistContext ctx)
        {
            base.SaveTo(writer, ctx);

            // Save the label using the standard .NET BinaryWriter
            writer.Write(m_Label);

            // Save the image using the MindFusion.Diagramming built-in image saving code,
            // which stores the contents of shared images only once.
            ctx.SaveImage(m_Icon);
        }

        protected override void LoadFrom(BinaryReader reader, PersistContext ctx)
        {
            base.LoadFrom(reader, ctx);

            m_Label = reader.ReadString();
            m_Icon = ctx.LoadImage();
        }
    }
 



Chart layout:
Code
Select All
private void InitializeCustomNode()
        {
            // Enable serialization of IconNode instances
            if ((diagram as IItemFactory).TypeTable[typeof(IconNode)] == null)
                Diagram.RegisterItemClass(typeof(IconNode), "IconNode", 1);

            // Let users draw IconNode objects
            diagramView.CustomNodeType = typeof(IconNode);

            //diagramView.Behavior = Behavior.Custom;
        }

private void InitializeLinkChart()
        {
            LinkChartService service = new LinkChartService();
            m_Entities = service.GetAllEdges();

            diagramView.AutoScroll = true;
            diagram.ShowGrid = false;
            diagramView.ShowScrollbars = true;

            // Changes the active item's handlestyle by showing a border when a node is selected.
            diagram.ActiveItemHandlesStyle.DashPen = new MindFusion.Drawing.Pen(Color.Blue);

            diagramView.SmoothingMode = SmoothingMode.AntiAlias;

            PopulateNodes();

            /*using (TreeLayout layout = new TreeLayout(TreeLayoutType.Radial))
            {
                layout.NodeDistance = 150;
                layout.Arrange(diagram);
            }*/

            using (FractalLayout layout = new FractalLayout())
            {
                layout.Anchoring = Anchoring.Reassign;
                layout.Arrange(diagram);
            }

            using (SpringLayout slayout = new SpringLayout(500, 200, true))
            {
                //slayout.BeginArrange(diagram, diagram.Items);

                slayout.EnableClusters = true;
                slayout.Arrange(diagram);

                //slayout.EndArrange();
            }

            diagram.AutoResize = AutoResize.AllDirections;
            diagram.ResizeToFitItems(diagram.Nodes.Count);
            diagramView.ZoomFactor = 50;
        }

private void PopulateNodes()
        {
            foreach (DataRow row in m_Entities.Rows)
            {
                //CreateNode((int)row["FromNodeId"], row["FromNode"].ToString());
                //CreateNode((int)row["ToNodeId"], row["ToNode"].ToString());

                //ConnectNodes((ShapeNode)diagram.FindNodeById((int)row["FromNodeId"]), (ShapeNode)diagram.FindNodeById((int)row["ToNodeId"]), row["RelationshipType"].ToString());

                CreateIconNode((int)row["FromNodeId"], row["FromNode"].ToString());
                CreateIconNode((int)row["ToNodeId"], row["ToNode"].ToString());

                ConnectIconNodes((IconNode)diagram.FindNodeById((int)row["FromNodeId"]), (IconNode)diagram.FindNodeById((int)row["ToNodeId"]), row["RelationshipType"].ToString());
            }
        }

private void CreateIconNode(int key, string value)
        {
            if (diagram.FindNodeById(key) != null)
                return;

            IconNode iconNode = new IconNode(diagram);
            iconNode.Id = key;
            iconNode.Label = value;
            iconNode.Icon = Properties.Resources.UserBlue48;
            iconNode.HandlesStyle = HandlesStyle.MoveOnly;
            diagram.Nodes.Add(iconNode);
        }

private void ConnectIconNodes(IconNode parent, IconNode child, string label)
        {
            if (child == null)
                return;

            DiagramLink link = diagram.Factory.CreateDiagramLink(parent, child);
            link.Text = label;
            link.TextStyle = LinkTextStyle.OverLongestSegment;
            link.Font = new System.Drawing.Font("Segoe UI", 9.0f);
        }
 

  

Nodes_no_text.png (Attachment deleted)
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: IconNode's Text not Rendering Correctly
Reply #1 - Sep 12th, 2013 at 10:50am
Print Post  
DeviceToDoc will not give you the correct document size of the image when there is ZoomFactor set; it expects size in pixels that corresponds to the zoom level, but you pass to it unscaled image size in pixels. Change ImageSize to following if you need to support multiple MeasureUnits:

Code
Select All
RectangleF imageSize = MindFusion.Utilities.DeviceToDoc(graphics, iconSizePixels);
imageSize.Width *= options.Scale / 100;
imageSize.Height *= options.Scale / 100; 



If using only pixels as unit, you do not need any conversion, and could just set Rectangle imageSize = iconSizePixels;

Try running SpringLayout with Randomize set to true if you start with all nodes at the same position.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
SWATalk
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 15
Joined: Oct 23rd, 2005
Re: IconNode's Text not Rendering Correctly
Reply #2 - Sep 12th, 2013 at 3:28pm
Print Post  
Spot on...problem solved.  Thanks Stoyo
  
Back to top
 
IP Logged
 
SWATalk
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 15
Joined: Oct 23rd, 2005
Re: IconNode's Text not Rendering Correctly
Reply #3 - Oct 2nd, 2013 at 2:39am
Print Post  
Back to square one.  This code actually does not work on a monitor with a resolution of 1920x1080.  In addition, when you view it by clicking print preview, all of the nodes are bunched together and does not look like anything that appears on the original diagram.

Any thoughts?
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: IconNode's Text not Rendering Correctly
Reply #4 - Oct 2nd, 2013 at 8:32am
Print Post  
It works fine in our test on 1920x1080, see attached screenshot. It shows IconNodes with unit set to Pixel, your version of the class and the scaling fix above applied. Have you changed anything else in the drawing code or properties from IconNodes?

When you use Pixel as unit, one unit corresponds to a device pixel. The nodes get bunched together because the printer pixels are much smaller. If you want to print with Pixel unit and get similar resolution as on screen, you will have to either apply additional scale in PrintOptions, or print a copy of the diagram where Unit is switched to Point (or WpfPoint = 96 dpi from version 6.1).

I hope that helps,
Stoyan
  

IconNodes_Zoom.png (Attachment deleted)
Back to top
 
IP Logged
 
SWATalk
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 15
Joined: Oct 23rd, 2005
Re: IconNode's Text not Rendering Correctly
Reply #5 - Oct 2nd, 2013 at 5:40pm
Print Post  
Unfortunately that does not work for me. This is what it looks like on my screen:

  

DefaultQMark.png (Attachment deleted)
IconNode.png (Attachment deleted)
Back to top
 
IP Logged
 
SWATalk
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 15
Joined: Oct 23rd, 2005
Re: IconNode's Text not Rendering Correctly
Reply #6 - Oct 2nd, 2013 at 5:43pm
Print Post  
Print preview code:
Code
Select All
public static double ScreenDPI(int monitorSize, int resolutionWidth, int resolutionHeight)
        {
            //int resolutionWidth = 1600;
            //int resolutionHeight = 1200;
            //int monitorSize = 19;
            if (0 < monitorSize)
            {
                double screenDpi = Math.Sqrt(Math.Pow(resolutionWidth, 2) + Math.Pow(resolutionHeight, 2)) / monitorSize;
                return screenDpi;
            }
            return 0;
        }
 



Print preview code
Code
Select All
diagramView.PrintOptions.HeaderFormat = "Diagram Title";

                    var screenResolution = ScreenDPI(24, 1920, 1080);
                    var printerResolution = 72f; // for Point unit

                    var newDiagramView = new DiagramView();
                    diagramView.Diagram.LoadFromString(diagram.SaveToString()); // copy the main diagram
                    diagramView.Diagram.MeasureUnit = GraphicsUnit.Point;
                    diagramView.PrintOptions.Scale = 100f * (float)(screenResolution / printerResolution);

                    // ****** Somewhat works ******
                    //diagram.MeasureUnit = GraphicsUnit.Point;
                    //diagramView.PrintOptions.Scale = 72;
                    //diagramView.PrintOptions.ScaleToPage();

                    //PrintDocument doc = new PrintDocument();
                    //diagramView.PrintOptions.Scale = doc.PrinterSettings.DefaultPageSettings.PrinterResolution.X;

                    diagramView.PrintPreviewEx();
 



When I click print preview and return to the diagram, the diagram looks like the print preview.  I don't think that's how it is supposed to function.
  

Print_Preview_2.png (Attachment deleted)
Before_Print_Preview.png (Attachment deleted)
After_Print_Preview.png (Attachment deleted)
Back to top
 
IP Logged
 
SWATalk
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 15
Joined: Oct 23rd, 2005
Re: IconNode's Text not Rendering Correctly
Reply #7 - Oct 2nd, 2013 at 6:43pm
Print Post  
I am drawing a border around the image and the question mark and this is what it looks like.  The border is drawn correctly but the "?" and the icon is not.  Any ideas?
  

Border-QMark.png (Attachment deleted)
Border-Icon.png (Attachment deleted)
Back to top
 
IP Logged
 
SWATalk
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 15
Joined: Oct 23rd, 2005
Re: IconNode's Text not Rendering Correctly
Reply #8 - Oct 2nd, 2013 at 6:46pm
Print Post  
This is the icon node and it is 48x48 and centered.
  

Imageforiconnode.png (Attachment deleted)
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: IconNode's Text not Rendering Correctly
Reply #9 - Oct 3rd, 2013 at 7:34am
Print Post  
SWATalk wrote on Oct 2nd, 2013 at 5:40pm:
Unfortunately that does not work for me. This is what it looks like on my screen:


This has nothing to do with your initial zoom problem.

The question mark is cut off because the bold 48px Segoe UI question mark symbol does not fit within the 48x48 bitmap when drawn aligned to top left corner. I suppose the actual glyph drawing starts around the 6th-7th scanline and then there's no place for the bottom part of the base point. It seems to fit ok if you draw it centered:

Code
Select All
static IconNode()
{
	m_DefaultIcon = new Bitmap(48, 48);

	Graphics g = Graphics.FromImage(m_DefaultIcon);
	Font f = new Font("Segoe UI", 48, FontStyle.Bold, GraphicsUnit.Pixel);

	g.FillRectangle(Brushes.Transparent, 0, 0, 48, 48);
	g.DrawString("?", f, Brushes.Black, 24, 24, new StringFormat
	{
		Alignment = StringAlignment.Center,
		LineAlignment = StringAlignment.Center
	});

	f.Dispose();
	g.Dispose();
} 



Quote:
The label is above the image but there should be a space ...


The labelBounds rectangle overlaps the icon rectangle after you call Inflate.

Code
Select All
RectangleF labelBounds = RectangleF.FromLTRB(localBounds.X, localBounds.Y + imageSize.Height, localBounds.Right, localBounds.Bottom);
// at this point labelBounds starts exactly below the image

labelBounds.Inflate(10, 10);
// now labelBounds starts 10 pixels above its old coordinates and overlaps the image
 



If you need to draw in a larger rectangle, make sure its Y starts below the icon's bottom line to avoid that overlap.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: IconNode's Text not Rendering Correctly
Reply #10 - Oct 3rd, 2013 at 7:49am
Print Post  
SWATalk wrote on Oct 2nd, 2013 at 5:43pm:
Print preview code:
Code
Select All
public static double ScreenDPI(int monitorSize, int resolutionWidth, int resolutionHeight)
        {
            //int resolutionWidth = 1600;
            //int resolutionHeight = 1200;
            //int monitorSize = 19;
            if (0 < monitorSize)
            {
                double screenDpi = Math.Sqrt(Math.Pow(resolutionWidth, 2) + Math.Pow(resolutionHeight, 2)) / monitorSize;
                return screenDpi;
            }
            return 0;
        }
 



Print preview code
Code
Select All
diagramView.PrintOptions.HeaderFormat = "Diagram Title";

                    var screenResolution = ScreenDPI(24, 1920, 1080);
                    var printerResolution = 72f; // for Point unit

                    var newDiagramView = new DiagramView();
                    diagramView.Diagram.LoadFromString(diagram.SaveToString()); // copy the main diagram
                    diagramView.Diagram.MeasureUnit = GraphicsUnit.Point;
                    diagramView.PrintOptions.Scale = 100f * (float)(screenResolution / printerResolution);

                    // ****** Somewhat works ******
                    //diagram.MeasureUnit = GraphicsUnit.Point;
                    //diagramView.PrintOptions.Scale = 72;
                    //diagramView.PrintOptions.ScaleToPage();

                    //PrintDocument doc = new PrintDocument();
                    //diagramView.PrintOptions.Scale = doc.PrinterSettings.DefaultPageSettings.PrinterResolution.X;

                    diagramView.PrintPreviewEx();
 



When I click print preview and return to the diagram, the diagram looks like the print preview. I don't think that's how it is supposed to function.


If you are changing MeasureUnit on the original diagram, you should restore it back to Pixel after calling PrintPreview. Or alternatively, print a copy of the diagram to prevent users from seeing the on-screen diagram changed (e.g. if the print preview window is not maximized).

Code
Select All
var copyForPrint = new Diagram();
copyForPrint.LoadFromString(diagram.SaveToString());
copyForPrint.MeasureUnit = GraphicUnit.Point;

var printView = new DagramView();
printView.Diagram = copyForPrint;
printView.PrintPreviewEx(); 



I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: IconNode's Text not Rendering Correctly
Reply #11 - Oct 3rd, 2013 at 8:02am
Print Post  
SWATalk wrote on Oct 2nd, 2013 at 6:43pm:
I am drawing a border around the image and the question mark and this is what it looks like. The border is drawn correctly but the "?" and the icon is not. Any ideas?


graphics.DrawImage(x, y) might be stretching the image a bit if its DPI is different than the screen's DPI. Try using the DrawImage(rect) overload instead:

Code
Select All
var iconRect = new RectangleF(
	localBounds.X + localBounds.Width / 2 - imageSize.Width / 2,
	localBounds.Y, imageSize.Width, imageSize.Height);
graphics.DrawImage(m_Icon, iconRect);
graphics.DrawRectangle(Pens.Red, iconRect); 



or try calling bitmap.SetResolution(graphics.DpiX, graphics.DpiY) before drawing with the (x,y) overload.

I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
SWATalk
YaBB Newbies
*
Offline


I love YaBB 1G - SP1!

Posts: 15
Joined: Oct 23rd, 2005
Re: IconNode's Text not Rendering Correctly
Reply #12 - Oct 4th, 2013 at 1:20am
Print Post  
Stoyo,

Your suggestions seemed to work, however, when I click print preview, the icons are really tiny.  Any ideas on a fix?
  
Back to top
 
IP Logged
 
Stoyo
God Member
*****
Offline


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: IconNode's Text not Rendering Correctly
Reply #13 - Oct 4th, 2013 at 6:31am
Print Post  
Hi,

The unit conversion in Draw actually gives you a size corresponding to 48 printer pixels; it seems to work fine if you remove it, both on printer and when zooming on the screen:

Code
Select All
//Rectangle iconSizePixels = new Rectangle(0, 0, m_Icon.Width, m_Icon.Height);
//RectangleF imageSize = MindFusion.Utilities.DeviceToDoc(graphics, iconSizePixels);

// now that's in device-independent points when printing
RectangleF imageSize = new Rectangle(0, 0, m_Icon.Width, m_Icon.Height); 



I hope that helps,
Stoyan
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint