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