Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic strange behaviour in swimlane (Read 2238 times)
Michael
YaBB Newbies
*
Offline


I Love MindFusion!

Posts: 17
Joined: Nov 9th, 2012
strange behaviour in swimlane
Dec 2nd, 2014 at 1:24pm
Print Post  
Hallo
IŽm using a diagram with a swimlane diagram view. The grid of the diagram is a lane grid.
The diagram has three columns that get filled programmatically.
The first time the diagram gets filled with nodes and links everything looks like it should.
After clearing the content of the diagram with ClearAll() and refilling it with ch anged (e.g. only two of the columns are filled with nodes) content, everything is still looking fine. The error behavior comes with the third filling when the look changes completely (the third column has a black stroke and the links are shortened) and I canŽt localize the issue why.

Do you have any idea what can change in the code to get it work properly?

Attached youŽll find three pictures and the code behind of my diagram control.
Thank you very much.

Here is the Code
using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using IBS.Common.Enums;
using IBS.Common.PropertyClasses;
using Infragistics.Win.Misc;
using MindFusion.Diagramming;
using MindFusion.Diagramming.Lanes;
using MindFusion.Diagramming.Layout;
using MindFusion.Diagramming.WinForms;

namespace IBS.Controls
{
    public partial class SwimlaneControl : UserControl
    {
        SwimlaneLayout _layout;
        private Grid _grid;
        private MindFusion.Diagramming.Lanes.Style _laneStyle;
        private MindFusion.Drawing.Pen _whiteSmokePen;
        private float _startZoomFactor;

        public SwimlaneControl()
        {
            InitializeComponent();
            DiagramSetup();
        }
        private void DiagramSetup()
        {
            diagramView1.BackColor = Color.White;
            diagramView1.BackgroundImageLayout = ImageLayout.Center;
            diagramView1.Behavior = Behavior.Modify;
            diagramView1.ControlHandlesStyle = HandlesStyle.HatchHandles;
            diagramView1.ControlMouseAction = ControlMouseAction.SelectNode;
            diagramView1.DelKeyAction = DelKeyAction.DeleteSelectedItems;
            diagramView1.Diagram = diagram1;
            diagramView1.Dock = DockStyle.Fill;
            diagramView1.Location = new Point(0, 0);
            diagramView1.MiddleButtonActions = MouseButtonActions.None;
            diagramView1.ModificationStart = ModificationStart.SelectedOnly;
            diagramView1.RightButtonActions = MouseButtonActions.Cancel;
            diagramView1.Text = "";
            diagram1.ShadowsStyle = ShadowsStyle.None;
            diagram1.BackBrush = new MindFusion.Drawing.SolidBrush(Color.White);
            diagram1.Bounds = new RectangleF(0, 0, 1000, 1000);
            diagram1.LaneGrid.ColumnHeadersHeights = new float[] { 0 };
            diagramView1.ScrollTo(0, 0);
            _startZoomFactor = diagramView1.ZoomFactor;
            _grid = diagram1.LaneGrid;
            HeaderCollection columns = _grid.ColumnHeaders;
            _grid.MinHeaderSize = 20;
            _grid.HookHeaders = false;
            _grid.HeadersOnTop = true;
            _grid.AlignCells = false;
            _grid.AllowResizeHeaders = true;
            
            _whiteSmokePen = new MindFusion.Drawing.Pen(Color.WhiteSmoke, 0.01f);
            _laneStyle = new MindFusion.Diagramming.Lanes.Style
            {
                BottomBorderPen = _whiteSmokePen,
                LeftBorderPen = new MindFusion.Drawing.Pen(Color.Transparent),
                RightBorderPen = _whiteSmokePen,
                TopBorderPen = _whiteSmokePen
            };
            
            columns.Add(new Header("Client") { Width = 100f, Height = 120f, Style = _laneStyle });
            columns.Add(new Header("Server") { Width = 100f, Height = 120f, Style = _laneStyle });
            columns.Add(new Header("Database") { Width = 100f, Height = 120f, Style = _laneStyle });
            _grid.RowHeaders.Add(new Header("") { Height = 300f, Width = 0.1f, Style = _laneStyle });
            _grid[0, 0].Style = _laneStyle;
            _grid[1, 0].Style = _laneStyle;
            _grid[2, 0].Style = _laneStyle;
            _grid.AlignCells = true;
            diagram1.EnableLanes = true;
            diagram1.AlignToGrid = true;
            diagram1.LinkTextStyle = LinkTextStyle.OverLongestSegment;
            diagram1.RoundedLinks = true;
            diagram1.LinkEndsMovable = false;
        }

        public void AddNodes(CallStackProperty callStackProperty, bool clearAllRecentNodes)
        {
            if(CheckIfCallStackAllreadyExistsOnDiagram(callStackProperty))return;

            if (clearAllRecentNodes)
            {
                DeleteAllExistingNodes();
            }

            var activityID = callStackProperty.ActivityID;
            var correlationID = callStackProperty.CorrelationID;
            ControlNode titleNode = null, clientStart = null, serverStart = null, databaseStart = null, serverEnd = null, clientEnd = null;
            titleNode =
                CreateNode(
                    new UltraLabel
                    {
                        Text = string.Format("Activity ID:{1}{0}", activityID, Environment.NewLine),
                        AutoSize = true,
                        Font = new Font("Segoe UI", 8, FontStyle.Bold)
                    }, 0);
            if (callStackProperty.hasClientOutElement)
            {
                clientStart =
                    CreateNode(
                        new NodeCtrl("Client", "start request", ETyp.ServiceBeforeSendRequest, activityID, correlationID),
                        0);
            }
            if (callStackProperty.hasServerOutElement)
            {
                serverStart = CreateNode(new NodeCtrl("Server", "start DB interaction", ETyp.ServiceAfterReceiveRequest,
                    activityID, correlationID), 1,-20);
            }
            if (callStackProperty.hasDatabaseElement)
            {
                databaseStart =
                    CreateNode(
                        new NodeCtrl("Database", string.Format("Duration: {0}ms", callStackProperty.DatabaseQueryTime),
                            ETyp.SQLLoad,
                            activityID, correlationID), 2);
            }
            if (callStackProperty.hasServerInElement)
            {
                serverEnd = CreateNode(new NodeCtrl("Server", "send result", ETyp.ServiceBeforeSendReply,
                    activityID, correlationID),1);
            }
            if (callStackProperty.hasClientInElement)
            {
                clientEnd =
                    CreateNode(
                        new NodeCtrl("Client", "received result", ETyp.ServiceAfterReceiveReply, activityID,
                            correlationID), 0,-20);
            }

            if (clientStart != null && serverStart != null)
            {
                ApplyDefaultStyle(diagram1.Factory.CreateDiagramLink(clientStart, serverStart), string.Format("{0}ms", callStackProperty.TimeFromClientToServer));

            }
            if (serverStart != null && databaseStart != null)
            {
                ApplyDefaultStyle(diagram1.Factory.CreateDiagramLink(serverStart, databaseStart), string.Format("{0}ms", callStackProperty.TimeFromServerToDatabase));
            }
            if (databaseStart != null && serverEnd != null)
            {
                ApplyDefaultStyle(diagram1.Factory.CreateDiagramLink(databaseStart, serverEnd), string.Format("{0}ms", callStackProperty.TimeFromDatabaseToServer));
            }

            if (serverEnd != null && clientEnd != null)
            {
                ApplyDefaultStyle(diagram1.Factory.CreateDiagramLink(serverEnd, clientEnd), string.Format("{0}ms", callStackProperty.TimeFromServerToClient));
            }

            Rearrange();
            diagram1.RouteAllLinks();
            ResizeToFitItems();
            diagramView1.Diagram.ResizeToFitItems(1.0f);
        }

        private void DeleteAllExistingNodes()
        {
            diagram1.ClearAll();
            
            //var nodes =
            //    diagram1.Nodes.Select(node => node as ControlNode)
            //        .TakeWhile(controlNode => controlNode != null)
            //        .ToList();
            
            //foreach (var controlNode in nodes)
            //{
            //    diagram1.Nodes.Remove(controlNode);
            //}
            //nodes.Clear();
        }

        private bool CheckIfCallStackAllreadyExistsOnDiagram(CallStackProperty callStackProperty)
        {
            return
                diagram1.Nodes.Select(node => node as ControlNode)
                    .TakeWhile(controlNode => controlNode != null)
                    .Select(controlNode => controlNode.Control as NodeCtrl)
                    .Any(
                        detailControl =>
                            detailControl != null &&
                            (detailControl.ActivityID == callStackProperty.ActivityID &&
                             detailControl.CorrelationID == callStackProperty.CorrelationID));
        }

        private ControlNode CreateNode(Control control, object laneLine, float movePosition = 0)
        {
            var location = new PointF(0,0);
            var size = new SizeF(52f, 16f);
            var node = new ControlNode(diagram1)
            {
                Control = control,
                Bounds = new RectangleF(location.X, location.Y, size.Width, size.Height),
                ControlMouseAction = ControlMouseAction.IgnoreControl,
                Brush = new MindFusion.Drawing.SolidBrush(Color.Black),
                ShadowBrush = new MindFusion.Drawing.SolidBrush(Color.WhiteSmoke),
                ForceControlRedraw = true
            };
            diagram1.Nodes.Add(node);
            node.LayoutTraits.Add(MindFusion.Layout.SwimlaneLayoutTraits.Lane, laneLine);
            node.Move(0, movePosition);
            node.Locked = true;
            return node;
        }

        private void ApplyDefaultStyle(DiagramLink link, string duration)
        {
            link.RetainForm = true;
            link.DrawCrossings = true;
            link.Pen = new MindFusion.Drawing.Pen(Color.Black, 0.2f)
            {
                DashStyle = System.Drawing.Drawing2D.DashStyle.Solid
            };
            link.HeadPen = new MindFusion.Drawing.Pen(Color.Black, 0.2f);
            link.HeadShapeSize = 2;
            link.Brush = new MindFusion.Drawing.SolidBrush(Color.Black);
            link.Font = new Font("Segoe UI", 12, FontStyle.Bold);
            link.TextBrush = new MindFusion.Drawing.SolidBrush(Color.FromArgb(255, 222, 141, 0));
            link.TextPadding = new Thickness(15f, 0, -15f, 0);
            link.ShadowBrush = new MindFusion.Drawing.SolidBrush(Color.WhiteSmoke);
            link.TextAlignment = StringAlignment.Near;
            link.ZBottom(false);
            link.ZTop(true);
            link.Text = duration;
            link.Locked = true;
        }

        public void ZoomIn()
        {
            diagramView1.ZoomIn();
        }

        public void ZoomOut()
        {
            if(_startZoomFactor < diagramView1.ZoomFactor){diagramView1.ZoomOut();}
        }

        private void ResizeToFitItems()
        {
            var content = diagramView1.Diagram.GetContentBounds(false, true);
            content.Location = new PointF(0, 20);
            diagramView1.Diagram.Bounds = content;
        }

        private void Rearrange()
        {
            _layout = new SwimlaneLayout
            {
                Anchoring = Anchoring.Ignore,
                CompactNodes = false,
                Direction = Direction.Straight,
                CollapseEmptyLanes = false,
                KeepGroupLayout = false,
                KeepLaneSizes = true,
                LaneDistance = 20,
                NodeDistance = 0,
                Orientation = MindFusion.Diagramming.Layout.Orientation.Vertical,
                Margins = new SizeF(
                    (int) diagram1.LaneGrid.GetRowHeaderBounds().Width + diagram1.Bounds.X,
                    (int) diagram1.LaneGrid.GetColumnHeaderBounds().Height + diagram1.Bounds.Y)
            };
            _layout.Arrange(diagram1);
        }
    }
}

  

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


MindFusion support

Posts: 13230
Joined: Jul 20th, 2005
Re: strange behaviour in swimlane
Reply #1 - Dec 2nd, 2014 at 2:34pm
Print Post  
Hi,

Apparently SwimlaneLayout.Arrange resizes the grid to match largest used lane index in nodes, so after second arrangement the database column disappears, and is added again with default style the third time.

I suppose you could refactor the code to add columns in CreateNode when you detect there's no lane for specified laneLine index, or otherwise add a temporary node to last column to make SwimlaneLayout keep it.

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


I Love MindFusion!

Posts: 17
Joined: Nov 9th, 2012
Re: strange behaviour in swimlane
Reply #2 - Dec 3rd, 2014 at 3:12pm
Print Post  
Stoyo wrote on Dec 2nd, 2014 at 2:34pm:
Hi,

Apparently SwimlaneLayout.Arrange resizes the grid to match largest used lane index in nodes, so after second arrangement the database column disappears, and is added again with default style the third time.

I suppose you could refactor the code to add columns in CreateNode when you detect there's no lane for specified laneLine index, or otherwise add a temporary node to last column to make SwimlaneLayout keep it.

I hope that helps,
Stoyan




This is solved my problem, thank you very match.
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint