Server/MainForm.cs
author sl
Sun, 18 Jan 2015 12:35:22 +0100
changeset 92 787dee27fc0a
parent 90 aa157e129c42
child 94 fe939a729030
permissions -rw-r--r--
Auto Start should work.
     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Data;
     5 using System.Drawing;
     6 using System.Linq;
     7 using System.Text;
     8 using System.Threading.Tasks;
     9 using System.Windows.Forms;
    10 using System.IO;
    11 using CodeProject.Dialog;
    12 using System.Drawing.Imaging;
    13 using System.ServiceModel;
    14 using System.Threading;
    15 using System.Diagnostics;
    16 using System.Deployment.Application;
    17 //
    18 using SharpDisplayClient;
    19 using SharpDisplay;
    20 
    21 namespace SharpDisplayManager
    22 {
    23     //Types declarations
    24     public delegate uint ColorProcessingDelegate(int aX, int aY, uint aPixel);
    25     public delegate int CoordinateTranslationDelegate(System.Drawing.Bitmap aBmp, int aInt);
    26     //Delegates are used for our thread safe method
    27     public delegate void AddClientDelegate(string aSessionId, ICallback aCallback);
    28     public delegate void RemoveClientDelegate(string aSessionId);
    29     public delegate void SetFieldDelegate(string SessionId, DataField aField);
    30     public delegate void SetFieldsDelegate(string SessionId, System.Collections.Generic.IList<DataField> aFields);
    31     public delegate void SetLayoutDelegate(string SessionId, TableLayout aLayout);
    32     public delegate void SetClientNameDelegate(string aSessionId, string aName);
    33 
    34 
    35     /// <summary>
    36     /// Our Display manager main form
    37     /// </summary>
    38     public partial class MainForm : Form
    39     {
    40 
    41         DateTime LastTickTime;
    42         Display iDisplay;
    43         System.Drawing.Bitmap iBmp;
    44         bool iCreateBitmap; //Workaround render to bitmap issues when minimized
    45         ServiceHost iServiceHost;
    46         // Our collection of clients sorted by session id.
    47         public Dictionary<string, ClientData> iClients;
    48         // The name of the client which informations are currently displayed.
    49         public string iCurrentClientSessionId;
    50         ClientData iCurrentClientData;
    51         //
    52         public bool iClosing;
    53         //Function pointer for pixel color filtering
    54         ColorProcessingDelegate iColorFx;
    55         //Function pointer for pixel X coordinate intercept
    56         CoordinateTranslationDelegate iScreenX;
    57         //Function pointer for pixel Y coordinate intercept
    58         CoordinateTranslationDelegate iScreenY;
    59 
    60 		//
    61 		private StartupManager iStartupManager;
    62 
    63         public MainForm()
    64         {
    65             iCurrentClientSessionId = "";
    66             iCurrentClientData = null;
    67             LastTickTime = DateTime.Now;
    68             iDisplay = new Display();
    69             iClients = new Dictionary<string, ClientData>();
    70 			iStartupManager = new StartupManager();
    71 
    72             InitializeComponent();
    73             UpdateStatus();
    74             //We have a bug when drawing minimized and reusing our bitmap
    75             iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
    76             iCreateBitmap = false;
    77         }
    78 
    79         private void MainForm_Load(object sender, EventArgs e)
    80         {
    81 			if (ApplicationDeployment.IsNetworkDeployed)
    82 			{
    83 				this.Text += " - v" + ApplicationDeployment.CurrentDeployment.CurrentVersion;
    84 			}
    85 			else
    86 			{
    87 				this.Text += " - development";
    88 			}
    89 
    90             StartServer();
    91 
    92             if (Properties.Settings.Default.DisplayConnectOnStartup)
    93             {
    94                 OpenDisplayConnection();
    95             }
    96 
    97 			//
    98 			checkBoxAutoStart.Checked=iStartupManager.Startup;
    99         }
   100 
   101         /// <summary>
   102         /// Set our current client.
   103         /// This will take care of applying our client layout and set data fields.
   104         /// </summary>
   105         /// <param name="aSessionId"></param>
   106         void SetCurrentClient(string aSessionId)
   107         {
   108             if (aSessionId == iCurrentClientSessionId)
   109             {
   110                 //Given client is already the current one.
   111                 //Don't bother changing anything then.
   112                 return;
   113             }
   114 
   115             //Set current client ID.
   116             iCurrentClientSessionId = aSessionId;
   117             //Fetch and set current client data.
   118             iCurrentClientData = iClients[aSessionId];
   119             //Apply layout and set data fields.
   120             UpdateTableLayoutPanel(iCurrentClientData);
   121         }
   122 
   123         private void buttonFont_Click(object sender, EventArgs e)
   124         {
   125             //fontDialog.ShowColor = true;
   126             //fontDialog.ShowApply = true;
   127             fontDialog.ShowEffects = true;
   128             MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[0];
   129             fontDialog.Font = label.Font;
   130 
   131             fontDialog.FixedPitchOnly = checkBoxFixedPitchFontOnly.Checked;
   132 
   133             //fontDialog.ShowHelp = true;
   134 
   135             //fontDlg.MaxSize = 40;
   136             //fontDlg.MinSize = 22;
   137 
   138             //fontDialog.Parent = this;
   139             //fontDialog.StartPosition = FormStartPosition.CenterParent;
   140 
   141             //DlgBox.ShowDialog(fontDialog);
   142 
   143             //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
   144             if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
   145             {
   146 
   147                 //MsgBox.Show("MessageBox MsgBox", "MsgBox caption");
   148 
   149                 //MessageBox.Show("Ok");
   150                 foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
   151                 {
   152                     ctrl.Font = fontDialog.Font;
   153                 }
   154                 cds.Font = fontDialog.Font;
   155                 Properties.Settings.Default.Save();
   156                 //
   157                 CheckFontHeight();
   158             }
   159         }
   160 
   161         /// <summary>
   162         ///
   163         /// </summary>
   164         void CheckFontHeight()
   165         {
   166             //Show font height and width
   167             labelFontHeight.Text = "Font height: " + cds.Font.Height;
   168             float charWidth = IsFixedWidth(cds.Font);
   169             if (charWidth == 0.0f)
   170             {
   171                 labelFontWidth.Visible = false;
   172             }
   173             else
   174             {
   175                 labelFontWidth.Visible = true;
   176                 labelFontWidth.Text = "Font width: " + charWidth;
   177             }
   178 
   179             MarqueeLabel label = null;
   180             //Get the first label control we can find
   181             foreach (Control ctrl in tableLayoutPanel.Controls)
   182             {
   183                 if (ctrl is MarqueeLabel)
   184                 {
   185                     label = (MarqueeLabel)ctrl;
   186                     break;
   187                 }
   188             }
   189 
   190             //Now check font height and show a warning if needed.
   191             if (label != null && label.Font.Height > label.Height)
   192             {
   193                 labelWarning.Text = "WARNING: Selected font is too height by " + (label.Font.Height - label.Height) + " pixels!";
   194                 labelWarning.Visible = true;
   195             }
   196             else
   197             {
   198                 labelWarning.Visible = false;
   199             }
   200 
   201         }
   202 
   203         private void buttonCapture_Click(object sender, EventArgs e)
   204         {
   205             System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height);
   206             tableLayoutPanel.DrawToBitmap(bmp, tableLayoutPanel.ClientRectangle);
   207             //Bitmap bmpToSave = new Bitmap(bmp);
   208             bmp.Save("D:\\capture.png");
   209 
   210             ((MarqueeLabel)tableLayoutPanel.Controls[0]).Text = "Captured";
   211 
   212             /*
   213             string outputFileName = "d:\\capture.png";
   214             using (MemoryStream memory = new MemoryStream())
   215             {
   216                 using (FileStream fs = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
   217                 {
   218                     bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
   219                     byte[] bytes = memory.ToArray();
   220                     fs.Write(bytes, 0, bytes.Length);
   221                 }
   222             }
   223              */
   224 
   225         }
   226 
   227         private void CheckForRequestResults()
   228         {
   229             if (iDisplay.IsRequestPending())
   230             {
   231                 switch (iDisplay.AttemptRequestCompletion())
   232                 {
   233                     case Display.TMiniDisplayRequest.EMiniDisplayRequestFirmwareRevision:
   234                         toolStripStatusLabelConnect.Text += " v" + iDisplay.FirmwareRevision();
   235                         //Issue next request then
   236                         iDisplay.RequestPowerSupplyStatus();
   237                         break;
   238 
   239                     case Display.TMiniDisplayRequest.EMiniDisplayRequestPowerSupplyStatus:
   240                         if (iDisplay.PowerSupplyStatus())
   241                         {
   242                             toolStripStatusLabelPower.Text = "ON";
   243                         }
   244                         else
   245                         {
   246                             toolStripStatusLabelPower.Text = "OFF";
   247                         }
   248                         //Issue next request then
   249                         iDisplay.RequestDeviceId();
   250                         break;
   251 
   252                     case Display.TMiniDisplayRequest.EMiniDisplayRequestDeviceId:
   253                         toolStripStatusLabelConnect.Text += " - " + iDisplay.DeviceId();
   254                         //No more request to issue
   255                         break;
   256                 }
   257             }
   258         }
   259 
   260         public static uint ColorWhiteIsOn(int aX, int aY, uint aPixel)
   261         {
   262             if ((aPixel & 0x00FFFFFF) == 0x00FFFFFF)
   263             {
   264                 return 0xFFFFFFFF;
   265             }
   266             return 0x00000000;
   267         }
   268 
   269         public static uint ColorUntouched(int aX, int aY, uint aPixel)
   270         {
   271             return aPixel;
   272         }
   273 
   274         public static uint ColorInversed(int aX, int aY, uint aPixel)
   275         {
   276             return ~aPixel;
   277         }
   278 
   279         public static uint ColorChessboard(int aX, int aY, uint aPixel)
   280         {
   281             if ((aX % 2 == 0) && (aY % 2 == 0))
   282             {
   283                 return ~aPixel;
   284             }
   285             else if ((aX % 2 != 0) && (aY % 2 != 0))
   286             {
   287                 return ~aPixel;
   288             }
   289             return 0x00000000;
   290         }
   291 
   292 
   293         public static int ScreenReversedX(System.Drawing.Bitmap aBmp, int aX)
   294         {
   295             return aBmp.Width - aX - 1;
   296         }
   297 
   298         public int ScreenReversedY(System.Drawing.Bitmap aBmp, int aY)
   299         {
   300             return iBmp.Height - aY - 1;
   301         }
   302 
   303         public int ScreenX(System.Drawing.Bitmap aBmp, int aX)
   304         {
   305             return aX;
   306         }
   307 
   308         public int ScreenY(System.Drawing.Bitmap aBmp, int aY)
   309         {
   310             return aY;
   311         }
   312 
   313         /// <summary>
   314         /// Select proper pixel delegates according to our current settings.
   315         /// </summary>
   316         private void SetupPixelDelegates()
   317         {
   318             //Select our pixel processing routine
   319             if (cds.InverseColors)
   320             {
   321                 //iColorFx = ColorChessboard;
   322                 iColorFx = ColorInversed;
   323             }
   324             else
   325             {
   326                 iColorFx = ColorWhiteIsOn;
   327             }
   328 
   329             //Select proper coordinate translation functions
   330             //We used delegate/function pointer to support reverse screen without doing an extra test on each pixels
   331             if (cds.ReverseScreen)
   332             {
   333                 iScreenX = ScreenReversedX;
   334                 iScreenY = ScreenReversedY;
   335             }
   336             else
   337             {
   338                 iScreenX = ScreenX;
   339                 iScreenY = ScreenY;
   340             }
   341 
   342         }
   343 
   344         //This is our timer tick responsible to perform our render
   345         private void timer_Tick(object sender, EventArgs e)
   346         {
   347             //Update our animations
   348             DateTime NewTickTime = DateTime.Now;
   349 
   350             //Update animation for all our marquees
   351             foreach (Control ctrl in tableLayoutPanel.Controls)
   352             {
   353                 if (ctrl is MarqueeLabel)
   354                 {
   355                     ((MarqueeLabel)ctrl).UpdateAnimation(LastTickTime, NewTickTime);
   356                 }
   357             }
   358 
   359 
   360             //Update our display
   361             if (iDisplay.IsOpen())
   362             {
   363                 CheckForRequestResults();
   364 
   365                 //Draw to bitmap
   366                 if (iCreateBitmap)
   367                 {
   368                     iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
   369                 }
   370                 tableLayoutPanel.DrawToBitmap(iBmp, tableLayoutPanel.ClientRectangle);
   371                 //iBmp.Save("D:\\capture.png");
   372 
   373                 //Send it to our display
   374                 for (int i = 0; i < iBmp.Width; i++)
   375                 {
   376                     for (int j = 0; j < iBmp.Height; j++)
   377                     {
   378                         unchecked
   379                         {
   380                             //Get our processed pixel coordinates
   381                             int x = iScreenX(iBmp, i);
   382                             int y = iScreenY(iBmp, j);
   383                             //Get pixel color
   384                             uint color = (uint)iBmp.GetPixel(i, j).ToArgb();
   385                             //Apply color effects
   386                             color = iColorFx(x,y,color);
   387                             //Now set our pixel
   388                             iDisplay.SetPixel(x, y, color);
   389                         }
   390                     }
   391                 }
   392 
   393                 iDisplay.SwapBuffers();
   394 
   395             }
   396 
   397             //Compute instant FPS
   398             toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " / " + (1000/timer.Interval).ToString() + " FPS";
   399 
   400             LastTickTime = NewTickTime;
   401 
   402         }
   403 
   404         private void OpenDisplayConnection()
   405         {
   406             CloseDisplayConnection();
   407 
   408             if (iDisplay.Open((Display.TMiniDisplayType)cds.DisplayType))
   409             {
   410                 UpdateStatus();
   411                 iDisplay.RequestFirmwareRevision();
   412             }
   413             else
   414             {
   415                 UpdateStatus();
   416                 toolStripStatusLabelConnect.Text = "Connection error";
   417             }
   418         }
   419 
   420         private void CloseDisplayConnection()
   421         {
   422             iDisplay.Close();
   423             UpdateStatus();
   424         }
   425 
   426         private void buttonOpen_Click(object sender, EventArgs e)
   427         {
   428             OpenDisplayConnection();
   429         }
   430 
   431         private void buttonClose_Click(object sender, EventArgs e)
   432         {
   433             CloseDisplayConnection();
   434         }
   435 
   436         private void buttonClear_Click(object sender, EventArgs e)
   437         {
   438             iDisplay.Clear();
   439             iDisplay.SwapBuffers();
   440         }
   441 
   442         private void buttonFill_Click(object sender, EventArgs e)
   443         {
   444             iDisplay.Fill();
   445             iDisplay.SwapBuffers();
   446         }
   447 
   448         private void trackBarBrightness_Scroll(object sender, EventArgs e)
   449         {
   450             cds.Brightness = trackBarBrightness.Value;
   451             Properties.Settings.Default.Save();
   452             iDisplay.SetBrightness(trackBarBrightness.Value);
   453 
   454         }
   455 
   456 
   457         /// <summary>
   458         /// CDS stands for Current Display Settings
   459         /// </summary>
   460         private DisplaySettings cds
   461         {
   462             get
   463             {
   464                 DisplaysSettings settings = Properties.Settings.Default.DisplaysSettings;
   465                 if (settings == null)
   466                 {
   467                     settings = new DisplaysSettings();
   468                     settings.Init();
   469                     Properties.Settings.Default.DisplaysSettings = settings;
   470                 }
   471 
   472                 //Make sure all our settings have been created
   473                 while (settings.Displays.Count <= Properties.Settings.Default.CurrentDisplayIndex)
   474                 {
   475                     settings.Displays.Add(new DisplaySettings());
   476                 }
   477 
   478                 DisplaySettings displaySettings = settings.Displays[Properties.Settings.Default.CurrentDisplayIndex];
   479                 return displaySettings;
   480             }
   481         }
   482 
   483         /// <summary>
   484         /// Check if the given font has a fixed character pitch.
   485         /// </summary>
   486         /// <param name="ft"></param>
   487         /// <returns>0.0f if this is not a monospace font, otherwise returns the character width.</returns>
   488         public float IsFixedWidth(Font ft)
   489         {
   490             Graphics g = CreateGraphics();
   491             char[] charSizes = new char[] { 'i', 'a', 'Z', '%', '#', 'a', 'B', 'l', 'm', ',', '.' };
   492             float charWidth = g.MeasureString("I", ft, Int32.MaxValue, StringFormat.GenericTypographic).Width;
   493 
   494             bool fixedWidth = true;
   495 
   496             foreach (char c in charSizes)
   497                 if (g.MeasureString(c.ToString(), ft, Int32.MaxValue, StringFormat.GenericTypographic).Width != charWidth)
   498                     fixedWidth = false;
   499 
   500             if (fixedWidth)
   501             {
   502                 return charWidth;
   503             }
   504 
   505             return 0.0f;
   506         }
   507 
   508         private void UpdateStatus()
   509         {
   510             //Synchronize UI with settings
   511             //Load settings
   512             checkBoxShowBorders.Checked = cds.ShowBorders;
   513             tableLayoutPanel.CellBorderStyle = (cds.ShowBorders ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
   514 
   515             //Set the proper font to each of our labels
   516             foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
   517             {
   518                 ctrl.Font = cds.Font;
   519             }
   520 
   521             CheckFontHeight();
   522             checkBoxConnectOnStartup.Checked = Properties.Settings.Default.DisplayConnectOnStartup;
   523             checkBoxReverseScreen.Checked = cds.ReverseScreen;
   524             checkBoxInverseColors.Checked = cds.InverseColors;
   525             comboBoxDisplayType.SelectedIndex = cds.DisplayType;
   526             timer.Interval = cds.TimerInterval;
   527             maskedTextBoxTimerInterval.Text = cds.TimerInterval.ToString();
   528             //
   529             SetupPixelDelegates();
   530 
   531             if (iDisplay.IsOpen())
   532             {
   533                 //Only setup brightness if display is open
   534                 trackBarBrightness.Minimum = iDisplay.MinBrightness();
   535                 trackBarBrightness.Maximum = iDisplay.MaxBrightness();
   536                 trackBarBrightness.Value = cds.Brightness;
   537                 trackBarBrightness.LargeChange = Math.Max(1, (iDisplay.MaxBrightness() - iDisplay.MinBrightness()) / 5);
   538                 trackBarBrightness.SmallChange = 1;
   539                 iDisplay.SetBrightness(cds.Brightness);
   540                 //
   541                 buttonFill.Enabled = true;
   542                 buttonClear.Enabled = true;
   543                 buttonOpen.Enabled = false;
   544                 buttonClose.Enabled = true;
   545                 trackBarBrightness.Enabled = true;
   546                 toolStripStatusLabelConnect.Text = "Connected - " + iDisplay.Vendor() + " - " + iDisplay.Product();
   547                 //+ " - " + iDisplay.SerialNumber();
   548 
   549                 if (iDisplay.SupportPowerOnOff())
   550                 {
   551                     buttonPowerOn.Enabled = true;
   552                     buttonPowerOff.Enabled = true;
   553                 }
   554                 else
   555                 {
   556                     buttonPowerOn.Enabled = false;
   557                     buttonPowerOff.Enabled = false;
   558                 }
   559 
   560                 if (iDisplay.SupportClock())
   561                 {
   562                     buttonShowClock.Enabled = true;
   563                     buttonHideClock.Enabled = true;
   564                 }
   565                 else
   566                 {
   567                     buttonShowClock.Enabled = false;
   568                     buttonHideClock.Enabled = false;
   569                 }
   570             }
   571             else
   572             {
   573                 buttonFill.Enabled = false;
   574                 buttonClear.Enabled = false;
   575                 buttonOpen.Enabled = true;
   576                 buttonClose.Enabled = false;
   577                 trackBarBrightness.Enabled = false;
   578                 buttonPowerOn.Enabled = false;
   579                 buttonPowerOff.Enabled = false;
   580                 buttonShowClock.Enabled = false;
   581                 buttonHideClock.Enabled = false;
   582                 toolStripStatusLabelConnect.Text = "Disconnected";
   583                 toolStripStatusLabelPower.Text = "N/A";
   584             }
   585         }
   586 
   587 
   588 
   589         private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
   590         {
   591             //Save our show borders setting
   592             tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
   593             cds.ShowBorders = checkBoxShowBorders.Checked;
   594             Properties.Settings.Default.Save();
   595             CheckFontHeight();
   596         }
   597 
   598         private void checkBoxConnectOnStartup_CheckedChanged(object sender, EventArgs e)
   599         {
   600             //Save our connect on startup setting
   601             Properties.Settings.Default.DisplayConnectOnStartup = checkBoxConnectOnStartup.Checked;
   602             Properties.Settings.Default.Save();
   603         }
   604 
   605         private void checkBoxReverseScreen_CheckedChanged(object sender, EventArgs e)
   606         {
   607             //Save our reverse screen setting
   608             cds.ReverseScreen = checkBoxReverseScreen.Checked;
   609             Properties.Settings.Default.Save();
   610             SetupPixelDelegates();
   611         }
   612 
   613         private void checkBoxInverseColors_CheckedChanged(object sender, EventArgs e)
   614         {
   615             //Save our inverse colors setting
   616             cds.InverseColors = checkBoxInverseColors.Checked;
   617             Properties.Settings.Default.Save();
   618             SetupPixelDelegates();
   619         }
   620 
   621         private void MainForm_Resize(object sender, EventArgs e)
   622         {
   623             if (WindowState == FormWindowState.Minimized)
   624             {
   625                 // Do some stuff
   626                 //iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
   627                 iCreateBitmap = true;
   628             }
   629         }
   630 
   631         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
   632         {
   633             StopServer();
   634             e.Cancel = iClosing;
   635         }
   636 
   637         public void StartServer()
   638         {
   639             iServiceHost = new ServiceHost
   640                 (
   641                     typeof(Session),
   642                     new Uri[] { new Uri("net.tcp://localhost:8001/") }
   643                 );
   644 
   645             iServiceHost.AddServiceEndpoint(typeof(IService), new NetTcpBinding(SecurityMode.None, true), "DisplayService");
   646             iServiceHost.Open();
   647         }
   648 
   649         public void StopServer()
   650         {
   651             if (iClients.Count > 0 && !iClosing)
   652             {
   653                 //Tell our clients
   654                 iClosing = true;
   655                 BroadcastCloseEvent();
   656             }
   657             else if (iClosing)
   658             {
   659                 if (MessageBox.Show("Force exit?", "Waiting for clients...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
   660                 {
   661                     iClosing = false; //We make sure we force close if asked twice
   662                 }
   663             }
   664             else
   665             {
   666                 //We removed that as it often lags for some reason
   667                 //iServiceHost.Close();
   668             }
   669         }
   670 
   671         public void BroadcastCloseEvent()
   672         {
   673             Trace.TraceInformation("BroadcastCloseEvent - start");
   674 
   675             var inactiveClients = new List<string>();
   676             foreach (var client in iClients)
   677             {
   678                 //if (client.Key != eventData.ClientName)
   679                 {
   680                     try
   681                     {
   682                         Trace.TraceInformation("BroadcastCloseEvent - " + client.Key);
   683                         client.Value.Callback.OnCloseOrder(/*eventData*/);
   684                     }
   685                     catch (Exception ex)
   686                     {
   687                         inactiveClients.Add(client.Key);
   688                     }
   689                 }
   690             }
   691 
   692             if (inactiveClients.Count > 0)
   693             {
   694                 foreach (var client in inactiveClients)
   695                 {
   696                     iClients.Remove(client);
   697                     Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(client, false)[0]);
   698                 }
   699             }
   700         }
   701 
   702         private void buttonStartClient_Click(object sender, EventArgs e)
   703         {
   704             Thread clientThread = new Thread(SharpDisplayClient.Program.Main);
   705             clientThread.Start();
   706             BringToFront();
   707         }
   708 
   709         private void buttonSuspend_Click(object sender, EventArgs e)
   710         {
   711             LastTickTime = DateTime.Now; //Reset timer to prevent jump
   712             timer.Enabled = !timer.Enabled;
   713             if (!timer.Enabled)
   714             {
   715                 buttonSuspend.Text = "Run";
   716             }
   717             else
   718             {
   719                 buttonSuspend.Text = "Pause";
   720             }
   721         }
   722 
   723         private void buttonCloseClients_Click(object sender, EventArgs e)
   724         {
   725             BroadcastCloseEvent();
   726         }
   727 
   728         private void treeViewClients_AfterSelect(object sender, TreeViewEventArgs e)
   729         {
   730 
   731         }
   732 
   733 
   734         /// <summary>
   735         ///
   736         /// </summary>
   737         /// <param name="aSessionId"></param>
   738         /// <param name="aCallback"></param>
   739         public void AddClientThreadSafe(string aSessionId, ICallback aCallback)
   740         {
   741             if (this.InvokeRequired)
   742             {
   743                 //Not in the proper thread, invoke ourselves
   744                 AddClientDelegate d = new AddClientDelegate(AddClientThreadSafe);
   745                 this.Invoke(d, new object[] { aSessionId, aCallback });
   746             }
   747             else
   748             {
   749                 //We are in the proper thread
   750                 //Add this session to our collection of clients
   751                 ClientData newClient = new ClientData(aSessionId, aCallback);
   752                 Program.iMainForm.iClients.Add(aSessionId, newClient);
   753                 //Add this session to our UI
   754                 UpdateClientTreeViewNode(newClient);
   755             }
   756         }
   757 
   758         /// <summary>
   759         ///
   760         /// </summary>
   761         /// <param name="aSessionId"></param>
   762         public void RemoveClientThreadSafe(string aSessionId)
   763         {
   764             if (this.InvokeRequired)
   765             {
   766                 //Not in the proper thread, invoke ourselves
   767                 RemoveClientDelegate d = new RemoveClientDelegate(RemoveClientThreadSafe);
   768                 this.Invoke(d, new object[] { aSessionId });
   769             }
   770             else
   771             {
   772                 //We are in the proper thread
   773                 //Remove this session from both client collection and UI tree view
   774                 if (Program.iMainForm.iClients.Keys.Contains(aSessionId))
   775                 {
   776                     Program.iMainForm.iClients.Remove(aSessionId);
   777                     Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(aSessionId, false)[0]);
   778                 }
   779 
   780                 if (iClosing && iClients.Count == 0)
   781                 {
   782                     //We were closing our form
   783                     //All clients are now closed
   784                     //Just resume our close operation
   785                     iClosing = false;
   786                     Close();
   787                 }
   788             }
   789         }
   790 
   791         /// <summary>
   792         ///
   793         /// </summary>
   794         /// <param name="aSessionId"></param>
   795         /// <param name="aLayout"></param>
   796         public void SetClientLayoutThreadSafe(string aSessionId, TableLayout aLayout)
   797         {
   798             if (this.InvokeRequired)
   799             {
   800                 //Not in the proper thread, invoke ourselves
   801                 SetLayoutDelegate d = new SetLayoutDelegate(SetClientLayoutThreadSafe);
   802                 this.Invoke(d, new object[] { aSessionId, aLayout });
   803             }
   804             else
   805             {
   806                 ClientData client = iClients[aSessionId];
   807                 if (client != null)
   808                 {
   809                     client.Layout = aLayout;
   810                     UpdateTableLayoutPanel(client);
   811                     //
   812                     UpdateClientTreeViewNode(client);
   813                 }
   814             }
   815         }
   816 
   817         /// <summary>
   818         ///
   819         /// </summary>
   820         /// <param name="aSessionId"></param>
   821         /// <param name="aField"></param>
   822         public void SetClientFieldThreadSafe(string aSessionId, DataField aField)
   823         {
   824             if (this.InvokeRequired)
   825             {
   826                 //Not in the proper thread, invoke ourselves
   827                 SetFieldDelegate d = new SetFieldDelegate(SetClientFieldThreadSafe);
   828                 this.Invoke(d, new object[] { aSessionId, aField });
   829             }
   830             else
   831             {
   832                 //We are in the proper thread
   833                 //Call the non-thread-safe variant
   834                 SetClientField(aSessionId, aField);
   835             }
   836         }
   837 
   838         /// <summary>
   839         ///
   840         /// </summary>
   841         /// <param name="aSessionId"></param>
   842         /// <param name="aField"></param>
   843         private void SetClientField(string aSessionId, DataField aField)
   844         {
   845             SetCurrentClient(aSessionId);
   846             ClientData client = iClients[aSessionId];
   847             if (client != null)
   848             {
   849                 bool somethingChanged = false;
   850 
   851                 //Make sure all our fields are in place
   852                 while (client.Fields.Count < (aField.Index + 1))
   853                 {
   854                     //Add a text field with proper index
   855                     client.Fields.Add(new DataField(client.Fields.Count));
   856                     somethingChanged = true;
   857                 }
   858 
   859                 if (client.Fields[aField.Index].IsSameLayout(aField))
   860                 {
   861                     //Same layout just update our field
   862                     client.Fields[aField.Index] = aField;
   863                     //
   864                     if (aField.IsText && tableLayoutPanel.Controls[aField.Index] is MarqueeLabel)
   865                     {
   866                         //Text field control already in place, just change the text
   867                         MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[aField.Index];
   868                         somethingChanged = (label.Text != aField.Text || label.TextAlign != aField.Alignment);
   869                         label.Text = aField.Text;
   870                         label.TextAlign = aField.Alignment;
   871                     }
   872                     else if (aField.IsBitmap && tableLayoutPanel.Controls[aField.Index] is PictureBox)
   873                     {
   874                         somethingChanged = true; //TODO: Bitmap comp or should we leave that to clients?
   875                         //Bitmap field control already in place just change the bitmap
   876                         PictureBox pictureBox = (PictureBox)tableLayoutPanel.Controls[aField.Index];
   877                         pictureBox.Image = aField.Bitmap;
   878                     }
   879                     else
   880                     {
   881                         somethingChanged = true;
   882                         //The requested control in our layout it not of the correct type
   883                         //Wrong control type, re-create them all
   884                         UpdateTableLayoutPanel(iCurrentClientData);
   885                     }
   886                 }
   887                 else
   888                 {
   889                     somethingChanged = true;
   890                     //Different layout, need to rebuild it
   891                     client.Fields[aField.Index] = aField;
   892                     UpdateTableLayoutPanel(iCurrentClientData);
   893                 }
   894 
   895                 //
   896                 if (somethingChanged)
   897                 {
   898                     UpdateClientTreeViewNode(client);
   899                 }
   900             }
   901         }
   902 
   903         /// <summary>
   904         ///
   905         /// </summary>
   906         /// <param name="aTexts"></param>
   907         public void SetClientFieldsThreadSafe(string aSessionId, System.Collections.Generic.IList<DataField> aFields)
   908         {
   909             if (this.InvokeRequired)
   910             {
   911                 //Not in the proper thread, invoke ourselves
   912                 SetFieldsDelegate d = new SetFieldsDelegate(SetClientFieldsThreadSafe);
   913                 this.Invoke(d, new object[] { aSessionId, aFields });
   914             }
   915             else
   916             {
   917                 //Put each our text fields in a label control
   918                 foreach (DataField field in aFields)
   919                 {
   920                     SetClientField(aSessionId, field);
   921                 }
   922             }
   923         }
   924 
   925         /// <summary>
   926         ///
   927         /// </summary>
   928         /// <param name="aSessionId"></param>
   929         /// <param name="aName"></param>
   930         public void SetClientNameThreadSafe(string aSessionId, string aName)
   931         {
   932             if (this.InvokeRequired)
   933             {
   934                 //Not in the proper thread, invoke ourselves
   935                 SetClientNameDelegate d = new SetClientNameDelegate(SetClientNameThreadSafe);
   936                 this.Invoke(d, new object[] { aSessionId, aName });
   937             }
   938             else
   939             {
   940                 //We are in the proper thread
   941                 //Get our client
   942                 ClientData client = iClients[aSessionId];
   943                 if (client != null)
   944                 {
   945                     //Set its name
   946                     client.Name = aName;
   947                     //Update our tree-view
   948                     UpdateClientTreeViewNode(client);
   949                 }
   950             }
   951         }
   952 
   953         /// <summary>
   954         ///
   955         /// </summary>
   956         /// <param name="aClient"></param>
   957         private void UpdateClientTreeViewNode(ClientData aClient)
   958         {
   959             if (aClient == null)
   960             {
   961                 return;
   962             }
   963 
   964             TreeNode node = null;
   965             //Check that our client node already exists
   966             //Get our client root node using its key which is our session ID
   967             TreeNode[] nodes = treeViewClients.Nodes.Find(aClient.SessionId, false);
   968             if (nodes.Count()>0)
   969             {
   970                 //We already have a node for that client
   971                 node = nodes[0];
   972                 //Clear children as we are going to recreate them below
   973                 node.Nodes.Clear();
   974             }
   975             else
   976             {
   977                 //Client node does not exists create a new one
   978                 treeViewClients.Nodes.Add(aClient.SessionId, aClient.SessionId);
   979                 node = treeViewClients.Nodes.Find(aClient.SessionId, false)[0];
   980             }
   981 
   982             if (node != null)
   983             {
   984                 //Change its name
   985                 if (aClient.Name != "")
   986                 {
   987                     //We have a name, us it as text for our root node
   988                     node.Text = aClient.Name;
   989                     //Add a child with SessionId
   990                     node.Nodes.Add(new TreeNode(aClient.SessionId));
   991                 }
   992                 else
   993                 {
   994                     //No name, use session ID instead
   995                     node.Text = aClient.SessionId;
   996                 }
   997 
   998                 if (aClient.Fields.Count > 0)
   999                 {
  1000                     //Create root node for our texts
  1001                     TreeNode textsRoot = new TreeNode("Fields");
  1002                     node.Nodes.Add(textsRoot);
  1003                     //For each text add a new entry
  1004                     foreach (DataField field in aClient.Fields)
  1005                     {
  1006                         if (!field.IsBitmap)
  1007                         {
  1008                             DataField textField = (DataField)field;
  1009                             textsRoot.Nodes.Add(new TreeNode("[Text]" + textField.Text));
  1010                         }
  1011                         else
  1012                         {
  1013                             textsRoot.Nodes.Add(new TreeNode("[Bitmap]"));
  1014                         }
  1015                     }
  1016                 }
  1017 
  1018                 node.ExpandAll();
  1019             }
  1020         }
  1021 
  1022         private void buttonAddRow_Click(object sender, EventArgs e)
  1023         {
  1024             if (tableLayoutPanel.RowCount < 6)
  1025             {
  1026                 UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount, tableLayoutPanel.RowCount + 1);
  1027             }
  1028         }
  1029 
  1030         private void buttonRemoveRow_Click(object sender, EventArgs e)
  1031         {
  1032             if (tableLayoutPanel.RowCount > 1)
  1033             {
  1034                 UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount, tableLayoutPanel.RowCount - 1);
  1035             }
  1036 
  1037             UpdateTableLayoutRowStyles();
  1038         }
  1039 
  1040         private void buttonAddColumn_Click(object sender, EventArgs e)
  1041         {
  1042             if (tableLayoutPanel.ColumnCount < 8)
  1043             {
  1044                 UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount + 1, tableLayoutPanel.RowCount);
  1045             }
  1046         }
  1047 
  1048         private void buttonRemoveColumn_Click(object sender, EventArgs e)
  1049         {
  1050             if (tableLayoutPanel.ColumnCount > 1)
  1051             {
  1052                 UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount - 1, tableLayoutPanel.RowCount);
  1053             }
  1054         }
  1055 
  1056 
  1057         /// <summary>
  1058         /// Update our table layout row styles to make sure each rows have similar height
  1059         /// </summary>
  1060         private void UpdateTableLayoutRowStyles()
  1061         {
  1062             foreach (RowStyle rowStyle in tableLayoutPanel.RowStyles)
  1063             {
  1064                 rowStyle.SizeType = SizeType.Percent;
  1065                 rowStyle.Height = 100 / tableLayoutPanel.RowCount;
  1066             }
  1067         }
  1068 
  1069         /// DEPRECATED
  1070         /// <summary>
  1071         /// Empty and recreate our table layout with the given number of columns and rows.
  1072         /// Sizes of rows and columns are uniform.
  1073         /// </summary>
  1074         /// <param name="aColumn"></param>
  1075         /// <param name="aRow"></param>
  1076         private void UpdateTableLayoutPanel(int aColumn, int aRow)
  1077         {
  1078             tableLayoutPanel.Controls.Clear();
  1079             tableLayoutPanel.RowStyles.Clear();
  1080             tableLayoutPanel.ColumnStyles.Clear();
  1081             tableLayoutPanel.RowCount = 0;
  1082             tableLayoutPanel.ColumnCount = 0;
  1083 
  1084             while (tableLayoutPanel.RowCount < aRow)
  1085             {
  1086                 tableLayoutPanel.RowCount++;
  1087             }
  1088 
  1089             while (tableLayoutPanel.ColumnCount < aColumn)
  1090             {
  1091                 tableLayoutPanel.ColumnCount++;
  1092             }
  1093 
  1094             for (int i = 0; i < tableLayoutPanel.ColumnCount; i++)
  1095             {
  1096                 //Create our column styles
  1097                 this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100 / tableLayoutPanel.ColumnCount));
  1098 
  1099                 for (int j = 0; j < tableLayoutPanel.RowCount; j++)
  1100                 {
  1101                     if (i == 0)
  1102                     {
  1103                         //Create our row styles
  1104                         this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100 / tableLayoutPanel.RowCount));
  1105                     }
  1106 
  1107                     MarqueeLabel control = new SharpDisplayManager.MarqueeLabel();
  1108                     control.AutoEllipsis = true;
  1109                     control.AutoSize = true;
  1110                     control.BackColor = System.Drawing.Color.Transparent;
  1111                     control.Dock = System.Windows.Forms.DockStyle.Fill;
  1112                     control.Location = new System.Drawing.Point(1, 1);
  1113                     control.Margin = new System.Windows.Forms.Padding(0);
  1114                     control.Name = "marqueeLabelCol" + aColumn + "Row" + aRow;
  1115                     control.OwnTimer = false;
  1116                     control.PixelsPerSecond = 64;
  1117                     control.Separator = "|";
  1118                     //control.Size = new System.Drawing.Size(254, 30);
  1119                     //control.TabIndex = 2;
  1120                     control.Font = cds.Font;
  1121                     control.Text = "ABCDEFGHIJKLMNOPQRST-0123456789";
  1122                     control.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
  1123                     control.UseCompatibleTextRendering = true;
  1124                     //
  1125                     tableLayoutPanel.Controls.Add(control, i, j);
  1126                 }
  1127             }
  1128 
  1129             CheckFontHeight();
  1130         }
  1131 
  1132 
  1133         /// <summary>
  1134         /// Update our display table layout.
  1135         /// </summary>
  1136         /// <param name="aLayout"></param>
  1137         private void UpdateTableLayoutPanel(ClientData aClient)
  1138         {
  1139             TableLayout layout = aClient.Layout;
  1140             int fieldCount = 0;
  1141 
  1142             tableLayoutPanel.Controls.Clear();
  1143             tableLayoutPanel.RowStyles.Clear();
  1144             tableLayoutPanel.ColumnStyles.Clear();
  1145             tableLayoutPanel.RowCount = 0;
  1146             tableLayoutPanel.ColumnCount = 0;
  1147 
  1148             while (tableLayoutPanel.RowCount < layout.Rows.Count)
  1149             {
  1150                 tableLayoutPanel.RowCount++;
  1151             }
  1152 
  1153             while (tableLayoutPanel.ColumnCount < layout.Columns.Count)
  1154             {
  1155                 tableLayoutPanel.ColumnCount++;
  1156             }
  1157 
  1158             for (int i = 0; i < tableLayoutPanel.ColumnCount; i++)
  1159             {
  1160                 //Create our column styles
  1161                 this.tableLayoutPanel.ColumnStyles.Add(layout.Columns[i]);
  1162 
  1163                 for (int j = 0; j < tableLayoutPanel.RowCount; j++)
  1164                 {
  1165                     if (i == 0)
  1166                     {
  1167                         //Create our row styles
  1168                         this.tableLayoutPanel.RowStyles.Add(layout.Rows[j]);
  1169                     }
  1170 
  1171                     //Check if we already have a control
  1172                     Control existingControl = tableLayoutPanel.GetControlFromPosition(i,j);
  1173                     if (existingControl!=null)
  1174                     {
  1175                         //We already have a control in that cell as a results of row/col spanning
  1176                         //Move on to next cell then
  1177                         continue;
  1178                     }
  1179 
  1180                     fieldCount++;
  1181 
  1182                     //Check if a client field already exists for that cell
  1183                     if (aClient.Fields.Count <= tableLayoutPanel.Controls.Count)
  1184                     {
  1185                         //No client field specified, create a text field by default
  1186                         aClient.Fields.Add(new DataField(aClient.Fields.Count));
  1187                     }
  1188 
  1189                     //Create a control corresponding to the field specified for that cell
  1190                     DataField field = aClient.Fields[tableLayoutPanel.Controls.Count];
  1191                     Control control = CreateControlForDataField(field);
  1192 
  1193                     //Add newly created control to our table layout at the specified row and column
  1194                     tableLayoutPanel.Controls.Add(control, i, j);
  1195                     //Make sure we specify row and column span for that new control
  1196                     tableLayoutPanel.SetRowSpan(control,field.RowSpan);
  1197                     tableLayoutPanel.SetColumnSpan(control, field.ColumnSpan);
  1198                 }
  1199             }
  1200 
  1201             //
  1202             while (aClient.Fields.Count > fieldCount)
  1203             {
  1204                 //We have too much fields for this layout
  1205                 //Just discard them until we get there
  1206                 aClient.Fields.RemoveAt(aClient.Fields.Count-1);
  1207             }
  1208 
  1209             CheckFontHeight();
  1210         }
  1211 
  1212         /// <summary>
  1213         /// Check our type of data field and create corresponding control
  1214         /// </summary>
  1215         /// <param name="aField"></param>
  1216         private Control CreateControlForDataField(DataField aField)
  1217         {
  1218             Control control=null;
  1219             if (!aField.IsBitmap)
  1220             {
  1221                 MarqueeLabel label = new SharpDisplayManager.MarqueeLabel();
  1222                 label.AutoEllipsis = true;
  1223                 label.AutoSize = true;
  1224                 label.BackColor = System.Drawing.Color.Transparent;
  1225                 label.Dock = System.Windows.Forms.DockStyle.Fill;
  1226                 label.Location = new System.Drawing.Point(1, 1);
  1227                 label.Margin = new System.Windows.Forms.Padding(0);
  1228                 label.Name = "marqueeLabel" + aField.Index;
  1229                 label.OwnTimer = false;
  1230                 label.PixelsPerSecond = 64;
  1231                 label.Separator = "|";
  1232                 //control.Size = new System.Drawing.Size(254, 30);
  1233                 //control.TabIndex = 2;
  1234                 label.Font = cds.Font;
  1235 
  1236                 label.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
  1237                 label.UseCompatibleTextRendering = true;
  1238                 label.Text = aField.Text;
  1239                 //
  1240                 control = label;
  1241             }
  1242             else
  1243             {
  1244                 //Create picture box
  1245                 PictureBox picture = new PictureBox();
  1246                 picture.AutoSize = true;
  1247                 picture.BackColor = System.Drawing.Color.Transparent;
  1248                 picture.Dock = System.Windows.Forms.DockStyle.Fill;
  1249                 picture.Location = new System.Drawing.Point(1, 1);
  1250                 picture.Margin = new System.Windows.Forms.Padding(0);
  1251                 picture.Name = "pictureBox" + aField;
  1252                 //Set our image
  1253                 picture.Image = aField.Bitmap;
  1254                 //
  1255                 control = picture;
  1256             }
  1257 
  1258             return control;
  1259         }
  1260 
  1261 
  1262         private void buttonAlignLeft_Click(object sender, EventArgs e)
  1263         {
  1264             foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
  1265             {
  1266                 ctrl.TextAlign = ContentAlignment.MiddleLeft;
  1267             }
  1268         }
  1269 
  1270         private void buttonAlignCenter_Click(object sender, EventArgs e)
  1271         {
  1272             foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
  1273             {
  1274                 ctrl.TextAlign = ContentAlignment.MiddleCenter;
  1275             }
  1276         }
  1277 
  1278         private void buttonAlignRight_Click(object sender, EventArgs e)
  1279         {
  1280             foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
  1281             {
  1282                 ctrl.TextAlign = ContentAlignment.MiddleRight;
  1283             }
  1284         }
  1285 
  1286         private void comboBoxDisplayType_SelectedIndexChanged(object sender, EventArgs e)
  1287         {
  1288             Properties.Settings.Default.CurrentDisplayIndex = comboBoxDisplayType.SelectedIndex;
  1289             cds.DisplayType = comboBoxDisplayType.SelectedIndex;
  1290             Properties.Settings.Default.Save();
  1291             if (iDisplay.IsOpen())
  1292             {
  1293                 OpenDisplayConnection();
  1294             }
  1295             else
  1296             {
  1297                 UpdateStatus();
  1298             }
  1299         }
  1300 
  1301 
  1302         private void maskedTextBoxTimerInterval_TextChanged(object sender, EventArgs e)
  1303         {
  1304             if (maskedTextBoxTimerInterval.Text != "")
  1305             {
  1306                 int interval = Convert.ToInt32(maskedTextBoxTimerInterval.Text);
  1307 
  1308                 if (interval > 0)
  1309                 {
  1310                     timer.Interval = interval;
  1311                     cds.TimerInterval = timer.Interval;
  1312                     Properties.Settings.Default.Save();
  1313                 }
  1314             }
  1315         }
  1316 
  1317         private void buttonPowerOn_Click(object sender, EventArgs e)
  1318         {
  1319             iDisplay.PowerOn();
  1320         }
  1321 
  1322         private void buttonPowerOff_Click(object sender, EventArgs e)
  1323         {
  1324             iDisplay.PowerOff();
  1325         }
  1326 
  1327         private void buttonShowClock_Click(object sender, EventArgs e)
  1328         {
  1329             iDisplay.ShowClock();
  1330         }
  1331 
  1332         private void buttonHideClock_Click(object sender, EventArgs e)
  1333         {
  1334             iDisplay.HideClock();
  1335         }
  1336 
  1337         private void buttonUpdate_Click(object sender, EventArgs e)
  1338         {
  1339             InstallUpdateSyncWithInfo();
  1340         }
  1341 
  1342 
  1343         private void InstallUpdateSyncWithInfo()
  1344         {
  1345             UpdateCheckInfo info = null;
  1346 
  1347             if (ApplicationDeployment.IsNetworkDeployed)
  1348             {
  1349                 ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
  1350 
  1351                 try
  1352                 {
  1353                     info = ad.CheckForDetailedUpdate();
  1354 
  1355                 }
  1356                 catch (DeploymentDownloadException dde)
  1357                 {
  1358                     MessageBox.Show("The new version of the application cannot be downloaded at this time. \n\nPlease check your network connection, or try again later. Error: " + dde.Message);
  1359                     return;
  1360                 }
  1361                 catch (InvalidDeploymentException ide)
  1362                 {
  1363                     MessageBox.Show("Cannot check for a new version of the application. The ClickOnce deployment is corrupt. Please redeploy the application and try again. Error: " + ide.Message);
  1364                     return;
  1365                 }
  1366                 catch (InvalidOperationException ioe)
  1367                 {
  1368                     MessageBox.Show("This application cannot be updated. It is likely not a ClickOnce application. Error: " + ioe.Message);
  1369                     return;
  1370                 }
  1371 
  1372 				if (info.UpdateAvailable)
  1373 				{
  1374 					Boolean doUpdate = true;
  1375 
  1376 					if (!info.IsUpdateRequired)
  1377 					{
  1378 						DialogResult dr = MessageBox.Show("An update is available. Would you like to update the application now?", "Update Available", MessageBoxButtons.OKCancel);
  1379 						if (!(DialogResult.OK == dr))
  1380 						{
  1381 							doUpdate = false;
  1382 						}
  1383 					}
  1384 					else
  1385 					{
  1386 						// Display a message that the app MUST reboot. Display the minimum required version.
  1387 						MessageBox.Show("This application has detected a mandatory update from your current " +
  1388 							"version to version " + info.MinimumRequiredVersion.ToString() +
  1389 							". The application will now install the update and restart.",
  1390 							"Update Available", MessageBoxButtons.OK,
  1391 							MessageBoxIcon.Information);
  1392 					}
  1393 
  1394 					if (doUpdate)
  1395 					{
  1396 						try
  1397 						{
  1398 							ad.Update();
  1399 							MessageBox.Show("The application has been upgraded, and will now restart.");
  1400 							Application.Restart();
  1401 						}
  1402 						catch (DeploymentDownloadException dde)
  1403 						{
  1404 							MessageBox.Show("Cannot install the latest version of the application. \n\nPlease check your network connection, or try again later. Error: " + dde);
  1405 							return;
  1406 						}
  1407 					}
  1408 				}
  1409 				else
  1410 				{
  1411 					MessageBox.Show("You are already running the latest version.", "Application up-to-date");
  1412 				}
  1413             }
  1414         }
  1415 
  1416 		private void checkBoxAutoStart_CheckedChanged(object sender, EventArgs e)
  1417 		{
  1418 			iStartupManager.Startup = checkBoxAutoStart.Checked;
  1419 		}
  1420     }
  1421 
  1422     /// <summary>
  1423     /// A UI thread copy of a client relevant data.
  1424     /// Keeping this copy in the UI thread helps us deal with threading issues.
  1425     /// </summary>
  1426     public class ClientData
  1427     {
  1428         public ClientData(string aSessionId, ICallback aCallback)
  1429         {
  1430             SessionId = aSessionId;
  1431             Name = "";
  1432             Fields = new List<DataField>();
  1433             Layout = new TableLayout(1, 2); //Default to one column and two rows
  1434             Callback = aCallback;
  1435         }
  1436 
  1437         public string SessionId { get; set; }
  1438         public string Name { get; set; }
  1439         public List<DataField> Fields { get; set; }
  1440         public TableLayout Layout { get; set; }
  1441         public ICallback Callback { get; set; }
  1442     }
  1443 }