Adding text field support to our tree view.
authorsl
Sun, 17 Aug 2014 22:30:30 +0200
changeset 3459bfa4ebcbbb
parent 33 1363bda20171
child 35 f3893924a6eb
Adding text field support to our tree view.
Trying to fix our messy text alignment issue causing loop problems.
Server/MainForm.Designer.cs
Server/MainForm.cs
Server/MarqueeLabel.cs
Server/Servers.cs
     1.1 --- a/Server/MainForm.Designer.cs	Sat Aug 16 11:15:42 2014 +0200
     1.2 +++ b/Server/MainForm.Designer.cs	Sun Aug 17 22:30:30 2014 +0200
     1.3 @@ -396,6 +396,9 @@
     1.4              // 
     1.5              // treeViewClients
     1.6              // 
     1.7 +            this.treeViewClients.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
     1.8 +            | System.Windows.Forms.AnchorStyles.Left) 
     1.9 +            | System.Windows.Forms.AnchorStyles.Right)));
    1.10              this.treeViewClients.Location = new System.Drawing.Point(6, 6);
    1.11              this.treeViewClients.Name = "treeViewClients";
    1.12              this.treeViewClients.Size = new System.Drawing.Size(439, 357);
     2.1 --- a/Server/MainForm.cs	Sat Aug 16 11:15:42 2014 +0200
     2.2 +++ b/Server/MainForm.cs	Sun Aug 17 22:30:30 2014 +0200
     2.3 @@ -20,27 +20,6 @@
     2.4  
     2.5  namespace SharpDisplayManager
     2.6  {
     2.7 -    /// <summary>
     2.8 -    /// A UI thread copy of a client relevant data.
     2.9 -    /// Keeping this copy in the UI thread helps us deal with threading issues.
    2.10 -    /// </summary>
    2.11 -    public class ClientData
    2.12 -    {
    2.13 -        public ClientData(string aSessionId, IDisplayServiceCallback aCallback)
    2.14 -        {
    2.15 -            SessionId = aSessionId;
    2.16 -            Name = "";
    2.17 -            Texts = new List<string>();
    2.18 -            Callback = aCallback;
    2.19 -        }
    2.20 -
    2.21 -        public string SessionId { get; set;}
    2.22 -        public string Name { get; set;}
    2.23 -        public List<string> Texts { get; set;}
    2.24 -        public IDisplayServiceCallback Callback { get; set;}
    2.25 -    }
    2.26 -
    2.27 -
    2.28      public partial class MainForm : Form
    2.29      {
    2.30          DateTime LastTickTime;
    2.31 @@ -478,8 +457,8 @@
    2.32          //Delegates are used for our thread safe method 
    2.33          public delegate void AddClientDelegate(string aSessionId, IDisplayServiceCallback aCallback);
    2.34          public delegate void RemoveClientDelegate(string aSessionId);
    2.35 -        public delegate void SetTextDelegate(int aLineIndex, string aText);
    2.36 -        public delegate void SetTextsDelegate(System.Collections.Generic.IList<string> aTexts);
    2.37 +        public delegate void SetTextDelegate(string SessionId, int aLineIndex, string aText);
    2.38 +        public delegate void SetTextsDelegate(string SessionId, System.Collections.Generic.IList<string> aTexts);
    2.39          public delegate void SetClientNameDelegate(string aSessionId, string aName);
    2.40  
    2.41         
    2.42 @@ -545,25 +524,39 @@
    2.43          /// </summary>
    2.44          /// <param name="aLineIndex"></param>
    2.45          /// <param name="aText"></param>
    2.46 -        public void SetTextThreadSafe(int aLineIndex, string aText)
    2.47 +        public void SetTextThreadSafe(string aSessionId, int aLineIndex, string aText)
    2.48          {
    2.49              if (this.InvokeRequired)
    2.50              {
    2.51                  //Not in the proper thread, invoke ourselves
    2.52                  SetTextDelegate d = new SetTextDelegate(SetTextThreadSafe);
    2.53 -                this.Invoke(d, new object[] { aLineIndex, aText });
    2.54 +                this.Invoke(d, new object[] { aSessionId, aLineIndex, aText });
    2.55              }
    2.56              else
    2.57              {
    2.58 -                //We are in the proper thread
    2.59 -                //Only support two lines for now
    2.60 -                if (aLineIndex == 0)
    2.61 +                ClientData client = iClients[aSessionId];
    2.62 +                if (client != null)
    2.63                  {
    2.64 -                    marqueeLabelTop.Text = aText;
    2.65 -                }
    2.66 -                else if (aLineIndex == 1)
    2.67 -                {
    2.68 -                    marqueeLabelBottom.Text = aText;
    2.69 +                    //Make sure all our texts are in place
    2.70 +                    while (client.Texts.Count < (aLineIndex + 1))
    2.71 +                    {
    2.72 +                        client.Texts.Add("");
    2.73 +                    }
    2.74 +                    client.Texts[aLineIndex] = aText;
    2.75 +
    2.76 +                    //We are in the proper thread
    2.77 +                    //Only support two lines for now
    2.78 +                    if (aLineIndex == 0)
    2.79 +                    {
    2.80 +                        marqueeLabelTop.Text = aText;                        
    2.81 +                    }
    2.82 +                    else if (aLineIndex == 1)
    2.83 +                    {
    2.84 +                        marqueeLabelBottom.Text = aText;
    2.85 +                    }
    2.86 +
    2.87 +
    2.88 +                    UpdateClientTreeViewNode(client);
    2.89                  }
    2.90              }
    2.91          }
    2.92 @@ -572,28 +565,49 @@
    2.93          /// 
    2.94          /// </summary>
    2.95          /// <param name="aTexts"></param>
    2.96 -        public void SetTextsThreadSafe(System.Collections.Generic.IList<string> aTexts)
    2.97 +        public void SetTextsThreadSafe(string aSessionId, System.Collections.Generic.IList<string> aTexts)
    2.98          {
    2.99              if (this.InvokeRequired)
   2.100              {
   2.101                  //Not in the proper thread, invoke ourselves
   2.102                  SetTextsDelegate d = new SetTextsDelegate(SetTextsThreadSafe);
   2.103 -                this.Invoke(d, new object[] { aTexts });
   2.104 +                this.Invoke(d, new object[] { aSessionId, aTexts });
   2.105              }
   2.106              else
   2.107              {
   2.108 -                //We are in the proper thread
   2.109 -                //Only support two lines for now
   2.110 -                for (int i = 0; i < aTexts.Count; i++)
   2.111 +                ClientData client = iClients[aSessionId];
   2.112 +                if (client != null)
   2.113                  {
   2.114 -                    if (i == 0)
   2.115 +                    //Populate our client with the given texts
   2.116 +                    int j = 0;
   2.117 +                    foreach (string text in aTexts)
   2.118                      {
   2.119 -                        marqueeLabelTop.Text = aTexts[i];
   2.120 +                        if (client.Texts.Count < (j + 1))
   2.121 +                        {
   2.122 +                            client.Texts.Add(text);
   2.123 +                        }
   2.124 +                        else
   2.125 +                        {
   2.126 +                            client.Texts[j]=text;
   2.127 +                        }
   2.128 +                        j++;
   2.129                      }
   2.130 -                    else if (i == 1)
   2.131 +                    //We are in the proper thread
   2.132 +                    //Only support two lines for now
   2.133 +                    for (int i = 0; i < aTexts.Count; i++)
   2.134                      {
   2.135 -                        marqueeLabelBottom.Text = aTexts[i];
   2.136 +                        if (i == 0)
   2.137 +                        {
   2.138 +                            marqueeLabelTop.Text = aTexts[i];
   2.139 +                        }
   2.140 +                        else if (i == 1)
   2.141 +                        {
   2.142 +                            marqueeLabelBottom.Text = aTexts[i];
   2.143 +                        }
   2.144                      }
   2.145 +
   2.146 +
   2.147 +                    UpdateClientTreeViewNode(client);
   2.148                  }
   2.149              }
   2.150          }
   2.151 @@ -683,8 +697,30 @@
   2.152                          textsRoot.Nodes.Add(new TreeNode(text));
   2.153                      }
   2.154                  }
   2.155 +
   2.156 +                node.ExpandAll();
   2.157              }
   2.158          }
   2.159  
   2.160      }
   2.161 +
   2.162 +    /// <summary>
   2.163 +    /// A UI thread copy of a client relevant data.
   2.164 +    /// Keeping this copy in the UI thread helps us deal with threading issues.
   2.165 +    /// </summary>
   2.166 +    public class ClientData
   2.167 +    {
   2.168 +        public ClientData(string aSessionId, IDisplayServiceCallback aCallback)
   2.169 +        {
   2.170 +            SessionId = aSessionId;
   2.171 +            Name = "";
   2.172 +            Texts = new List<string>();
   2.173 +            Callback = aCallback;
   2.174 +        }
   2.175 +
   2.176 +        public string SessionId { get; set; }
   2.177 +        public string Name { get; set; }
   2.178 +        public List<string> Texts { get; set; }
   2.179 +        public IDisplayServiceCallback Callback { get; set; }
   2.180 +    }
   2.181  }
     3.1 --- a/Server/MarqueeLabel.cs	Sat Aug 16 11:15:42 2014 +0200
     3.2 +++ b/Server/MarqueeLabel.cs	Sun Aug 17 22:30:30 2014 +0200
     3.3 @@ -19,6 +19,8 @@
     3.4          private SolidBrush iBrush;
     3.5          private SizeF iTextSize;
     3.6          private SizeF iSeparatorSize;
     3.7 +        private SizeF iScrollSize;
     3.8 +        //private ContentAlignment iRequestedContentAlignment;
     3.9  
    3.10          [Category("Appearance")]
    3.11          [Description("Separator in our scrolling loop.")]
    3.12 @@ -82,6 +84,7 @@
    3.13              PixelsLeft = 0;
    3.14              CurrentPosition = 0;
    3.15              iBrush = new SolidBrush(ForeColor);
    3.16 +            //iRequestedContentAlignment = TextAlign;
    3.17          }
    3.18  
    3.19          public void UpdateAnimation(DateTime aLastTickTime, DateTime aNewTickTime)
    3.20 @@ -92,10 +95,18 @@
    3.21                  return;
    3.22              }
    3.23  
    3.24 +            /*
    3.25              while (CurrentPosition > (iTextSize.Width + iSeparatorSize.Width))
    3.26              {
    3.27                  CurrentPosition -= ((int)(iTextSize.Width + iSeparatorSize.Width));
    3.28              }
    3.29 +             */
    3.30 +
    3.31 +            while (CurrentPosition > iScrollSize.Width)
    3.32 +            {
    3.33 +                CurrentPosition -= (int)iScrollSize.Width;
    3.34 +            }
    3.35 +
    3.36  
    3.37              PixelsLeft += aNewTickTime.Subtract(aLastTickTime).TotalSeconds * PixelsPerSecond;
    3.38  
    3.39 @@ -148,36 +159,36 @@
    3.40              switch (ca)
    3.41              {
    3.42                  case ContentAlignment.TopCenter:
    3.43 -                    format.Alignment = StringAlignment.Near;
    3.44 -                    format.LineAlignment = StringAlignment.Center;
    3.45 +                    format.Alignment = StringAlignment.Center;
    3.46 +                    format.LineAlignment = StringAlignment.Near;
    3.47                      break;
    3.48                  case ContentAlignment.TopLeft:
    3.49                      format.Alignment = StringAlignment.Near;
    3.50                      format.LineAlignment = StringAlignment.Near;
    3.51                      break;
    3.52                  case ContentAlignment.TopRight:
    3.53 -                    format.Alignment = StringAlignment.Near;
    3.54 -                    format.LineAlignment = StringAlignment.Far;
    3.55 +                    format.Alignment = StringAlignment.Far;
    3.56 +                    format.LineAlignment = StringAlignment.Near;
    3.57                      break;
    3.58                  case ContentAlignment.MiddleCenter:
    3.59                      format.Alignment = StringAlignment.Center;
    3.60                      format.LineAlignment = StringAlignment.Center;
    3.61                      break;
    3.62                  case ContentAlignment.MiddleLeft:
    3.63 -                    format.Alignment = StringAlignment.Center;
    3.64 -                    format.LineAlignment = StringAlignment.Near;
    3.65 +                    format.Alignment = StringAlignment.Near;
    3.66 +                    format.LineAlignment = StringAlignment.Center;
    3.67                      break;
    3.68                  case ContentAlignment.MiddleRight:
    3.69 +                    format.Alignment = StringAlignment.Far;
    3.70 +                    format.LineAlignment = StringAlignment.Center;
    3.71 +                    break;
    3.72 +                case ContentAlignment.BottomCenter:
    3.73                      format.Alignment = StringAlignment.Center;
    3.74                      format.LineAlignment = StringAlignment.Far;
    3.75                      break;
    3.76 -                case ContentAlignment.BottomCenter:
    3.77 -                    format.Alignment = StringAlignment.Far;
    3.78 -                    format.LineAlignment = StringAlignment.Center;
    3.79 -                    break;
    3.80                  case ContentAlignment.BottomLeft:
    3.81 -                    format.Alignment = StringAlignment.Far;
    3.82 -                    format.LineAlignment = StringAlignment.Near;
    3.83 +                    format.Alignment = StringAlignment.Near;
    3.84 +                    format.LineAlignment = StringAlignment.Far;
    3.85                      break;
    3.86                  case ContentAlignment.BottomRight:
    3.87                      format.Alignment = StringAlignment.Far;
    3.88 @@ -208,6 +219,8 @@
    3.89              CurrentPosition = 0;
    3.90              LastTickTime = DateTime.Now;
    3.91              PixelsLeft = 0;
    3.92 +            //Reset text align
    3.93 +            //TextAlign = iRequestedContentAlignment;
    3.94  
    3.95              //For all string measurements and drawing issues refer to the following article:
    3.96              // http://stackoverflow.com/questions/1203087/why-is-graphics-measurestring-returning-a-higher-than-expected-number
    3.97 @@ -217,11 +230,23 @@
    3.98              iStringFormat = GetStringFormatFromContentAllignment(TextAlign);
    3.99              iTextSize = g.MeasureString(Text, Font, Int32.MaxValue, iStringFormat);
   3.100              iSeparatorSize = g.MeasureString(Separator, Font, Int32.MaxValue, iStringFormat);
   3.101 +            //Scroll width is the width of our text and our separator without taking kerning into account since
   3.102 +            //both text and separator are drawn independently from each other.
   3.103 +            iScrollSize.Width = iSeparatorSize.Width + iTextSize.Width;
   3.104 +            iScrollSize.Height = Math.Max(iSeparatorSize.Height, iTextSize.Height); //Not relevant for now
   3.105 +            //We don't want scroll with to take kerning into account so we don't use the following
   3.106 +            //iScrollSize = g.MeasureString(Text + Separator, Font, Int32.MaxValue, iStringFormat);
   3.107  
   3.108              if (NeedToScroll())
   3.109              {
   3.110                  //Always align left when scrolling
   3.111 -                iStringFormat.Alignment = StringAlignment.Near;
   3.112 +                //Somehow draw string still takes into our control alignment so we need to set it too
   3.113 +                //ContentAlignment original = TextAlign;
   3.114 +                TextAlign = ContentAlignment.MiddleLeft;
   3.115 +                //Make sure our original text alignment remain the same even though we override it when scrolling
   3.116 +                //iRequestedContentAlignment = original; 
   3.117 +                //iStringFormat will get updated in OnTextAlignChanged
   3.118 +                //iStringFormat.Alignment = StringAlignment.Near;
   3.119              }
   3.120          }
   3.121  
   3.122 @@ -242,7 +267,7 @@
   3.123          protected override void OnTextAlignChanged(EventArgs e)
   3.124          {
   3.125              iStringFormat = GetStringFormatFromContentAllignment(TextAlign);
   3.126 -
   3.127 +            //iRequestedContentAlignment = TextAlign;
   3.128              base.OnTextAlignChanged(e);
   3.129  
   3.130          }
   3.131 @@ -253,18 +278,20 @@
   3.132              e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
   3.133              if (NeedToScroll())
   3.134              {
   3.135 -                //Draw it all in a single call
   3.136 +                //Draw it all in a single call would take kerning into account
   3.137 +                //e.Graphics.TranslateTransform(-(float)CurrentPosition, 0);
   3.138 +                //e.Graphics.DrawString(Text + Separator + Text, Font, iBrush, ClientRectangle, iStringFormat);
   3.139 +
   3.140 +                //Doing separate draw operation allows us not to take kerning into account between separator and string
   3.141 +                //Draw the first one
   3.142                  e.Graphics.TranslateTransform(-(float)CurrentPosition, 0);
   3.143 -                e.Graphics.DrawString(Text + Separator + Text, Font, iBrush, ClientRectangle, iStringFormat);
   3.144 -                //Draw the first one
   3.145 -                //e.Graphics.TranslateTransform(-(float)CurrentPosition, 0);
   3.146 -                //e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
   3.147 +                e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
   3.148                  //Draw separator
   3.149 -                //e.Graphics.TranslateTransform(iTextSize.Width, 0);
   3.150 -                //e.Graphics.DrawString(Separator, Font, iBrush, ClientRectangle, iStringFormat);
   3.151 +                e.Graphics.TranslateTransform(iTextSize.Width, 0);
   3.152 +                e.Graphics.DrawString(Separator, Font, iBrush, ClientRectangle, iStringFormat);
   3.153                  //Draw the last one
   3.154 -                //e.Graphics.TranslateTransform(iSeparatorSize.Width, 0);
   3.155 -                //e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
   3.156 +                e.Graphics.TranslateTransform(iSeparatorSize.Width, 0);
   3.157 +                e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
   3.158              }
   3.159              else
   3.160              {
     4.1 --- a/Server/Servers.cs	Sat Aug 16 11:15:42 2014 +0200
     4.2 +++ b/Server/Servers.cs	Sun Aug 17 22:30:30 2014 +0200
     4.3 @@ -42,13 +42,13 @@
     4.4          //From IDisplayService
     4.5          public void SetTexts(System.Collections.Generic.IList<string> aTexts)
     4.6          {
     4.7 -            Program.iMainForm.SetTextsThreadSafe(aTexts);
     4.8 +            Program.iMainForm.SetTextsThreadSafe(SessionId, aTexts);
     4.9          }
    4.10  
    4.11          //
    4.12          public void SetText(int aLineIndex, string aText)
    4.13          {
    4.14 -            Program.iMainForm.SetTextThreadSafe(aLineIndex, aText);
    4.15 +            Program.iMainForm.SetTextThreadSafe(SessionId, aLineIndex, aText);
    4.16          }
    4.17  
    4.18          //