Adding text field support to our tree view.
Trying to fix our messy text alignment issue causing loop problems.
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 //