Ground work for display layout support.
authorStephaneLenclud
Sun, 15 Jan 2017 18:49:06 +0100
changeset 27910f0de70b69b
parent 278 2481c46d1f93
child 280 f90d1e101932
Ground work for display layout support.
Clients/Idle/SharpDisplayClientIdle.csproj
Clients/Idle/packages.config
Clients/Message/SharpDisplayClientMessage.csproj
Clients/Message/packages.config
Clients/Test/SharpDisplayClientTest.csproj
Clients/Test/packages.config
Server/ClientData.cs
Server/FormMain.Designer.cs
Server/FormMain.cs
Server/Session.cs
Server/SharpDisplayManager.csproj
Server/packages.config
     1.1 --- a/Clients/Idle/SharpDisplayClientIdle.csproj	Sun Jan 08 12:19:35 2017 +0100
     1.2 +++ b/Clients/Idle/SharpDisplayClientIdle.csproj	Sun Jan 15 18:49:06 2017 +0100
     1.3 @@ -66,8 +66,8 @@
     1.4      <Prefer32Bit>true</Prefer32Bit>
     1.5    </PropertyGroup>
     1.6    <ItemGroup>
     1.7 -    <Reference Include="SharpLibDisplay, Version=0.2.8.30538, Culture=neutral, processorArchitecture=MSIL">
     1.8 -      <HintPath>..\..\packages\SharpLibDisplay.0.2.8\lib\net40\SharpLibDisplay.dll</HintPath>
     1.9 +    <Reference Include="SharpLibDisplay, Version=0.2.8.17764, Culture=neutral, processorArchitecture=MSIL">
    1.10 +      <HintPath>..\..\packages\SharpLibDisplay.0.3.3\lib\net40\SharpLibDisplay.dll</HintPath>
    1.11        <Private>True</Private>
    1.12      </Reference>
    1.13      <Reference Include="System" />
     2.1 --- a/Clients/Idle/packages.config	Sun Jan 08 12:19:35 2017 +0100
     2.2 +++ b/Clients/Idle/packages.config	Sun Jan 15 18:49:06 2017 +0100
     2.3 @@ -1,4 +1,4 @@
     2.4  <?xml version="1.0" encoding="utf-8"?>
     2.5  <packages>
     2.6 -  <package id="SharpLibDisplay" version="0.2.8" targetFramework="net46" />
     2.7 +  <package id="SharpLibDisplay" version="0.3.3" targetFramework="net46" />
     2.8  </packages>
     2.9 \ No newline at end of file
     3.1 --- a/Clients/Message/SharpDisplayClientMessage.csproj	Sun Jan 08 12:19:35 2017 +0100
     3.2 +++ b/Clients/Message/SharpDisplayClientMessage.csproj	Sun Jan 15 18:49:06 2017 +0100
     3.3 @@ -65,8 +65,8 @@
     3.4      <Prefer32Bit>true</Prefer32Bit>
     3.5    </PropertyGroup>
     3.6    <ItemGroup>
     3.7 -    <Reference Include="SharpLibDisplay, Version=0.2.8.30538, Culture=neutral, processorArchitecture=MSIL">
     3.8 -      <HintPath>..\..\packages\SharpLibDisplay.0.2.8\lib\net40\SharpLibDisplay.dll</HintPath>
     3.9 +    <Reference Include="SharpLibDisplay, Version=0.2.8.17764, Culture=neutral, processorArchitecture=MSIL">
    3.10 +      <HintPath>..\..\packages\SharpLibDisplay.0.3.3\lib\net40\SharpLibDisplay.dll</HintPath>
    3.11        <Private>True</Private>
    3.12      </Reference>
    3.13      <Reference Include="System" />
     4.1 --- a/Clients/Message/packages.config	Sun Jan 08 12:19:35 2017 +0100
     4.2 +++ b/Clients/Message/packages.config	Sun Jan 15 18:49:06 2017 +0100
     4.3 @@ -1,4 +1,4 @@
     4.4  <?xml version="1.0" encoding="utf-8"?>
     4.5  <packages>
     4.6 -  <package id="SharpLibDisplay" version="0.2.8" targetFramework="net452" />
     4.7 +  <package id="SharpLibDisplay" version="0.3.3" targetFramework="net452" />
     4.8  </packages>
     4.9 \ No newline at end of file
     5.1 --- a/Clients/Test/SharpDisplayClientTest.csproj	Sun Jan 08 12:19:35 2017 +0100
     5.2 +++ b/Clients/Test/SharpDisplayClientTest.csproj	Sun Jan 15 18:49:06 2017 +0100
     5.3 @@ -84,8 +84,8 @@
     5.4      <NoWin32Manifest>true</NoWin32Manifest>
     5.5    </PropertyGroup>
     5.6    <ItemGroup>
     5.7 -    <Reference Include="SharpLibDisplay, Version=0.2.8.30538, Culture=neutral, processorArchitecture=MSIL">
     5.8 -      <HintPath>..\..\packages\SharpLibDisplay.0.2.8\lib\net40\SharpLibDisplay.dll</HintPath>
     5.9 +    <Reference Include="SharpLibDisplay, Version=0.2.8.17764, Culture=neutral, processorArchitecture=MSIL">
    5.10 +      <HintPath>..\..\packages\SharpLibDisplay.0.3.3\lib\net40\SharpLibDisplay.dll</HintPath>
    5.11        <Private>True</Private>
    5.12      </Reference>
    5.13      <Reference Include="System" />
     6.1 --- a/Clients/Test/packages.config	Sun Jan 08 12:19:35 2017 +0100
     6.2 +++ b/Clients/Test/packages.config	Sun Jan 15 18:49:06 2017 +0100
     6.3 @@ -1,4 +1,4 @@
     6.4  <?xml version="1.0" encoding="utf-8"?>
     6.5  <packages>
     6.6 -  <package id="SharpLibDisplay" version="0.2.8" targetFramework="net46" />
     6.7 +  <package id="SharpLibDisplay" version="0.3.3" targetFramework="net46" />
     6.8  </packages>
     6.9 \ No newline at end of file
     7.1 --- a/Server/ClientData.cs	Sun Jan 08 12:19:35 2017 +0100
     7.2 +++ b/Server/ClientData.cs	Sun Jan 15 18:49:06 2017 +0100
     7.3 @@ -19,62 +19,24 @@
     7.4              SessionId = aSessionId;
     7.5              Name = "";
     7.6              Priority = Priorities.Default;
     7.7 -            Fields = new List<DataField>();
     7.8 -            Layout = new TableLayout(1, 2); //Default to one column and two rows
     7.9              Callback = aCallback;
    7.10 -            HasNewLayout = true;            
    7.11 +            HasNewLayout = true;
    7.12 +            View = new View();       
    7.13          }
    7.14  
    7.15          public string SessionId { get; set; }
    7.16          public string Name { get; set; }
    7.17          public uint Priority { get; set; }
    7.18 -        public List<DataField> Fields { get; set; }
    7.19 -        public TableLayout Layout { get; set; }
    7.20 +        public Target Target { get; set; }
    7.21 +        public View View { get; set; }
    7.22          public ICallback Callback { get; set; }
    7.23 +        
    7.24  
    7.25          public bool HasNewLayout { get; set; }
    7.26  
    7.27          //Client management
    7.28          public DateTime LastSwitchTime { get; set; }
    7.29  
    7.30 -        /// <summary>
    7.31 -        /// Look up the corresponding field in our field collection.
    7.32 -        /// </summary>
    7.33 -        /// <param name="aField"></param>
    7.34 -        /// <returns></returns>
    7.35 -        public DataField FindSameFieldAs(DataField aField)
    7.36 -        {
    7.37 -            foreach (DataField field in Fields)
    7.38 -            {
    7.39 -                if (field.IsSameAs(aField))
    7.40 -                {
    7.41 -                    return field;
    7.42 -                }                
    7.43 -            }
    7.44 -
    7.45 -            return null;
    7.46 -        }
    7.47 -
    7.48 -
    7.49 -        /// <summary>
    7.50 -        /// Look up the corresponding field in our field collection.
    7.51 -        /// </summary>
    7.52 -        /// <param name="aField"></param>
    7.53 -        /// <returns></returns>
    7.54 -        public int FindSameFieldIndex(DataField aField)
    7.55 -        {
    7.56 -            int i = 0;
    7.57 -            foreach (DataField field in Fields)
    7.58 -            {
    7.59 -                if (field.IsSameAs(aField))
    7.60 -                {
    7.61 -                    return i;
    7.62 -                }
    7.63 -                i++;
    7.64 -            }
    7.65 -
    7.66 -            return -1;
    7.67 -        }
    7.68  
    7.69  
    7.70      }
     8.1 --- a/Server/FormMain.Designer.cs	Sun Jan 08 12:19:35 2017 +0100
     8.2 +++ b/Server/FormMain.Designer.cs	Sun Jan 15 18:49:06 2017 +0100
     8.3 @@ -39,8 +39,10 @@
     8.4          {
     8.5              this.components = new System.ComponentModel.Container();
     8.6              System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormMain));
     8.7 -            this.panelDisplay = new System.Windows.Forms.Panel();
     8.8 -            this.iTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
     8.9 +            this.iPanelDisplay = new System.Windows.Forms.Panel();
    8.10 +            this.panel1 = new System.Windows.Forms.Panel();
    8.11 +            this.iTableLayoutPanelDisplay = new System.Windows.Forms.TableLayoutPanel();
    8.12 +            this.iTableLayoutPanelCurrentClient = new System.Windows.Forms.TableLayoutPanel();
    8.13              this.marqueeLabelTop = new SharpDisplayManager.MarqueeLabel();
    8.14              this.marqueeLabelBottom = new SharpDisplayManager.MarqueeLabel();
    8.15              this.fontDialog = new System.Windows.Forms.FontDialog();
    8.16 @@ -133,8 +135,10 @@
    8.17              this.labelFontHeight = new System.Windows.Forms.Label();
    8.18              this.toolTip = new System.Windows.Forms.ToolTip(this.components);
    8.19              this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
    8.20 -            this.panelDisplay.SuspendLayout();
    8.21 -            this.iTableLayoutPanel.SuspendLayout();
    8.22 +            this.iPanelDisplay.SuspendLayout();
    8.23 +            this.panel1.SuspendLayout();
    8.24 +            this.iTableLayoutPanelDisplay.SuspendLayout();
    8.25 +            this.iTableLayoutPanelCurrentClient.SuspendLayout();
    8.26              this.statusStrip.SuspendLayout();
    8.27              this.tabPageClients.SuspendLayout();
    8.28              this.tabPageDisplay.SuspendLayout();
    8.29 @@ -153,36 +157,69 @@
    8.30              // 
    8.31              // panelDisplay
    8.32              // 
    8.33 -            this.panelDisplay.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
    8.34 -            this.panelDisplay.Controls.Add(this.iTableLayoutPanel);
    8.35 -            this.panelDisplay.Location = new System.Drawing.Point(173, 40);
    8.36 -            this.panelDisplay.Margin = new System.Windows.Forms.Padding(0);
    8.37 -            this.panelDisplay.Name = "panelDisplay";
    8.38 -            this.panelDisplay.Size = new System.Drawing.Size(258, 66);
    8.39 -            this.panelDisplay.TabIndex = 12;
    8.40 +            this.iPanelDisplay.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
    8.41 +            this.iPanelDisplay.Controls.Add(this.panel1);
    8.42 +            this.iPanelDisplay.Location = new System.Drawing.Point(173, 40);
    8.43 +            this.iPanelDisplay.Margin = new System.Windows.Forms.Padding(0);
    8.44 +            this.iPanelDisplay.Name = "panelDisplay";
    8.45 +            this.iPanelDisplay.Size = new System.Drawing.Size(258, 66);
    8.46 +            this.iPanelDisplay.TabIndex = 12;
    8.47              // 
    8.48 -            // iTableLayoutPanel
    8.49 +            // panel1
    8.50              // 
    8.51 -            this.iTableLayoutPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
    8.52 +            this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
    8.53 +            this.panel1.Controls.Add(this.iTableLayoutPanelDisplay);
    8.54 +            this.panel1.Location = new System.Drawing.Point(-1, -1);
    8.55 +            this.panel1.Margin = new System.Windows.Forms.Padding(0);
    8.56 +            this.panel1.Name = "panel1";
    8.57 +            this.panel1.Size = new System.Drawing.Size(258, 66);
    8.58 +            this.panel1.TabIndex = 22;
    8.59 +            // 
    8.60 +            // iTableLayoutPanelDisplay
    8.61 +            // 
    8.62 +            this.iTableLayoutPanelDisplay.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
    8.63              | System.Windows.Forms.AnchorStyles.Left) 
    8.64              | System.Windows.Forms.AnchorStyles.Right)));
    8.65 -            this.iTableLayoutPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
    8.66 -            this.iTableLayoutPanel.BackColor = System.Drawing.SystemColors.ControlLightLight;
    8.67 -            this.iTableLayoutPanel.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.Single;
    8.68 -            this.iTableLayoutPanel.ColumnCount = 1;
    8.69 -            this.iTableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
    8.70 -            this.iTableLayoutPanel.Controls.Add(this.marqueeLabelTop, 0, 0);
    8.71 -            this.iTableLayoutPanel.Controls.Add(this.marqueeLabelBottom, 0, 1);
    8.72 -            this.iTableLayoutPanel.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.FixedSize;
    8.73 -            this.iTableLayoutPanel.Location = new System.Drawing.Point(0, 0);
    8.74 -            this.iTableLayoutPanel.Margin = new System.Windows.Forms.Padding(0);
    8.75 -            this.iTableLayoutPanel.Name = "iTableLayoutPanel";
    8.76 -            this.iTableLayoutPanel.RowCount = 2;
    8.77 -            this.iTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
    8.78 -            this.iTableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
    8.79 -            this.iTableLayoutPanel.Size = new System.Drawing.Size(256, 64);
    8.80 -            this.iTableLayoutPanel.TabIndex = 5;
    8.81 -            this.iTableLayoutPanel.SizeChanged += new System.EventHandler(this.tableLayoutPanel_SizeChanged);
    8.82 +            this.iTableLayoutPanelDisplay.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
    8.83 +            this.iTableLayoutPanelDisplay.BackColor = System.Drawing.SystemColors.ControlLightLight;
    8.84 +            this.iTableLayoutPanelDisplay.ColumnCount = 2;
    8.85 +            this.iTableLayoutPanelDisplay.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 88.88889F));
    8.86 +            this.iTableLayoutPanelDisplay.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 11.11111F));
    8.87 +            this.iTableLayoutPanelDisplay.Controls.Add(this.iTableLayoutPanelCurrentClient, 0, 0);
    8.88 +            this.iTableLayoutPanelDisplay.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.FixedSize;
    8.89 +            this.iTableLayoutPanelDisplay.Location = new System.Drawing.Point(0, 0);
    8.90 +            this.iTableLayoutPanelDisplay.Margin = new System.Windows.Forms.Padding(0);
    8.91 +            this.iTableLayoutPanelDisplay.Name = "iTableLayoutPanelDisplay";
    8.92 +            this.iTableLayoutPanelDisplay.RowCount = 4;
    8.93 +            this.iTableLayoutPanelDisplay.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F));
    8.94 +            this.iTableLayoutPanelDisplay.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F));
    8.95 +            this.iTableLayoutPanelDisplay.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F));
    8.96 +            this.iTableLayoutPanelDisplay.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F));
    8.97 +            this.iTableLayoutPanelDisplay.Size = new System.Drawing.Size(256, 64);
    8.98 +            this.iTableLayoutPanelDisplay.TabIndex = 5;
    8.99 +            // 
   8.100 +            // iTableLayoutPanelCurrentClient
   8.101 +            // 
   8.102 +            this.iTableLayoutPanelCurrentClient.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
   8.103 +            | System.Windows.Forms.AnchorStyles.Left) 
   8.104 +            | System.Windows.Forms.AnchorStyles.Right)));
   8.105 +            this.iTableLayoutPanelCurrentClient.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
   8.106 +            this.iTableLayoutPanelCurrentClient.BackColor = System.Drawing.SystemColors.ControlLightLight;
   8.107 +            this.iTableLayoutPanelCurrentClient.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.Single;
   8.108 +            this.iTableLayoutPanelCurrentClient.ColumnCount = 1;
   8.109 +            this.iTableLayoutPanelCurrentClient.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
   8.110 +            this.iTableLayoutPanelCurrentClient.Controls.Add(this.marqueeLabelTop, 0, 0);
   8.111 +            this.iTableLayoutPanelCurrentClient.Controls.Add(this.marqueeLabelBottom, 0, 1);
   8.112 +            this.iTableLayoutPanelCurrentClient.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.FixedSize;
   8.113 +            this.iTableLayoutPanelCurrentClient.Location = new System.Drawing.Point(0, 0);
   8.114 +            this.iTableLayoutPanelCurrentClient.Margin = new System.Windows.Forms.Padding(0);
   8.115 +            this.iTableLayoutPanelCurrentClient.Name = "iTableLayoutPanelCurrentClient";
   8.116 +            this.iTableLayoutPanelCurrentClient.RowCount = 2;
   8.117 +            this.iTableLayoutPanelDisplay.SetRowSpan(this.iTableLayoutPanelCurrentClient, 4);
   8.118 +            this.iTableLayoutPanelCurrentClient.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
   8.119 +            this.iTableLayoutPanelCurrentClient.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
   8.120 +            this.iTableLayoutPanelCurrentClient.Size = new System.Drawing.Size(227, 64);
   8.121 +            this.iTableLayoutPanelCurrentClient.TabIndex = 6;
   8.122              // 
   8.123              // marqueeLabelTop
   8.124              // 
   8.125 @@ -198,7 +235,7 @@
   8.126              this.marqueeLabelTop.PixelsPerSecond = 64;
   8.127              this.marqueeLabelTop.ScaleToFit = true;
   8.128              this.marqueeLabelTop.Separator = "|";
   8.129 -            this.marqueeLabelTop.Size = new System.Drawing.Size(254, 30);
   8.130 +            this.marqueeLabelTop.Size = new System.Drawing.Size(225, 30);
   8.131              this.marqueeLabelTop.TabIndex = 2;
   8.132              this.marqueeLabelTop.Text = "ABCDEFGHIJKLMNOPQRST-0123456789";
   8.133              this.marqueeLabelTop.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
   8.134 @@ -217,7 +254,7 @@
   8.135              this.marqueeLabelBottom.PixelsPerSecond = 64;
   8.136              this.marqueeLabelBottom.ScaleToFit = true;
   8.137              this.marqueeLabelBottom.Separator = "|";
   8.138 -            this.marqueeLabelBottom.Size = new System.Drawing.Size(254, 31);
   8.139 +            this.marqueeLabelBottom.Size = new System.Drawing.Size(225, 31);
   8.140              this.marqueeLabelBottom.TabIndex = 3;
   8.141              this.marqueeLabelBottom.Text = "abcdefghijklmnopqrst-0123456789";
   8.142              this.marqueeLabelBottom.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
   8.143 @@ -1261,7 +1298,7 @@
   8.144              this.Controls.Add(this.labelWarning);
   8.145              this.Controls.Add(this.statusStrip);
   8.146              this.Controls.Add(this.tabControl);
   8.147 -            this.Controls.Add(this.panelDisplay);
   8.148 +            this.Controls.Add(this.iPanelDisplay);
   8.149              this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
   8.150              this.MinimumSize = new System.Drawing.Size(800, 600);
   8.151              this.Name = "FormMain";
   8.152 @@ -1270,9 +1307,11 @@
   8.153              this.Load += new System.EventHandler(this.MainForm_Load);
   8.154              this.SizeChanged += new System.EventHandler(this.MainForm_SizeChanged);
   8.155              this.Resize += new System.EventHandler(this.MainForm_Resize);
   8.156 -            this.panelDisplay.ResumeLayout(false);
   8.157 -            this.iTableLayoutPanel.ResumeLayout(false);
   8.158 -            this.iTableLayoutPanel.PerformLayout();
   8.159 +            this.iPanelDisplay.ResumeLayout(false);
   8.160 +            this.panel1.ResumeLayout(false);
   8.161 +            this.iTableLayoutPanelDisplay.ResumeLayout(false);
   8.162 +            this.iTableLayoutPanelCurrentClient.ResumeLayout(false);
   8.163 +            this.iTableLayoutPanelCurrentClient.PerformLayout();
   8.164              this.statusStrip.ResumeLayout(false);
   8.165              this.statusStrip.PerformLayout();
   8.166              this.tabPageClients.ResumeLayout(false);
   8.167 @@ -1310,10 +1349,7 @@
   8.168          private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelFps;
   8.169          private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelSpring;
   8.170          private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabelPower;
   8.171 -        private System.Windows.Forms.Panel panelDisplay;
   8.172 -        private System.Windows.Forms.TableLayoutPanel iTableLayoutPanel;
   8.173 -        private MarqueeLabel marqueeLabelTop;
   8.174 -        private MarqueeLabel marqueeLabelBottom;
   8.175 +        private System.Windows.Forms.Panel iPanelDisplay;
   8.176          private System.Windows.Forms.TabPage tabPageClients;
   8.177          private System.Windows.Forms.TreeView iTreeViewClients;
   8.178          private System.Windows.Forms.TabPage tabPageDisplay;
   8.179 @@ -1397,6 +1433,11 @@
   8.180          private System.Windows.Forms.TextBox iTextBoxHarmonyHubAddress;
   8.181          private System.Windows.Forms.CheckBox iCheckBoxHarmonyEnabled;
   8.182          private System.Windows.Forms.Button iButtonHarmonyConnect;
   8.183 +        private System.Windows.Forms.Panel panel1;
   8.184 +        private System.Windows.Forms.TableLayoutPanel iTableLayoutPanelDisplay;
   8.185 +        private System.Windows.Forms.TableLayoutPanel iTableLayoutPanelCurrentClient;
   8.186 +        private MarqueeLabel marqueeLabelTop;
   8.187 +        private MarqueeLabel marqueeLabelBottom;
   8.188      }
   8.189  }
   8.190  
     9.1 --- a/Server/FormMain.cs	Sun Jan 08 12:19:35 2017 +0100
     9.2 +++ b/Server/FormMain.cs	Sun Jan 15 18:49:06 2017 +0100
     9.3 @@ -69,16 +69,6 @@
     9.4  
     9.5      public delegate void RemoveClientDelegate(string aSessionId);
     9.6  
     9.7 -    public delegate void SetFieldDelegate(string SessionId, DataField aField);
     9.8 -
     9.9 -    public delegate void SetFieldsDelegate(string SessionId, System.Collections.Generic.IList<DataField> aFields);
    9.10 -
    9.11 -    public delegate void SetLayoutDelegate(string SessionId, TableLayout aLayout);
    9.12 -
    9.13 -    public delegate void SetClientNameDelegate(string aSessionId, string aName);
    9.14 -
    9.15 -    public delegate void SetClientPriorityDelegate(string aSessionId, uint aPriority);
    9.16 -
    9.17      public delegate void WndProcDelegate(ref Message aMessage);
    9.18  
    9.19      /// <summary>
    9.20 @@ -99,6 +89,13 @@
    9.21          // The name of the client which informations are currently displayed.
    9.22          public string iCurrentClientSessionId;
    9.23          ClientData iCurrentClientData;
    9.24 +        /// <summary>
    9.25 +        /// Define our display view including layout and fields.
    9.26 +        /// Display view should include one ClientField that will show on client View.
    9.27 +        /// </summary>
    9.28 +        SharpLib.Display.View iDisplayView;
    9.29 +
    9.30 +        bool iHasNewDisplayLayout;
    9.31          //
    9.32          public bool iClosing;
    9.33          //
    9.34 @@ -175,6 +172,10 @@
    9.35              iStartupManager = new StartupManager();
    9.36              iNotifyIcon = new SharpLib.Notification.Control();
    9.37              iRecordingNotification = new SharpLib.Notification.Control();
    9.38 +            iDisplayView = new SharpLib.Display.View();
    9.39 +            // Default to a single field showing our client
    9.40 +            iDisplayView.Layout = new TableLayout(1, 1);
    9.41 +            iDisplayView.Fields.Add(new ClientField());
    9.42  
    9.43              //Have our designer initialize its controls
    9.44              InitializeComponent();
    9.45 @@ -191,7 +192,7 @@
    9.46  
    9.47              //We have a bug when drawing minimized and reusing our bitmap
    9.48              //Though I could not reproduce it on Windows 10
    9.49 -            iBmp = new System.Drawing.Bitmap(iTableLayoutPanel.Width, iTableLayoutPanel.Height,
    9.50 +            iBmp = new System.Drawing.Bitmap(iTableLayoutPanelDisplay.Width, iTableLayoutPanelDisplay.Height,
    9.51                  PixelFormat.Format32bppArgb);
    9.52              iCreateBitmap = false;
    9.53  
    9.54 @@ -255,7 +256,7 @@
    9.55  
    9.56  #if !DEBUG
    9.57      //When not debugging we want the screen to be empty until a client takes over
    9.58 -			ClearLayout();
    9.59 +			ClearLayout(iTableLayoutPanelCurrentClient);
    9.60              iCurrentClientData = null;
    9.61  #else
    9.62              //When developing we want at least one client for testing
    9.63 @@ -344,7 +345,7 @@
    9.64              //panelDisplay needs an extra 2 pixels for borders on each sides
    9.65              //tableLayoutPanel will eventually be the exact size of our display
    9.66              Size size = new Size(iDisplay.WidthInPixels() + 2, iDisplay.HeightInPixels() + 2);
    9.67 -            panelDisplay.Size = size;
    9.68 +            iPanelDisplay.Size = size;
    9.69  
    9.70              //Our display was just opened, update our UI
    9.71              UpdateStatus();
    9.72 @@ -665,12 +666,12 @@
    9.73  
    9.74              // Check if our current client has an Audio Visualizer field
    9.75              // and render them as needed
    9.76 -            foreach (DataField f in iCurrentClientData.Fields)
    9.77 +            foreach (DataField f in iCurrentClientData.View.Fields)
    9.78              {
    9.79                  if (f is AudioVisualizerField)
    9.80                  {
    9.81                      AudioVisualizerField avf = (AudioVisualizerField)f;
    9.82 -                    Control ctrl = iTableLayoutPanel.GetControlFromPosition(avf.Column, avf.Row);
    9.83 +                    Control ctrl = iTableLayoutPanelCurrentClient.GetControlFromPosition(avf.Column, avf.Row);
    9.84  
    9.85                      if (ctrl is PictureBox)
    9.86                      {
    9.87 @@ -853,7 +854,7 @@
    9.88              //Fetch and set current client data.
    9.89              iCurrentClientData = requestedClientData;
    9.90              //Apply layout and set data fields.
    9.91 -            UpdateTableLayoutPanel(iCurrentClientData);
    9.92 +            UpdateTableLayoutPanel(iCurrentClientData.View, iTableLayoutPanelCurrentClient);
    9.93          }
    9.94  
    9.95          private void buttonFont_Click(object sender, EventArgs e)
    9.96 @@ -878,25 +879,19 @@
    9.97              //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
    9.98              if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
    9.99              {
   9.100 -                //Set the fonts to all our labels in our layout
   9.101 -                foreach (Control ctrl in iTableLayoutPanel.Controls)
   9.102 -                {
   9.103 -                    if (ctrl is MarqueeLabel)
   9.104 -                    {
   9.105 -                        ((MarqueeLabel) ctrl).Font = fontDialog.Font;
   9.106 -                    }
   9.107 -                }
   9.108 -
   9.109                  //Save font settings
   9.110                  cds.Font = fontDialog.Font;
   9.111                  Properties.Settings.Default.Save();
   9.112                  //
   9.113 +                //Set the fonts to all our labels in our layout
   9.114 +                UpdateFonts(iTableLayoutPanelDisplay);
   9.115 +                //
   9.116                  CheckFontHeight();
   9.117              }
   9.118          }
   9.119  
   9.120          /// <summary>
   9.121 -        ///
   9.122 +        /// TODO: review this in respect to our logical font feature when we get there.
   9.123          /// </summary>
   9.124          void CheckFontHeight()
   9.125          {
   9.126 @@ -915,7 +910,7 @@
   9.127  
   9.128              MarqueeLabel label = null;
   9.129              //Get the first label control we can find
   9.130 -            foreach (Control ctrl in iTableLayoutPanel.Controls)
   9.131 +            foreach (Control ctrl in iTableLayoutPanelCurrentClient.Controls)
   9.132              {
   9.133                  if (ctrl is MarqueeLabel)
   9.134                  {
   9.135 @@ -940,13 +935,11 @@
   9.136  
   9.137          private void buttonCapture_Click(object sender, EventArgs e)
   9.138          {
   9.139 -            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(iTableLayoutPanel.Width, iTableLayoutPanel.Height);
   9.140 -            iTableLayoutPanel.DrawToBitmap(bmp, iTableLayoutPanel.ClientRectangle);
   9.141 +            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(iTableLayoutPanelDisplay.Width, iTableLayoutPanelDisplay.Height);
   9.142 +            iTableLayoutPanelDisplay.DrawToBitmap(bmp, iTableLayoutPanelDisplay.ClientRectangle);
   9.143              //Bitmap bmpToSave = new Bitmap(bmp);
   9.144              bmp.Save("D:\\capture.png");
   9.145  
   9.146 -            ((MarqueeLabel) iTableLayoutPanel.Controls[0]).Text = "Captured";
   9.147 -
   9.148              /*
   9.149              string outputFileName = "d:\\capture.png";
   9.150              using (MemoryStream memory = new MemoryStream())
   9.151 @@ -1092,15 +1085,10 @@
   9.152  
   9.153              UpdateNetworkSignal(LastTickTime, NewTickTime);
   9.154  
   9.155 -            //Update animation for all our marquees
   9.156 -            foreach (Control ctrl in iTableLayoutPanel.Controls)
   9.157 -            {
   9.158 -                if (ctrl is MarqueeLabel)
   9.159 -                {
   9.160 -                    ((MarqueeLabel) ctrl).UpdateAnimation(LastTickTime, NewTickTime);
   9.161 -                }
   9.162 -            }
   9.163 -
   9.164 +            // Update animation for all our marquees
   9.165 +            UpdateMarqueesAnimations(iTableLayoutPanelDisplay, LastTickTime, NewTickTime);
   9.166 +
   9.167 +            // Update audio visualization
   9.168              UpdateAudioVisualization();
   9.169  
   9.170              //Update our display
   9.171 @@ -1115,11 +1103,11 @@
   9.172                      //Draw to bitmap
   9.173                      if (iCreateBitmap)
   9.174                      {
   9.175 -                        iBmp = new System.Drawing.Bitmap(iTableLayoutPanel.Width, iTableLayoutPanel.Height,
   9.176 +                        iBmp = new System.Drawing.Bitmap(iTableLayoutPanelDisplay.Width, iTableLayoutPanelDisplay.Height,
   9.177                              PixelFormat.Format32bppArgb);
   9.178                          iCreateBitmap = false;
   9.179                      }
   9.180 -                    iTableLayoutPanel.DrawToBitmap(iBmp, iTableLayoutPanel.ClientRectangle);
   9.181 +                    iTableLayoutPanelDisplay.DrawToBitmap(iBmp, iTableLayoutPanelDisplay.ClientRectangle);
   9.182                      //iBmp.Save("D:\\capture.png");
   9.183  
   9.184                      //Send it to our display
   9.185 @@ -1155,6 +1143,25 @@
   9.186          }
   9.187  
   9.188          /// <summary>
   9.189 +        /// Update marquee animation children of the given control.
   9.190 +        /// </summary>
   9.191 +        static private void UpdateMarqueesAnimations(Control aControl, DateTime aLastTickTime, DateTime aNewTickTime)
   9.192 +        {
   9.193 +            // For each our children
   9.194 +            foreach (Control ctrl in aControl.Controls)
   9.195 +            {
   9.196 +                // Update animation if it is a marquee control
   9.197 +                if (ctrl is MarqueeLabel)
   9.198 +                {
   9.199 +                    ((MarqueeLabel)ctrl).UpdateAnimation(aLastTickTime, aNewTickTime);
   9.200 +                }
   9.201 +
   9.202 +                // Go one level deeper by recursion
   9.203 +                UpdateMarqueesAnimations(ctrl, aLastTickTime, aNewTickTime);
   9.204 +            }
   9.205 +        }
   9.206 +
   9.207 +        /// <summary>
   9.208          /// Attempt to establish connection with our display hardware.
   9.209          /// </summary>
   9.210          private void OpenDisplayConnection()
   9.211 @@ -1273,21 +1280,56 @@
   9.212          }
   9.213  
   9.214          /// <summary>
   9.215 +        /// Update fonts in our control tree.
   9.216 +        /// </summary>
   9.217 +        /// <param name="aControls"></param>
   9.218 +        private void UpdateFonts(Control aControl)
   9.219 +        {
   9.220 +            foreach (Control ctrl in aControl.Controls)
   9.221 +            {
   9.222 +                if (ctrl is MarqueeLabel)
   9.223 +                {
   9.224 +                    MarqueeLabel marquee = (MarqueeLabel)ctrl;
   9.225 +                    marquee.Font = cds.Font;
   9.226 +                }
   9.227 +
   9.228 +                // Recurse
   9.229 +                UpdateFonts(ctrl);
   9.230 +            }
   9.231 +        }
   9.232 +
   9.233 +        /// <summary>
   9.234 +        /// Update marquees separator in our control tree.
   9.235 +        /// </summary>
   9.236 +        /// <param name="aControls"></param>
   9.237 +        private void UpdateMarqueesSeparator(Control aControl)
   9.238 +        {
   9.239 +            foreach (Control ctrl in aControl.Controls)
   9.240 +            {
   9.241 +                if (ctrl is MarqueeLabel)
   9.242 +                {
   9.243 +                    MarqueeLabel marquee = (MarqueeLabel)ctrl;
   9.244 +                    marquee.Separator = cds.Separator;
   9.245 +                }
   9.246 +
   9.247 +                // Recurse
   9.248 +                UpdateMarqueesSeparator(ctrl);
   9.249 +            }
   9.250 +        }
   9.251 +
   9.252 +        /// <summary>
   9.253          /// Synchronize UI with settings
   9.254          /// </summary>
   9.255          private void UpdateStatus()
   9.256          {
   9.257              //Load settings
   9.258              checkBoxShowBorders.Checked = cds.ShowBorders;
   9.259 -            iTableLayoutPanel.CellBorderStyle = (cds.ShowBorders
   9.260 +            iTableLayoutPanelCurrentClient.CellBorderStyle = (cds.ShowBorders
   9.261                  ? TableLayoutPanelCellBorderStyle.Single
   9.262                  : TableLayoutPanelCellBorderStyle.None);
   9.263  
   9.264              //Set the proper font to each of our labels
   9.265 -            foreach (MarqueeLabel ctrl in iTableLayoutPanel.Controls)
   9.266 -            {
   9.267 -                ctrl.Font = cds.Font;
   9.268 -            }
   9.269 +            UpdateFonts(iTableLayoutPanelDisplay);
   9.270  
   9.271              CheckFontHeight();
   9.272              //Check if "run on Windows startup" is enabled
   9.273 @@ -1318,8 +1360,9 @@
   9.274                  //Reflect that in our UI
   9.275                  StartTimer();
   9.276  
   9.277 -                iTableLayoutPanel.Enabled = true;
   9.278 -                panelDisplay.Enabled = true;
   9.279 +                iTableLayoutPanelDisplay.Enabled = true;
   9.280 +                iTableLayoutPanelCurrentClient.Enabled = true;
   9.281 +                iPanelDisplay.Enabled = true;
   9.282  
   9.283                  //Only setup brightness if display is open
   9.284                  trackBarBrightness.Minimum = iDisplay.MinBrightness();
   9.285 @@ -1397,8 +1440,9 @@
   9.286                  StopTimer();
   9.287  #endif
   9.288                  checkBoxShowVolumeLabel.Enabled = false;
   9.289 -                iTableLayoutPanel.Enabled = false;
   9.290 -                panelDisplay.Enabled = false;
   9.291 +                iTableLayoutPanelDisplay.Enabled = false;
   9.292 +                iTableLayoutPanelCurrentClient.Enabled = false;
   9.293 +                iPanelDisplay.Enabled = false;
   9.294                  buttonFill.Enabled = false;
   9.295                  buttonClear.Enabled = false;
   9.296                  buttonOpen.Enabled = true;
   9.297 @@ -1430,7 +1474,7 @@
   9.298          private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
   9.299          {
   9.300              //Save our show borders setting
   9.301 -            iTableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked
   9.302 +            iTableLayoutPanelCurrentClient.CellBorderStyle = (checkBoxShowBorders.Checked
   9.303                  ? TableLayoutPanelCellBorderStyle.Single
   9.304                  : TableLayoutPanelCellBorderStyle.None);
   9.305              cds.ShowBorders = checkBoxShowBorders.Checked;
   9.306 @@ -1527,6 +1571,9 @@
   9.307              }
   9.308          }
   9.309  
   9.310 +        /// <summary>
   9.311 +        /// 
   9.312 +        /// </summary>
   9.313          public void BroadcastCloseEvent()
   9.314          {
   9.315              Trace.TraceInformation("BroadcastCloseEvent - start");
   9.316 @@ -1560,7 +1607,7 @@
   9.317  
   9.318              if (iClients.Count == 0)
   9.319              {
   9.320 -                ClearLayout();
   9.321 +                ClearLayout(iTableLayoutPanelCurrentClient);
   9.322                  iCurrentClientData = null;
   9.323              }
   9.324          }
   9.325 @@ -1568,24 +1615,24 @@
   9.326          /// <summary>
   9.327          /// Just remove all our fields.
   9.328          /// </summary>
   9.329 -        private void ClearLayout()
   9.330 +        static private void ClearLayout(TableLayoutPanel aPanel)
   9.331          {
   9.332              // For each loop did not work as calling Dispose on a control removes it from the collection.
   9.333              // We make sure every control are disposed of notably to turn off visualizer when no more needed.
   9.334              // That's the only way we found to make sure Control.Disposed is called in a timely fashion.
   9.335              // Though that loop is admetitly dangerous as if one of the control does not removes itself from the list we end up with infinite loop.
   9.336              // That's what happened with our MarqueeLabel until we fixed it's Dispose override.
   9.337 -            while (iTableLayoutPanel.Controls.Count>0)
   9.338 +            while (aPanel.Controls.Count>0)
   9.339              {
   9.340                  // Dispose our last item
   9.341 -                iTableLayoutPanel.Controls[iTableLayoutPanel.Controls.Count-1].Dispose();
   9.342 +                aPanel.Controls[aPanel.Controls.Count-1].Dispose();
   9.343              }
   9.344  
   9.345 -            iTableLayoutPanel.Controls.Clear();
   9.346 -            iTableLayoutPanel.RowStyles.Clear();
   9.347 -            iTableLayoutPanel.ColumnStyles.Clear();
   9.348 -            iTableLayoutPanel.RowCount = 0;
   9.349 -            iTableLayoutPanel.ColumnCount = 0;            
   9.350 +            aPanel.Controls.Clear();
   9.351 +            aPanel.RowStyles.Clear();
   9.352 +            aPanel.ColumnStyles.Clear();
   9.353 +            aPanel.RowCount = 0;
   9.354 +            aPanel.ColumnCount = 0;            
   9.355          }
   9.356  
   9.357          /// <summary>
   9.358 @@ -1764,7 +1811,7 @@
   9.359                  if (iClients.Count == 0)
   9.360                  {
   9.361                      //Clear our screen when last client disconnects
   9.362 -                    ClearLayout();
   9.363 +                    ClearLayout(iTableLayoutPanelCurrentClient);
   9.364                      iCurrentClientData = null;
   9.365  
   9.366                      if (iClosing)
   9.367 @@ -1789,32 +1836,43 @@
   9.368              if (this.InvokeRequired)
   9.369              {
   9.370                  //Not in the proper thread, invoke ourselves
   9.371 -                SetLayoutDelegate d = new SetLayoutDelegate(SetClientLayoutThreadSafe);
   9.372 -                this.Invoke(d, new object[] {aSessionId, aLayout});
   9.373 +                Invoke(new Action<FormMain>((sender) => { SetClientLayoutThreadSafe(aSessionId, aLayout); }), this);
   9.374 +                return;
   9.375              }
   9.376 -            else
   9.377 +
   9.378 +            ClientData client = iClients[aSessionId];
   9.379 +            if (client == null)
   9.380              {
   9.381 -                ClientData client = iClients[aSessionId];
   9.382 -                if (client != null)
   9.383 +                //TODO: logs
   9.384 +                return;
   9.385 +            }
   9.386 +
   9.387 +            // If we have a matching client and we want to change the client layout
   9.388 +            if (client.Target == Target.Client)
   9.389 +            {
   9.390 +                //Don't change a thing if the layout is the same
   9.391 +                if (!client.View.Layout.IsSameAs(aLayout))
   9.392                  {
   9.393 -                    //Don't change a thing if the layout is the same
   9.394 -                    if (!client.Layout.IsSameAs(aLayout))
   9.395 -                    {
   9.396 -                        Debug.Print("SetClientLayoutThreadSafe: Layout updated.");
   9.397 -                        //Set our client layout then
   9.398 -                        client.Layout = aLayout;
   9.399 -                        //So that next time we update all our fields at ones
   9.400 -                        client.HasNewLayout = true;
   9.401 -                        //Layout has changed clear our fields then
   9.402 -                        client.Fields.Clear();
   9.403 -                        //
   9.404 -                        UpdateClientTreeViewNode(client);
   9.405 -                    }
   9.406 -                    else
   9.407 -                    {
   9.408 -                        Debug.Print("SetClientLayoutThreadSafe: Layout has not changed.");
   9.409 -                    }
   9.410 +                    Debug.Print("SetClientLayoutThreadSafe: Layout updated.");
   9.411 +                    //Set our client layout then
   9.412 +                    client.View.Layout = aLayout;
   9.413 +                    //So that next time we update all our fields at ones
   9.414 +                    client.HasNewLayout = true;
   9.415 +                    //Layout has changed clear our fields then
   9.416 +                    client.View.Fields.Clear();
   9.417 +                    //
   9.418 +                    UpdateClientTreeViewNode(client);
   9.419                  }
   9.420 +                else
   9.421 +                {
   9.422 +                    Debug.Print("SetClientLayoutThreadSafe: Layout has not changed.");
   9.423 +                }
   9.424 +            }
   9.425 +            else if (client.Target == Target.Display)
   9.426 +            {
   9.427 +                // Mark our display layout has updated and wait for the fields.
   9.428 +                // Is display layout a property from our client?
   9.429 +                //iTableLayoutPanelDisplay. = aLayout;
   9.430              }
   9.431          }
   9.432  
   9.433 @@ -1828,8 +1886,7 @@
   9.434              if (this.InvokeRequired)
   9.435              {
   9.436                  //Not in the proper thread, invoke ourselves
   9.437 -                SetFieldDelegate d = new SetFieldDelegate(SetClientFieldThreadSafe);
   9.438 -                this.Invoke(d, new object[] {aSessionId, aField});
   9.439 +                Invoke(new Action<FormMain>((sender) => { SetClientFieldThreadSafe(aSessionId, aField); }), this);
   9.440              }
   9.441              else
   9.442              {
   9.443 @@ -1856,7 +1913,7 @@
   9.444              bool contentChanged = true;
   9.445  
   9.446              //Fetch our field index
   9.447 -            int fieldIndex = client.FindSameFieldIndex(aField);
   9.448 +            int fieldIndex = client.View.FindSameFieldIndex(aField);
   9.449  
   9.450              if (fieldIndex < 0)
   9.451              {
   9.452 @@ -1865,9 +1922,9 @@
   9.453              }
   9.454  
   9.455              //Keep our previous field in there
   9.456 -            DataField previousField = client.Fields[fieldIndex];
   9.457 +            DataField previousField = client.View.Fields[fieldIndex];
   9.458              //Just update that field then 
   9.459 -            client.Fields[fieldIndex] = aField;
   9.460 +            client.View.Fields[fieldIndex] = aField;
   9.461  
   9.462              if (!aField.IsTableField)
   9.463              {
   9.464 @@ -1882,7 +1939,7 @@
   9.465                  //If we are updating a field in our current client we need to update it in our panel
   9.466                  if (aSessionId == iCurrentClientSessionId)
   9.467                  {
   9.468 -                    Control ctrl = iTableLayoutPanel.GetControlFromPosition(tableField.Column, tableField.Row);
   9.469 +                    Control ctrl = iTableLayoutPanelCurrentClient.GetControlFromPosition(tableField.Column, tableField.Row);
   9.470                      if (aField.IsTextField && ctrl is MarqueeLabel)
   9.471                      {
   9.472                          TextField textField = (TextField)aField;
   9.473 @@ -1927,7 +1984,7 @@
   9.474                      if (aSessionId == iCurrentClientSessionId)
   9.475                      {
   9.476                          //Apply layout and set data fields.
   9.477 -                        UpdateTableLayoutPanel(iCurrentClientData);
   9.478 +                        UpdateTableLayoutPanel(iCurrentClientData.View, iTableLayoutPanelCurrentClient);
   9.479                      }
   9.480                  }
   9.481                  else
   9.482 @@ -1953,8 +2010,7 @@
   9.483              if (this.InvokeRequired)
   9.484              {
   9.485                  //Not in the proper thread, invoke ourselves
   9.486 -                SetFieldsDelegate d = new SetFieldsDelegate(SetClientFieldsThreadSafe);
   9.487 -                this.Invoke(d, new object[] {aSessionId, aFields});
   9.488 +                Invoke(new Action<FormMain>((sender) => { SetClientFieldsThreadSafe(aSessionId, aFields); }), this);
   9.489              }
   9.490              else
   9.491              {
   9.492 @@ -1967,7 +2023,7 @@
   9.493                      //Do some special handling to avoid re-creating our panel N times, once for each fields
   9.494                      client.HasNewLayout = false;
   9.495                      //Just set all our fields then
   9.496 -                    client.Fields.AddRange(aFields);
   9.497 +                    client.View.Fields.AddRange(aFields);
   9.498                      //Try switch to that client
   9.499                      SetCurrentClient(aSessionId);
   9.500  
   9.501 @@ -1975,7 +2031,7 @@
   9.502                      if (aSessionId == iCurrentClientSessionId)
   9.503                      {
   9.504                          //Apply layout and set data fields.
   9.505 -                        UpdateTableLayoutPanel(iCurrentClientData);
   9.506 +                        UpdateTableLayoutPanel(iCurrentClientData.View, iTableLayoutPanelCurrentClient);
   9.507                      }
   9.508  
   9.509                      UpdateClientTreeViewNode(client);
   9.510 @@ -2001,8 +2057,7 @@
   9.511              if (this.InvokeRequired)
   9.512              {
   9.513                  //Not in the proper thread, invoke ourselves
   9.514 -                SetClientNameDelegate d = new SetClientNameDelegate(SetClientNameThreadSafe);
   9.515 -                this.Invoke(d, new object[] {aSessionId, aName});
   9.516 +                Invoke(new Action<FormMain>((sender) => { SetClientNameThreadSafe(aSessionId, aName); }), this);
   9.517              }
   9.518              else
   9.519              {
   9.520 @@ -2025,8 +2080,7 @@
   9.521              if (this.InvokeRequired)
   9.522              {
   9.523                  //Not in the proper thread, invoke ourselves
   9.524 -                SetClientPriorityDelegate d = new SetClientPriorityDelegate(SetClientPriorityThreadSafe);
   9.525 -                this.Invoke(d, new object[] {aSessionId, aPriority});
   9.526 +                Invoke(new Action<FormMain>((sender) => { SetClientPriorityThreadSafe(aSessionId, aPriority); }), this);
   9.527              }
   9.528              else
   9.529              {
   9.530 @@ -2035,7 +2089,7 @@
   9.531                  ClientData client = iClients[aSessionId];
   9.532                  if (client != null)
   9.533                  {
   9.534 -                    //Set its name
   9.535 +                    //Set its priority
   9.536                      client.Priority = aPriority;
   9.537                      //Update our tree-view
   9.538                      UpdateClientTreeViewNode(client);
   9.539 @@ -2052,6 +2106,33 @@
   9.540          /// <summary>
   9.541          /// 
   9.542          /// </summary>
   9.543 +        /// <param name="aSessionId"></param>
   9.544 +        /// <param name="aPriority"></param>
   9.545 +        public void SetClientTargetThreadSafe(string aSessionId, Target aTarget)
   9.546 +        {
   9.547 +            if (this.InvokeRequired)
   9.548 +            {
   9.549 +                //Not in the proper thread, invoke ourselves
   9.550 +                Invoke(new Action<FormMain>((sender) => { SetClientTargetThreadSafe(aSessionId, aTarget); }), this);
   9.551 +            }
   9.552 +            else
   9.553 +            {
   9.554 +                //We are in the proper thread
   9.555 +                //Get our client
   9.556 +                ClientData client = iClients[aSessionId];
   9.557 +                if (client != null)
   9.558 +                {
   9.559 +                    //Set its priority
   9.560 +                    client.Target = aTarget;
   9.561 +                    //Update our tree-view
   9.562 +                    //UpdateClientTreeViewNode(client);
   9.563 +                }
   9.564 +            }
   9.565 +        }
   9.566 +
   9.567 +        /// <summary>
   9.568 +        /// 
   9.569 +        /// </summary>
   9.570          /// <param name="value"></param>
   9.571          /// <param name="maxChars"></param>
   9.572          /// <returns></returns>
   9.573 @@ -2071,7 +2152,7 @@
   9.574              RecordingField recField = new RecordingField();
   9.575              foreach (var client in iClients)
   9.576              {
   9.577 -                RecordingField rec = (RecordingField) client.Value.FindSameFieldAs(recField);
   9.578 +                RecordingField rec = (RecordingField) client.Value.View.FindSameFieldAs(recField);
   9.579                  if (rec != null && rec.IsActive)
   9.580                  {
   9.581                      activeRecording = true;
   9.582 @@ -2158,13 +2239,13 @@
   9.583                  //Display client priority
   9.584                  node.Nodes.Add(new TreeNode("Priority: " + aClient.Priority));
   9.585  
   9.586 -                if (aClient.Fields.Count > 0)
   9.587 +                if (aClient.View.Fields.Count > 0)
   9.588                  {
   9.589                      //Create root node for our texts
   9.590                      TreeNode textsRoot = new TreeNode("Fields");
   9.591                      node.Nodes.Add(textsRoot);
   9.592                      //For each text add a new entry
   9.593 -                    foreach (DataField field in aClient.Fields)
   9.594 +                    foreach (DataField field in aClient.View.Fields)
   9.595                      {
   9.596                          if (field.IsTextField)
   9.597                          {
   9.598 @@ -2192,64 +2273,52 @@
   9.599          }
   9.600  
   9.601          /// <summary>
   9.602 -        /// Update our table layout row styles to make sure each rows have similar height
   9.603 -        /// </summary>
   9.604 -        private void UpdateTableLayoutRowStyles()
   9.605 -        {
   9.606 -            foreach (RowStyle rowStyle in iTableLayoutPanel.RowStyles)
   9.607 -            {
   9.608 -                rowStyle.SizeType = SizeType.Percent;
   9.609 -                rowStyle.Height = 100/iTableLayoutPanel.RowCount;
   9.610 -            }
   9.611 -        }
   9.612 -
   9.613 -        /// <summary>
   9.614          /// Update our display table layout.
   9.615          /// Will instanciated every field control as defined by our client.
   9.616          /// Fields must be specified by rows from the left.
   9.617          /// </summary>
   9.618          /// <param name="aLayout"></param>
   9.619 -        private void UpdateTableLayoutPanel(ClientData aClient)
   9.620 +        private void UpdateTableLayoutPanel(SharpLib.Display.View aView, TableLayoutPanel aPanel)
   9.621          {
   9.622              Debug.Print("UpdateTableLayoutPanel");
   9.623  
   9.624 -            if (aClient == null)
   9.625 +            if (aView == null)
   9.626              {
   9.627                  //Just drop it
   9.628                  return;
   9.629              }
   9.630  
   9.631  
   9.632 -            TableLayout layout = aClient.Layout;
   9.633 +            TableLayout layout = aView.Layout;
   9.634  
   9.635              //First clean our current panel
   9.636 -            ClearLayout();
   9.637 +            ClearLayout(aPanel);
   9.638  
   9.639              //Then recreate our rows...
   9.640 -            while (iTableLayoutPanel.RowCount < layout.Rows.Count)
   9.641 +            while (aPanel.RowCount < layout.Rows.Count)
   9.642              {
   9.643 -                iTableLayoutPanel.RowCount++;
   9.644 +                aPanel.RowCount++;
   9.645              }
   9.646  
   9.647              // ...and columns 
   9.648 -            while (iTableLayoutPanel.ColumnCount < layout.Columns.Count)
   9.649 +            while (aPanel.ColumnCount < layout.Columns.Count)
   9.650              {
   9.651 -                iTableLayoutPanel.ColumnCount++;
   9.652 +                aPanel.ColumnCount++;
   9.653              }
   9.654  
   9.655              //For each column
   9.656 -            for (int i = 0; i < iTableLayoutPanel.ColumnCount; i++)
   9.657 +            for (int i = 0; i < aPanel.ColumnCount; i++)
   9.658              {
   9.659                  //Create our column styles
   9.660 -                this.iTableLayoutPanel.ColumnStyles.Add(layout.Columns[i]);
   9.661 +                aPanel.ColumnStyles.Add(layout.Columns[i]);
   9.662  
   9.663                  //For each rows
   9.664 -                for (int j = 0; j < iTableLayoutPanel.RowCount; j++)
   9.665 +                for (int j = 0; j < aPanel.RowCount; j++)
   9.666                  {
   9.667                      if (i == 0)
   9.668                      {
   9.669                          //Create our row styles
   9.670 -                        this.iTableLayoutPanel.RowStyles.Add(layout.Rows[j]);
   9.671 +                        aPanel.RowStyles.Add(layout.Rows[j]);
   9.672                      }
   9.673                      else
   9.674                      {
   9.675 @@ -2259,7 +2328,7 @@
   9.676              }
   9.677  
   9.678              //For each field
   9.679 -            foreach (DataField field in aClient.Fields)
   9.680 +            foreach (DataField field in aView.Fields)
   9.681              {
   9.682                  if (!field.IsTableField)
   9.683                  {
   9.684 @@ -2273,10 +2342,10 @@
   9.685                  Control control = CreateControlForDataField(tableField);
   9.686  
   9.687                  //Add newly created control to our table layout at the specified row and column
   9.688 -                iTableLayoutPanel.Controls.Add(control, tableField.Column, tableField.Row);
   9.689 +                aPanel.Controls.Add(control, tableField.Column, tableField.Row);
   9.690                  //Make sure we specify column and row span for that new control
   9.691 -                iTableLayoutPanel.SetColumnSpan(control, tableField.ColumnSpan);
   9.692 -                iTableLayoutPanel.SetRowSpan(control, tableField.RowSpan);
   9.693 +                aPanel.SetColumnSpan(control, tableField.ColumnSpan);
   9.694 +                aPanel.SetRowSpan(control, tableField.RowSpan);
   9.695              }
   9.696  
   9.697  
   9.698 @@ -2428,7 +2497,10 @@
   9.699                      cds.MinFontSize = minFontSize;
   9.700                      Properties.Settings.Default.Save();
   9.701                      //We need to recreate our layout for that change to take effect
   9.702 -                    UpdateTableLayoutPanel(iCurrentClientData);
   9.703 +                    if (iCurrentClientData != null)
   9.704 +                    {
   9.705 +                        UpdateTableLayoutPanel(iCurrentClientData.View, iTableLayoutPanelCurrentClient);
   9.706 +                    }
   9.707                  }
   9.708              }
   9.709          }
   9.710 @@ -2445,22 +2517,26 @@
   9.711                      cds.ScrollingSpeedInPixelsPerSecond = scrollingSpeed;
   9.712                      Properties.Settings.Default.Save();
   9.713                      //We need to recreate our layout for that change to take effect
   9.714 -                    UpdateTableLayoutPanel(iCurrentClientData);
   9.715 +                    if (iCurrentClientData != null)
   9.716 +                    {
   9.717 +                        UpdateTableLayoutPanel(iCurrentClientData.View, iTableLayoutPanelCurrentClient);
   9.718 +                    }
   9.719                  }
   9.720              }
   9.721          }
   9.722  
   9.723 +        /// <summary>
   9.724 +        /// 
   9.725 +        /// </summary>
   9.726 +        /// <param name="sender"></param>
   9.727 +        /// <param name="e"></param>
   9.728          private void textBoxScrollLoopSeparator_TextChanged(object sender, EventArgs e)
   9.729          {
   9.730              cds.Separator = textBoxScrollLoopSeparator.Text;
   9.731              Properties.Settings.Default.Save();
   9.732  
   9.733              //Update our text fields
   9.734 -            foreach (MarqueeLabel ctrl in iTableLayoutPanel.Controls)
   9.735 -            {
   9.736 -                ctrl.Separator = cds.Separator;
   9.737 -            }
   9.738 -
   9.739 +            UpdateMarqueesSeparator(iTableLayoutPanelDisplay);
   9.740          }
   9.741  
   9.742          private void buttonPowerOn_Click(object sender, EventArgs e)
    10.1 --- a/Server/Session.cs	Sun Jan 08 12:19:35 2017 +0100
    10.2 +++ b/Server/Session.cs	Sun Jan 15 18:49:06 2017 +0100
    10.3 @@ -41,6 +41,7 @@
    10.4          public string SessionId { get; set; }
    10.5          public string Name { get; set; }
    10.6          public uint Priority { get; set; }
    10.7 +        public Target Target { get; set; }
    10.8  
    10.9          Session()
   10.10          {
   10.11 @@ -84,6 +85,13 @@
   10.12              SharpDisplayManager.Program.iFormMain.SetClientPriorityThreadSafe(SessionId, Priority);
   10.13          }
   10.14  
   10.15 +        public void SetTarget(Target aTarget)
   10.16 +        {
   10.17 +            Target = aTarget;
   10.18 +            SharpDisplayManager.Program.iFormMain.SetClientTargetThreadSafe(SessionId, Target);
   10.19 +        }
   10.20 +
   10.21 +
   10.22          public void SetLayout(TableLayout aLayout)
   10.23          {
   10.24              SharpDisplayManager.Program.iFormMain.SetClientLayoutThreadSafe(SessionId, aLayout);
    11.1 --- a/Server/SharpDisplayManager.csproj	Sun Jan 08 12:19:35 2017 +0100
    11.2 +++ b/Server/SharpDisplayManager.csproj	Sun Jan 15 18:49:06 2017 +0100
    11.3 @@ -128,8 +128,8 @@
    11.4        <HintPath>..\packages\LibMiniDisplay.1.1.8\lib\net20\MiniDisplayInterop.dll</HintPath>
    11.5        <Private>True</Private>
    11.6      </Reference>
    11.7 -    <Reference Include="SharpLibDisplay, Version=0.2.8.30538, Culture=neutral, processorArchitecture=MSIL">
    11.8 -      <HintPath>..\packages\SharpLibDisplay.0.2.8\lib\net40\SharpLibDisplay.dll</HintPath>
    11.9 +    <Reference Include="SharpLibDisplay, Version=0.2.8.17764, Culture=neutral, processorArchitecture=MSIL">
   11.10 +      <HintPath>..\packages\SharpLibDisplay.0.3.3\lib\net40\SharpLibDisplay.dll</HintPath>
   11.11        <Private>True</Private>
   11.12      </Reference>
   11.13      <Reference Include="SharpLibHid, Version=1.0.0.0, Culture=neutral, processorArchitecture=x86">
    12.1 --- a/Server/packages.config	Sun Jan 08 12:19:35 2017 +0100
    12.2 +++ b/Server/packages.config	Sun Jan 15 18:49:06 2017 +0100
    12.3 @@ -3,7 +3,7 @@
    12.4    <package id="CSCore" version="1.1.0" targetFramework="net46" />
    12.5    <package id="LibMiniDisplay" version="1.1.8" targetFramework="net46" />
    12.6    <package id="Loamen.agsXMPP" version="1.3.1" targetFramework="net46" />
    12.7 -  <package id="SharpLibDisplay" version="0.2.8" targetFramework="net46" />
    12.8 +  <package id="SharpLibDisplay" version="0.3.3" targetFramework="net46" />
    12.9    <package id="SharpLibHarmony" version="0.7.0" targetFramework="net46" />
   12.10    <package id="SharpLibHid" version="1.4.2" targetFramework="net46" />
   12.11    <package id="SharpLibNotification" version="0.0.1" targetFramework="net46" />