Server/MainForm.cs
author StephaneLenclud
Sun, 08 Feb 2015 17:27:02 +0100
changeset 112 57b1c6507bd7
parent 110 31e63bd07dfa
child 113 0846e5112dd7
permissions -rw-r--r--
Adding 'Audio' tab.
Volume indicator of MDM16AA display now working.
Adding server side dependency on NAudio.
It was decided to have a server side dependency so that we could implement
new fields control such as:
* Volume indicator
* Mute indicator
* Spectrum visualizer
* Meter visualizer
* Fancy visualizer
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;
StephaneLenclud@112
    18
//NAudio
StephaneLenclud@112
    19
using NAudio.CoreAudioApi;
StephaneLenclud@112
    20
using NAudio.CoreAudioApi.Interfaces;
StephaneLenclud@112
    21
using System.Runtime.InteropServices;
sl@25
    22
//
sl@25
    23
using SharpDisplayClient;
sl@55
    24
using SharpDisplay;
sl@0
    25
sl@0
    26
namespace SharpDisplayManager
sl@0
    27
{
sl@58
    28
    //Types declarations
sl@58
    29
    public delegate uint ColorProcessingDelegate(int aX, int aY, uint aPixel);
sl@58
    30
    public delegate int CoordinateTranslationDelegate(System.Drawing.Bitmap aBmp, int aInt);
sl@62
    31
    //Delegates are used for our thread safe method
sl@62
    32
    public delegate void AddClientDelegate(string aSessionId, ICallback aCallback);
sl@62
    33
    public delegate void RemoveClientDelegate(string aSessionId);
sl@79
    34
    public delegate void SetFieldDelegate(string SessionId, DataField aField);
sl@79
    35
    public delegate void SetFieldsDelegate(string SessionId, System.Collections.Generic.IList<DataField> aFields);
sl@62
    36
    public delegate void SetLayoutDelegate(string SessionId, TableLayout aLayout);
sl@62
    37
    public delegate void SetClientNameDelegate(string aSessionId, string aName);
StephaneLenclud@112
    38
	public delegate void PlainUpdateDelegate();
sl@62
    39
sl@58
    40
sl@58
    41
    /// <summary>
sl@58
    42
    /// Our Display manager main form
sl@58
    43
    /// </summary>
StephaneLenclud@112
    44
	public partial class MainForm : Form, IMMNotificationClient
sl@0
    45
    {
sl@2
    46
        DateTime LastTickTime;
sl@3
    47
        Display iDisplay;
sl@14
    48
        System.Drawing.Bitmap iBmp;
sl@14
    49
        bool iCreateBitmap; //Workaround render to bitmap issues when minimized
sl@17
    50
        ServiceHost iServiceHost;
sl@65
    51
        // Our collection of clients sorted by session id.
sl@33
    52
        public Dictionary<string, ClientData> iClients;
sl@65
    53
        // The name of the client which informations are currently displayed.
sl@65
    54
        public string iCurrentClientSessionId;
sl@65
    55
        ClientData iCurrentClientData;
sl@65
    56
        //
sl@29
    57
        public bool iClosing;
sl@65
    58
        //Function pointer for pixel color filtering
sl@58
    59
        ColorProcessingDelegate iColorFx;
sl@65
    60
        //Function pointer for pixel X coordinate intercept
sl@58
    61
        CoordinateTranslationDelegate iScreenX;
sl@65
    62
        //Function pointer for pixel Y coordinate intercept
sl@58
    63
        CoordinateTranslationDelegate iScreenY;
StephaneLenclud@112
    64
		//NAudio
StephaneLenclud@112
    65
		private MMDeviceEnumerator iMultiMediaDeviceEnumerator;
StephaneLenclud@112
    66
		private MMDevice iMultiMediaDevice;
StephaneLenclud@112
    67
		
sl@2
    68
sl@94
    69
		/// <summary>
sl@94
    70
		/// Manage run when Windows startup option
sl@94
    71
		/// </summary>
sl@92
    72
		private StartupManager iStartupManager;
sl@92
    73
sl@94
    74
		/// <summary>
sl@94
    75
		/// System tray icon.
sl@94
    76
		/// </summary>
sl@94
    77
		private NotifyIconAdv iNotifyIcon;
sl@94
    78
sl@0
    79
        public MainForm()
sl@0
    80
        {
sl@65
    81
            iCurrentClientSessionId = "";
sl@65
    82
            iCurrentClientData = null;
sl@2
    83
            LastTickTime = DateTime.Now;
StephaneLenclud@104
    84
			//Instantiate our display and register for events notifications
sl@3
    85
            iDisplay = new Display();
StephaneLenclud@104
    86
			iDisplay.OnOpened += OnDisplayOpened;
StephaneLenclud@104
    87
			iDisplay.OnClosed += OnDisplayClosed;
StephaneLenclud@104
    88
			//
StephaneLenclud@104
    89
			iClients = new Dictionary<string, ClientData>();
sl@92
    90
			iStartupManager = new StartupManager();
sl@94
    91
			iNotifyIcon = new NotifyIconAdv();
sl@2
    92
StephaneLenclud@104
    93
			//Have our designer initialize its controls
sl@0
    94
            InitializeComponent();
StephaneLenclud@104
    95
StephaneLenclud@104
    96
			//Populate device types
StephaneLenclud@104
    97
			PopulateDeviceTypes();
StephaneLenclud@104
    98
StephaneLenclud@104
    99
			//Initial status update 
sl@7
   100
            UpdateStatus();
StephaneLenclud@104
   101
sl@14
   102
            //We have a bug when drawing minimized and reusing our bitmap
sl@14
   103
            iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14
   104
            iCreateBitmap = false;
sl@94
   105
StephaneLenclud@104
   106
			//Minimize our window if desired
sl@94
   107
			if (Properties.Settings.Default.StartMinimized)
sl@94
   108
			{
sl@94
   109
				WindowState = FormWindowState.Minimized;
sl@94
   110
			}
sl@94
   111
sl@0
   112
        }
sl@0
   113
sl@94
   114
		/// <summary>
StephaneLenclud@106
   115
		///
StephaneLenclud@106
   116
		/// </summary>
StephaneLenclud@106
   117
		/// <param name="sender"></param>
StephaneLenclud@106
   118
		/// <param name="e"></param>
StephaneLenclud@106
   119
        private void MainForm_Load(object sender, EventArgs e)
StephaneLenclud@106
   120
        {
StephaneLenclud@106
   121
			//Check if we are running a Click Once deployed application
StephaneLenclud@106
   122
			if (ApplicationDeployment.IsNetworkDeployed)
StephaneLenclud@106
   123
			{
StephaneLenclud@106
   124
				//This is a proper Click Once installation, fetch and show our version number
StephaneLenclud@106
   125
				this.Text += " - v" + ApplicationDeployment.CurrentDeployment.CurrentVersion;
StephaneLenclud@106
   126
			}
StephaneLenclud@106
   127
			else
StephaneLenclud@106
   128
			{
StephaneLenclud@106
   129
				//Not a proper Click Once installation, assuming development build then
StephaneLenclud@106
   130
				this.Text += " - development";
StephaneLenclud@106
   131
			}
StephaneLenclud@106
   132
StephaneLenclud@112
   133
			//NAudio
StephaneLenclud@112
   134
			iMultiMediaDeviceEnumerator = new MMDeviceEnumerator();
StephaneLenclud@112
   135
			iMultiMediaDeviceEnumerator.RegisterEndpointNotificationCallback(this);
StephaneLenclud@112
   136
			
StephaneLenclud@112
   137
			UpdateAudioDeviceAndMasterVolumeThreadSafe();
StephaneLenclud@112
   138
StephaneLenclud@106
   139
			//Setup notification icon
StephaneLenclud@106
   140
			SetupTrayIcon();
StephaneLenclud@106
   141
StephaneLenclud@106
   142
			// To make sure start up with minimize to tray works
StephaneLenclud@106
   143
			if (WindowState == FormWindowState.Minimized && Properties.Settings.Default.MinimizeToTray)
StephaneLenclud@106
   144
			{
StephaneLenclud@106
   145
				Visible = false;
StephaneLenclud@106
   146
			}
StephaneLenclud@106
   147
StephaneLenclud@106
   148
#if !DEBUG
StephaneLenclud@106
   149
			//When not debugging we want the screen to be empty until a client takes over
StephaneLenclud@106
   150
			ClearLayout();
StephaneLenclud@106
   151
#else
StephaneLenclud@106
   152
			//When developing we want at least one client for testing
StephaneLenclud@106
   153
			StartNewClient("abcdefghijklmnopqrst-0123456789","ABCDEFGHIJKLMNOPQRST-0123456789");
StephaneLenclud@106
   154
#endif
StephaneLenclud@106
   155
StephaneLenclud@106
   156
			//Open display connection on start-up if needed
StephaneLenclud@106
   157
			if (Properties.Settings.Default.DisplayConnectOnStartup)
StephaneLenclud@106
   158
			{
StephaneLenclud@106
   159
				OpenDisplayConnection();
StephaneLenclud@106
   160
			}
StephaneLenclud@106
   161
StephaneLenclud@106
   162
			//Start our server so that we can get client requests
StephaneLenclud@106
   163
			StartServer();
StephaneLenclud@106
   164
        }
StephaneLenclud@106
   165
StephaneLenclud@106
   166
		/// <summary>
StephaneLenclud@104
   167
		/// Called when our display is opened.
StephaneLenclud@104
   168
		/// </summary>
StephaneLenclud@104
   169
		/// <param name="aDisplay"></param>
StephaneLenclud@104
   170
		private void OnDisplayOpened(Display aDisplay)
StephaneLenclud@104
   171
		{
StephaneLenclud@105
   172
			//Set our screen size now that our display is connected
StephaneLenclud@105
   173
			//Our panelDisplay is the container of our tableLayoutPanel
StephaneLenclud@105
   174
			//tableLayoutPanel will resize itself to fit the client size of our panelDisplay
StephaneLenclud@105
   175
			//panelDisplay needs an extra 2 pixels for borders on each sides
StephaneLenclud@105
   176
			//tableLayoutPanel will eventually be the exact size of our display
StephaneLenclud@105
   177
			Size size = new Size(iDisplay.WidthInPixels() + 2, iDisplay.HeightInPixels() + 2);
StephaneLenclud@105
   178
			panelDisplay.Size = size;
StephaneLenclud@105
   179
StephaneLenclud@104
   180
			//Our display was just opened, update our UI
StephaneLenclud@104
   181
			UpdateStatus();
StephaneLenclud@104
   182
			//Initiate asynchronous request
StephaneLenclud@104
   183
			iDisplay.RequestFirmwareRevision();
StephaneLenclud@108
   184
StephaneLenclud@112
   185
			//
StephaneLenclud@112
   186
			UpdateMasterVolumeThreadSafe();
StephaneLenclud@112
   187
StephaneLenclud@108
   188
#if DEBUG
StephaneLenclud@108
   189
			//Testing icon in debug, no arm done if icon not supported
StephaneLenclud@109
   190
			//iDisplay.SetIconStatus(Display.TMiniDisplayIconType.EMiniDisplayIconRecording, 0, 1);
StephaneLenclud@112
   191
			//iDisplay.SetAllIconsStatus(2);
StephaneLenclud@108
   192
#endif
StephaneLenclud@108
   193
StephaneLenclud@104
   194
		}
StephaneLenclud@104
   195
StephaneLenclud@104
   196
		/// <summary>
StephaneLenclud@104
   197
		/// Called when our display is closed.
StephaneLenclud@104
   198
		/// </summary>
StephaneLenclud@104
   199
		/// <param name="aDisplay"></param>
StephaneLenclud@104
   200
		private void OnDisplayClosed(Display aDisplay)
StephaneLenclud@104
   201
		{
StephaneLenclud@104
   202
			//Our display was just closed, update our UI consequently
StephaneLenclud@104
   203
			UpdateStatus();
StephaneLenclud@104
   204
		}
StephaneLenclud@112
   205
		
StephaneLenclud@112
   206
        /// <summary>
StephaneLenclud@112
   207
        /// Receive volume change notification and reflect changes on our slider.
StephaneLenclud@112
   208
        /// </summary>
StephaneLenclud@112
   209
        /// <param name="data"></param>
StephaneLenclud@112
   210
        public void OnVolumeNotificationThreadSafe(AudioVolumeNotificationData data)
StephaneLenclud@112
   211
        {
StephaneLenclud@112
   212
			UpdateMasterVolumeThreadSafe();
StephaneLenclud@112
   213
        }
StephaneLenclud@112
   214
StephaneLenclud@112
   215
        /// <summary>
StephaneLenclud@112
   216
        /// Update master volume when user moves our slider.
StephaneLenclud@112
   217
        /// </summary>
StephaneLenclud@112
   218
        /// <param name="sender"></param>
StephaneLenclud@112
   219
        /// <param name="e"></param>
StephaneLenclud@112
   220
        private void trackBarMasterVolume_Scroll(object sender, EventArgs e)
StephaneLenclud@112
   221
        {
StephaneLenclud@112
   222
			iMultiMediaDevice.AudioEndpointVolume.MasterVolumeLevelScalar = trackBarMasterVolume.Value / 100.0f;
StephaneLenclud@112
   223
        }
StephaneLenclud@112
   224
StephaneLenclud@112
   225
        /// <summary>
StephaneLenclud@112
   226
        /// Device State Changed
StephaneLenclud@112
   227
        /// </summary>
StephaneLenclud@112
   228
        public void OnDeviceStateChanged([MarshalAs(UnmanagedType.LPWStr)] string deviceId, [MarshalAs(UnmanagedType.I4)] DeviceState newState){}
StephaneLenclud@112
   229
StephaneLenclud@112
   230
        /// <summary>
StephaneLenclud@112
   231
        /// Device Added
StephaneLenclud@112
   232
        /// </summary>
StephaneLenclud@112
   233
        public void OnDeviceAdded([MarshalAs(UnmanagedType.LPWStr)] string pwstrDeviceId) { }
StephaneLenclud@112
   234
StephaneLenclud@112
   235
        /// <summary>
StephaneLenclud@112
   236
        /// Device Removed
StephaneLenclud@112
   237
        /// </summary>
StephaneLenclud@112
   238
        public void OnDeviceRemoved([MarshalAs(UnmanagedType.LPWStr)] string deviceId) { }
StephaneLenclud@112
   239
StephaneLenclud@112
   240
        /// <summary>
StephaneLenclud@112
   241
        /// Default Device Changed
StephaneLenclud@112
   242
        /// </summary>
StephaneLenclud@112
   243
        public void OnDefaultDeviceChanged(DataFlow flow, Role role, [MarshalAs(UnmanagedType.LPWStr)] string defaultDeviceId)
StephaneLenclud@112
   244
        {
StephaneLenclud@112
   245
            if (role == Role.Multimedia && flow == DataFlow.Render)
StephaneLenclud@112
   246
            {
StephaneLenclud@112
   247
                UpdateAudioDeviceAndMasterVolumeThreadSafe();
StephaneLenclud@112
   248
            }
StephaneLenclud@112
   249
        }
StephaneLenclud@112
   250
StephaneLenclud@112
   251
        /// <summary>
StephaneLenclud@112
   252
        /// Property Value Changed
StephaneLenclud@112
   253
        /// </summary>
StephaneLenclud@112
   254
        /// <param name="pwstrDeviceId"></param>
StephaneLenclud@112
   255
        /// <param name="key"></param>
StephaneLenclud@112
   256
        public void OnPropertyValueChanged([MarshalAs(UnmanagedType.LPWStr)] string pwstrDeviceId, PropertyKey key){}
StephaneLenclud@112
   257
StephaneLenclud@112
   258
StephaneLenclud@112
   259
        
StephaneLenclud@112
   260
StephaneLenclud@112
   261
		/// <summary>
StephaneLenclud@112
   262
		/// 
StephaneLenclud@112
   263
		/// </summary>
StephaneLenclud@112
   264
		private void UpdateMasterVolumeThreadSafe()
StephaneLenclud@112
   265
		{
StephaneLenclud@112
   266
			if (this.InvokeRequired)
StephaneLenclud@112
   267
			{
StephaneLenclud@112
   268
				//Not in the proper thread, invoke ourselves
StephaneLenclud@112
   269
				PlainUpdateDelegate d = new PlainUpdateDelegate(UpdateMasterVolumeThreadSafe);
StephaneLenclud@112
   270
				this.Invoke(d, new object[] { });
StephaneLenclud@112
   271
				return;
StephaneLenclud@112
   272
			}
StephaneLenclud@112
   273
StephaneLenclud@112
   274
			float volumeLevelScalar = iMultiMediaDevice.AudioEndpointVolume.MasterVolumeLevelScalar;
StephaneLenclud@112
   275
			trackBarMasterVolume.Value = Convert.ToInt32(volumeLevelScalar * 100);
StephaneLenclud@112
   276
StephaneLenclud@112
   277
			//TODO: Check our display device too
StephaneLenclud@112
   278
			if (iDisplay.IsOpen())
StephaneLenclud@112
   279
			{
StephaneLenclud@112
   280
				int volumeIconCount = iDisplay.IconCount(Display.TMiniDisplayIconType.EMiniDisplayIconVolume);
StephaneLenclud@112
   281
				if (volumeIconCount > 0)
StephaneLenclud@112
   282
				{
StephaneLenclud@112
   283
					int currentVolume = Convert.ToInt32(volumeLevelScalar * volumeIconCount);
StephaneLenclud@112
   284
					for (int i = 0; i < volumeIconCount; i++)
StephaneLenclud@112
   285
					{
StephaneLenclud@112
   286
						if (i < currentVolume)
StephaneLenclud@112
   287
						{
StephaneLenclud@112
   288
							iDisplay.SetIconStatus(Display.TMiniDisplayIconType.EMiniDisplayIconVolume, i, 10);
StephaneLenclud@112
   289
						}
StephaneLenclud@112
   290
						else
StephaneLenclud@112
   291
						{
StephaneLenclud@112
   292
							iDisplay.SetIconStatus(Display.TMiniDisplayIconType.EMiniDisplayIconVolume, i, 0);
StephaneLenclud@112
   293
						}
StephaneLenclud@112
   294
					}
StephaneLenclud@112
   295
				}
StephaneLenclud@112
   296
			}
StephaneLenclud@112
   297
StephaneLenclud@112
   298
		}
StephaneLenclud@112
   299
StephaneLenclud@112
   300
        /// <summary>
StephaneLenclud@112
   301
        /// 
StephaneLenclud@112
   302
        /// </summary>
StephaneLenclud@112
   303
        private void UpdateAudioDeviceAndMasterVolumeThreadSafe()
StephaneLenclud@112
   304
        {
StephaneLenclud@112
   305
            if (this.InvokeRequired)
StephaneLenclud@112
   306
            {
StephaneLenclud@112
   307
                //Not in the proper thread, invoke ourselves
StephaneLenclud@112
   308
				PlainUpdateDelegate d = new PlainUpdateDelegate(UpdateAudioDeviceAndMasterVolumeThreadSafe);
StephaneLenclud@112
   309
                this.Invoke(d, new object[] { });
StephaneLenclud@112
   310
                return;
StephaneLenclud@112
   311
            }
StephaneLenclud@112
   312
            
StephaneLenclud@112
   313
            //We are in the correct thread just go ahead.
StephaneLenclud@112
   314
            try
StephaneLenclud@112
   315
            {                
StephaneLenclud@112
   316
                //Get our master volume            
StephaneLenclud@112
   317
				iMultiMediaDevice = iMultiMediaDeviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
StephaneLenclud@112
   318
                //Show our volume in our track bar
StephaneLenclud@112
   319
				UpdateMasterVolumeThreadSafe();
StephaneLenclud@112
   320
StephaneLenclud@112
   321
                //Register to get volume modifications
StephaneLenclud@112
   322
				iMultiMediaDevice.AudioEndpointVolume.OnVolumeNotification += OnVolumeNotificationThreadSafe;
StephaneLenclud@112
   323
                //
StephaneLenclud@112
   324
				trackBarMasterVolume.Enabled = true;
StephaneLenclud@112
   325
            }
StephaneLenclud@112
   326
            catch (Exception ex)
StephaneLenclud@112
   327
            {
StephaneLenclud@112
   328
                Debug.WriteLine("Exception thrown in UpdateAudioDeviceAndMasterVolume");
StephaneLenclud@112
   329
                Debug.WriteLine(ex.ToString());
StephaneLenclud@112
   330
                //Something went wrong S/PDIF device ca throw exception I guess
StephaneLenclud@112
   331
				trackBarMasterVolume.Enabled = false;
StephaneLenclud@112
   332
            }
StephaneLenclud@112
   333
        }
StephaneLenclud@104
   334
StephaneLenclud@104
   335
		/// <summary>
StephaneLenclud@104
   336
		/// 
StephaneLenclud@104
   337
		/// </summary>
StephaneLenclud@104
   338
		private void PopulateDeviceTypes()
StephaneLenclud@104
   339
		{
StephaneLenclud@104
   340
			int count = Display.TypeCount();
StephaneLenclud@104
   341
StephaneLenclud@106
   342
			for (int i = 0; i < count; i++)
StephaneLenclud@104
   343
			{
StephaneLenclud@104
   344
				comboBoxDisplayType.Items.Add(Display.TypeName((Display.TMiniDisplayType)i));
StephaneLenclud@106
   345
			}
StephaneLenclud@104
   346
		}
StephaneLenclud@104
   347
StephaneLenclud@104
   348
		/// <summary>
sl@99
   349
		///
sl@94
   350
		/// </summary>
sl@95
   351
		private void SetupTrayIcon()
sl@95
   352
		{
sl@95
   353
			iNotifyIcon.Icon = GetIcon("vfd.ico");
sl@95
   354
			iNotifyIcon.Text = "Sharp Display Manager";
sl@95
   355
			iNotifyIcon.Visible = true;
sl@95
   356
sl@95
   357
			//Double click toggles visibility - typically brings up the application
sl@95
   358
			iNotifyIcon.DoubleClick += delegate(object obj, EventArgs args)
sl@95
   359
			{
sl@95
   360
				SysTrayHideShow();
sl@95
   361
			};
sl@95
   362
sl@95
   363
			//Adding a context menu, useful to be able to exit the application
sl@95
   364
			ContextMenu contextMenu = new ContextMenu();
sl@95
   365
			//Context menu item to toggle visibility
sl@95
   366
			MenuItem hideShowItem = new MenuItem("Hide/Show");
sl@95
   367
			hideShowItem.Click += delegate(object obj, EventArgs args)
sl@95
   368
			{
sl@95
   369
				SysTrayHideShow();
sl@95
   370
			};
sl@95
   371
			contextMenu.MenuItems.Add(hideShowItem);
sl@95
   372
sl@95
   373
			//Context menu item separator
sl@95
   374
			contextMenu.MenuItems.Add(new MenuItem("-"));
sl@95
   375
sl@95
   376
			//Context menu exit item
sl@95
   377
			MenuItem exitItem = new MenuItem("Exit");
sl@95
   378
			exitItem.Click += delegate(object obj, EventArgs args)
sl@95
   379
			{
sl@95
   380
				Application.Exit();
sl@95
   381
			};
sl@95
   382
			contextMenu.MenuItems.Add(exitItem);
sl@95
   383
sl@95
   384
			iNotifyIcon.ContextMenu = contextMenu;
sl@95
   385
		}
sl@95
   386
sl@95
   387
		/// <summary>
sl@94
   388
		/// Access icons from embedded resources.
sl@94
   389
		/// </summary>
sl@94
   390
		/// <param name="name"></param>
sl@94
   391
		/// <returns></returns>
sl@94
   392
		public static Icon GetIcon(string name)
sl@94
   393
		{
sl@94
   394
			name = "SharpDisplayManager.Resources." + name;
sl@94
   395
sl@94
   396
			string[] names =
sl@94
   397
			  Assembly.GetExecutingAssembly().GetManifestResourceNames();
sl@94
   398
			for (int i = 0; i < names.Length; i++)
sl@94
   399
			{
sl@94
   400
				if (names[i].Replace('\\', '.') == name)
sl@94
   401
				{
sl@94
   402
					using (Stream stream = Assembly.GetExecutingAssembly().
sl@94
   403
					  GetManifestResourceStream(names[i]))
sl@94
   404
					{
sl@94
   405
						return new Icon(stream);
sl@94
   406
					}
sl@94
   407
				}
sl@94
   408
			}
sl@94
   409
sl@94
   410
			return null;
sl@94
   411
		}
sl@94
   412
sl@94
   413
sl@65
   414
        /// <summary>
sl@65
   415
        /// Set our current client.
sl@65
   416
        /// This will take care of applying our client layout and set data fields.
sl@65
   417
        /// </summary>
sl@65
   418
        /// <param name="aSessionId"></param>
sl@65
   419
        void SetCurrentClient(string aSessionId)
sl@57
   420
        {
sl@65
   421
            if (aSessionId == iCurrentClientSessionId)
sl@57
   422
            {
sl@65
   423
                //Given client is already the current one.
sl@65
   424
                //Don't bother changing anything then.
sl@65
   425
                return;
sl@65
   426
            }
sl@57
   427
sl@65
   428
            //Set current client ID.
sl@65
   429
            iCurrentClientSessionId = aSessionId;
sl@65
   430
            //Fetch and set current client data.
sl@65
   431
            iCurrentClientData = iClients[aSessionId];
sl@65
   432
            //Apply layout and set data fields.
sl@65
   433
            UpdateTableLayoutPanel(iCurrentClientData);
sl@57
   434
        }
sl@57
   435
sl@0
   436
        private void buttonFont_Click(object sender, EventArgs e)
sl@0
   437
        {
sl@0
   438
            //fontDialog.ShowColor = true;
sl@0
   439
            //fontDialog.ShowApply = true;
sl@0
   440
            fontDialog.ShowEffects = true;
sl@99
   441
            fontDialog.Font = cds.Font;
sl@28
   442
sl@28
   443
            fontDialog.FixedPitchOnly = checkBoxFixedPitchFontOnly.Checked;
sl@28
   444
sl@0
   445
            //fontDialog.ShowHelp = true;
sl@0
   446
sl@0
   447
            //fontDlg.MaxSize = 40;
sl@0
   448
            //fontDlg.MinSize = 22;
sl@0
   449
sl@0
   450
            //fontDialog.Parent = this;
sl@0
   451
            //fontDialog.StartPosition = FormStartPosition.CenterParent;
sl@0
   452
sl@0
   453
            //DlgBox.ShowDialog(fontDialog);
sl@0
   454
sl@0
   455
            //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
sl@0
   456
            if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
sl@0
   457
            {
sl@99
   458
                //Set the fonts to all our labels in our layout
sl@99
   459
                foreach (Control ctrl in tableLayoutPanel.Controls)
sl@99
   460
                {
sl@99
   461
                    if (ctrl is MarqueeLabel)
sl@99
   462
                    {
sl@99
   463
                        ((MarqueeLabel)ctrl).Font = fontDialog.Font;
sl@99
   464
                    }
sl@99
   465
                }
sl@0
   466
sl@99
   467
                //Save font settings
sl@48
   468
                cds.Font = fontDialog.Font;
sl@8
   469
                Properties.Settings.Default.Save();
sl@36
   470
                //
sl@37
   471
                CheckFontHeight();
sl@37
   472
            }
sl@37
   473
        }
sl@36
   474
sl@37
   475
        /// <summary>
sl@38
   476
        ///
sl@37
   477
        /// </summary>
sl@37
   478
        void CheckFontHeight()
sl@37
   479
        {
sl@54
   480
            //Show font height and width
sl@54
   481
            labelFontHeight.Text = "Font height: " + cds.Font.Height;
sl@54
   482
            float charWidth = IsFixedWidth(cds.Font);
sl@54
   483
            if (charWidth == 0.0f)
sl@54
   484
            {
sl@54
   485
                labelFontWidth.Visible = false;
sl@54
   486
            }
sl@54
   487
            else
sl@54
   488
            {
sl@54
   489
                labelFontWidth.Visible = true;
sl@54
   490
                labelFontWidth.Text = "Font width: " + charWidth;
sl@54
   491
            }
sl@54
   492
sl@70
   493
            MarqueeLabel label = null;
sl@68
   494
            //Get the first label control we can find
sl@68
   495
            foreach (Control ctrl in tableLayoutPanel.Controls)
sl@68
   496
            {
sl@68
   497
                if (ctrl is MarqueeLabel)
sl@68
   498
                {
sl@68
   499
                    label = (MarqueeLabel)ctrl;
sl@68
   500
                    break;
sl@68
   501
                }
sl@68
   502
            }
sl@68
   503
sl@54
   504
            //Now check font height and show a warning if needed.
sl@68
   505
            if (label != null && label.Font.Height > label.Height)
sl@37
   506
            {
sl@60
   507
                labelWarning.Text = "WARNING: Selected font is too height by " + (label.Font.Height - label.Height) + " pixels!";
sl@37
   508
                labelWarning.Visible = true;
sl@0
   509
            }
sl@37
   510
            else
sl@37
   511
            {
sl@37
   512
                labelWarning.Visible = false;
sl@37
   513
            }
sl@37
   514
sl@0
   515
        }
sl@0
   516
sl@0
   517
        private void buttonCapture_Click(object sender, EventArgs e)
sl@0
   518
        {
sl@0
   519
            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height);
sl@0
   520
            tableLayoutPanel.DrawToBitmap(bmp, tableLayoutPanel.ClientRectangle);
sl@14
   521
            //Bitmap bmpToSave = new Bitmap(bmp);
sl@14
   522
            bmp.Save("D:\\capture.png");
sl@14
   523
sl@60
   524
            ((MarqueeLabel)tableLayoutPanel.Controls[0]).Text = "Captured";
sl@17
   525
sl@14
   526
            /*
sl@14
   527
            string outputFileName = "d:\\capture.png";
sl@14
   528
            using (MemoryStream memory = new MemoryStream())
sl@14
   529
            {
sl@14
   530
                using (FileStream fs = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
sl@14
   531
                {
sl@14
   532
                    bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
sl@14
   533
                    byte[] bytes = memory.ToArray();
sl@14
   534
                    fs.Write(bytes, 0, bytes.Length);
sl@14
   535
                }
sl@14
   536
            }
sl@14
   537
             */
sl@14
   538
sl@0
   539
        }
sl@2
   540
sl@12
   541
        private void CheckForRequestResults()
sl@12
   542
        {
sl@12
   543
            if (iDisplay.IsRequestPending())
sl@12
   544
            {
sl@12
   545
                switch (iDisplay.AttemptRequestCompletion())
sl@12
   546
                {
sl@51
   547
                    case Display.TMiniDisplayRequest.EMiniDisplayRequestFirmwareRevision:
sl@51
   548
                        toolStripStatusLabelConnect.Text += " v" + iDisplay.FirmwareRevision();
sl@51
   549
                        //Issue next request then
sl@51
   550
                        iDisplay.RequestPowerSupplyStatus();
sl@51
   551
                        break;
sl@51
   552
sl@12
   553
                    case Display.TMiniDisplayRequest.EMiniDisplayRequestPowerSupplyStatus:
sl@12
   554
                        if (iDisplay.PowerSupplyStatus())
sl@12
   555
                        {
sl@12
   556
                            toolStripStatusLabelPower.Text = "ON";
sl@12
   557
                        }
sl@12
   558
                        else
sl@12
   559
                        {
sl@12
   560
                            toolStripStatusLabelPower.Text = "OFF";
sl@12
   561
                        }
sl@12
   562
                        //Issue next request then
sl@12
   563
                        iDisplay.RequestDeviceId();
sl@12
   564
                        break;
sl@12
   565
sl@12
   566
                    case Display.TMiniDisplayRequest.EMiniDisplayRequestDeviceId:
sl@12
   567
                        toolStripStatusLabelConnect.Text += " - " + iDisplay.DeviceId();
sl@12
   568
                        //No more request to issue
sl@12
   569
                        break;
sl@12
   570
                }
sl@12
   571
            }
sl@12
   572
        }
sl@12
   573
sl@58
   574
        public static uint ColorWhiteIsOn(int aX, int aY, uint aPixel)
sl@58
   575
        {
sl@58
   576
            if ((aPixel & 0x00FFFFFF) == 0x00FFFFFF)
sl@58
   577
            {
sl@58
   578
                return 0xFFFFFFFF;
sl@58
   579
            }
sl@58
   580
            return 0x00000000;
sl@58
   581
        }
sl@16
   582
sl@58
   583
        public static uint ColorUntouched(int aX, int aY, uint aPixel)
sl@57
   584
        {
sl@57
   585
            return aPixel;
sl@57
   586
        }
sl@57
   587
sl@58
   588
        public static uint ColorInversed(int aX, int aY, uint aPixel)
sl@57
   589
        {
sl@57
   590
            return ~aPixel;
sl@57
   591
        }
sl@57
   592
sl@58
   593
        public static uint ColorChessboard(int aX, int aY, uint aPixel)
sl@58
   594
        {
sl@58
   595
            if ((aX % 2 == 0) && (aY % 2 == 0))
sl@58
   596
            {
sl@58
   597
                return ~aPixel;
sl@58
   598
            }
sl@58
   599
            else if ((aX % 2 != 0) && (aY % 2 != 0))
sl@58
   600
            {
sl@58
   601
                return ~aPixel;
sl@58
   602
            }
sl@58
   603
            return 0x00000000;
sl@58
   604
        }
sl@58
   605
sl@16
   606
sl@16
   607
        public static int ScreenReversedX(System.Drawing.Bitmap aBmp, int aX)
sl@16
   608
        {
sl@16
   609
            return aBmp.Width - aX - 1;
sl@16
   610
        }
sl@16
   611
sl@16
   612
        public int ScreenReversedY(System.Drawing.Bitmap aBmp, int aY)
sl@16
   613
        {
sl@16
   614
            return iBmp.Height - aY - 1;
sl@16
   615
        }
sl@16
   616
sl@16
   617
        public int ScreenX(System.Drawing.Bitmap aBmp, int aX)
sl@16
   618
        {
sl@16
   619
            return aX;
sl@16
   620
        }
sl@16
   621
sl@16
   622
        public int ScreenY(System.Drawing.Bitmap aBmp, int aY)
sl@16
   623
        {
sl@16
   624
            return aY;
sl@16
   625
        }
sl@16
   626
sl@58
   627
        /// <summary>
sl@58
   628
        /// Select proper pixel delegates according to our current settings.
sl@58
   629
        /// </summary>
sl@58
   630
        private void SetupPixelDelegates()
sl@58
   631
        {
sl@59
   632
            //Select our pixel processing routine
sl@58
   633
            if (cds.InverseColors)
sl@58
   634
            {
sl@58
   635
                //iColorFx = ColorChessboard;
sl@58
   636
                iColorFx = ColorInversed;
sl@58
   637
            }
sl@58
   638
            else
sl@58
   639
            {
sl@58
   640
                iColorFx = ColorWhiteIsOn;
sl@58
   641
            }
sl@58
   642
sl@58
   643
            //Select proper coordinate translation functions
sl@58
   644
            //We used delegate/function pointer to support reverse screen without doing an extra test on each pixels
sl@58
   645
            if (cds.ReverseScreen)
sl@58
   646
            {
sl@58
   647
                iScreenX = ScreenReversedX;
sl@58
   648
                iScreenY = ScreenReversedY;
sl@58
   649
            }
sl@58
   650
            else
sl@58
   651
            {
sl@58
   652
                iScreenX = ScreenX;
sl@58
   653
                iScreenY = ScreenY;
sl@58
   654
            }
sl@58
   655
sl@58
   656
        }
sl@16
   657
sl@16
   658
        //This is our timer tick responsible to perform our render
sl@2
   659
        private void timer_Tick(object sender, EventArgs e)
sl@14
   660
        {
sl@2
   661
            //Update our animations
sl@2
   662
            DateTime NewTickTime = DateTime.Now;
sl@2
   663
sl@60
   664
            //Update animation for all our marquees
sl@68
   665
            foreach (Control ctrl in tableLayoutPanel.Controls)
sl@60
   666
            {
sl@68
   667
                if (ctrl is MarqueeLabel)
sl@68
   668
                {
sl@68
   669
                    ((MarqueeLabel)ctrl).UpdateAnimation(LastTickTime, NewTickTime);
sl@68
   670
                }
sl@60
   671
            }
sl@60
   672
sl@2
   673
sl@4
   674
            //Update our display
sl@4
   675
            if (iDisplay.IsOpen())
sl@4
   676
            {
sl@12
   677
                CheckForRequestResults();
sl@12
   678
sl@22
   679
                //Draw to bitmap
sl@14
   680
                if (iCreateBitmap)
sl@14
   681
                {
sl@14
   682
                    iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14
   683
                }
sl@14
   684
                tableLayoutPanel.DrawToBitmap(iBmp, tableLayoutPanel.ClientRectangle);
sl@14
   685
                //iBmp.Save("D:\\capture.png");
sl@16
   686
sl@7
   687
                //Send it to our display
sl@14
   688
                for (int i = 0; i < iBmp.Width; i++)
sl@4
   689
                {
sl@14
   690
                    for (int j = 0; j < iBmp.Height; j++)
sl@4
   691
                    {
sl@4
   692
                        unchecked
sl@4
   693
                        {
sl@58
   694
                            //Get our processed pixel coordinates
sl@58
   695
                            int x = iScreenX(iBmp, i);
sl@58
   696
                            int y = iScreenY(iBmp, j);
sl@58
   697
                            //Get pixel color
sl@14
   698
                            uint color = (uint)iBmp.GetPixel(i, j).ToArgb();
sl@57
   699
                            //Apply color effects
sl@58
   700
                            color = iColorFx(x,y,color);
sl@58
   701
                            //Now set our pixel
sl@58
   702
                            iDisplay.SetPixel(x, y, color);
sl@4
   703
                        }
sl@4
   704
                    }
sl@4
   705
                }
sl@4
   706
sl@4
   707
                iDisplay.SwapBuffers();
sl@4
   708
sl@4
   709
            }
sl@8
   710
sl@8
   711
            //Compute instant FPS
sl@47
   712
            toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " / " + (1000/timer.Interval).ToString() + " FPS";
sl@8
   713
sl@8
   714
            LastTickTime = NewTickTime;
sl@8
   715
sl@2
   716
        }
sl@3
   717
StephaneLenclud@103
   718
		/// <summary>
StephaneLenclud@103
   719
		/// Attempt to establish connection with our display hardware.
StephaneLenclud@103
   720
		/// </summary>
sl@46
   721
        private void OpenDisplayConnection()
sl@3
   722
        {
sl@46
   723
            CloseDisplayConnection();
sl@46
   724
StephaneLenclud@104
   725
            if (!iDisplay.Open((Display.TMiniDisplayType)cds.DisplayType))
StephaneLenclud@104
   726
            {   
StephaneLenclud@104
   727
				UpdateStatus();               
StephaneLenclud@104
   728
				toolStripStatusLabelConnect.Text = "Connection error";
sl@7
   729
            }
sl@46
   730
        }
sl@7
   731
sl@46
   732
        private void CloseDisplayConnection()
sl@46
   733
        {
StephaneLenclud@104
   734
			//Status will be updated upon receiving the closed event
sl@46
   735
            iDisplay.Close();
sl@46
   736
        }
sl@46
   737
sl@46
   738
        private void buttonOpen_Click(object sender, EventArgs e)
sl@46
   739
        {
sl@46
   740
            OpenDisplayConnection();
sl@3
   741
        }
sl@3
   742
sl@3
   743
        private void buttonClose_Click(object sender, EventArgs e)
sl@3
   744
        {
sl@46
   745
            CloseDisplayConnection();
sl@3
   746
        }
sl@3
   747
sl@3
   748
        private void buttonClear_Click(object sender, EventArgs e)
sl@3
   749
        {
sl@3
   750
            iDisplay.Clear();
sl@3
   751
            iDisplay.SwapBuffers();
sl@3
   752
        }
sl@3
   753
sl@3
   754
        private void buttonFill_Click(object sender, EventArgs e)
sl@3
   755
        {
sl@3
   756
            iDisplay.Fill();
sl@3
   757
            iDisplay.SwapBuffers();
sl@3
   758
        }
sl@3
   759
sl@3
   760
        private void trackBarBrightness_Scroll(object sender, EventArgs e)
sl@3
   761
        {
sl@48
   762
            cds.Brightness = trackBarBrightness.Value;
sl@9
   763
            Properties.Settings.Default.Save();
sl@3
   764
            iDisplay.SetBrightness(trackBarBrightness.Value);
sl@9
   765
sl@3
   766
        }
sl@7
   767
sl@48
   768
sl@48
   769
        /// <summary>
sl@48
   770
        /// CDS stands for Current Display Settings
sl@48
   771
        /// </summary>
sl@50
   772
        private DisplaySettings cds
sl@48
   773
        {
sl@48
   774
            get
sl@48
   775
            {
sl@65
   776
                DisplaysSettings settings = Properties.Settings.Default.DisplaysSettings;
sl@51
   777
                if (settings == null)
sl@51
   778
                {
sl@51
   779
                    settings = new DisplaysSettings();
sl@51
   780
                    settings.Init();
sl@65
   781
                    Properties.Settings.Default.DisplaysSettings = settings;
sl@51
   782
                }
sl@48
   783
sl@48
   784
                //Make sure all our settings have been created
sl@48
   785
                while (settings.Displays.Count <= Properties.Settings.Default.CurrentDisplayIndex)
sl@48
   786
                {
sl@50
   787
                    settings.Displays.Add(new DisplaySettings());
sl@48
   788
                }
sl@48
   789
sl@50
   790
                DisplaySettings displaySettings = settings.Displays[Properties.Settings.Default.CurrentDisplayIndex];
sl@48
   791
                return displaySettings;
sl@48
   792
            }
sl@48
   793
        }
sl@48
   794
sl@54
   795
        /// <summary>
sl@54
   796
        /// Check if the given font has a fixed character pitch.
sl@54
   797
        /// </summary>
sl@54
   798
        /// <param name="ft"></param>
sl@54
   799
        /// <returns>0.0f if this is not a monospace font, otherwise returns the character width.</returns>
sl@54
   800
        public float IsFixedWidth(Font ft)
sl@54
   801
        {
sl@54
   802
            Graphics g = CreateGraphics();
sl@54
   803
            char[] charSizes = new char[] { 'i', 'a', 'Z', '%', '#', 'a', 'B', 'l', 'm', ',', '.' };
sl@54
   804
            float charWidth = g.MeasureString("I", ft, Int32.MaxValue, StringFormat.GenericTypographic).Width;
sl@54
   805
sl@54
   806
            bool fixedWidth = true;
sl@54
   807
sl@54
   808
            foreach (char c in charSizes)
sl@54
   809
                if (g.MeasureString(c.ToString(), ft, Int32.MaxValue, StringFormat.GenericTypographic).Width != charWidth)
sl@54
   810
                    fixedWidth = false;
sl@54
   811
sl@54
   812
            if (fixedWidth)
sl@54
   813
            {
sl@54
   814
                return charWidth;
sl@54
   815
            }
sl@54
   816
sl@54
   817
            return 0.0f;
sl@54
   818
        }
sl@54
   819
StephaneLenclud@103
   820
		/// <summary>
StephaneLenclud@103
   821
		/// Synchronize UI with settings
StephaneLenclud@103
   822
		/// </summary>
sl@7
   823
        private void UpdateStatus()
StephaneLenclud@103
   824
        {            
sl@48
   825
            //Load settings
sl@54
   826
            checkBoxShowBorders.Checked = cds.ShowBorders;
sl@54
   827
            tableLayoutPanel.CellBorderStyle = (cds.ShowBorders ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
sl@60
   828
sl@60
   829
            //Set the proper font to each of our labels
sl@60
   830
            foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
sl@60
   831
            {
sl@60
   832
                ctrl.Font = cds.Font;
sl@60
   833
            }
sl@60
   834
sl@54
   835
            CheckFontHeight();
sl@96
   836
			//Check if "run on Windows startup" is enabled
sl@96
   837
			checkBoxAutoStart.Checked = iStartupManager.Startup;
sl@96
   838
			//
sl@48
   839
            checkBoxConnectOnStartup.Checked = Properties.Settings.Default.DisplayConnectOnStartup;
sl@94
   840
			checkBoxMinimizeToTray.Checked = Properties.Settings.Default.MinimizeToTray;
sl@94
   841
			checkBoxStartMinimized.Checked = Properties.Settings.Default.StartMinimized;
sl@48
   842
            checkBoxReverseScreen.Checked = cds.ReverseScreen;
sl@57
   843
            checkBoxInverseColors.Checked = cds.InverseColors;
sl@100
   844
            checkBoxScaleToFit.Checked = cds.ScaleToFit;
sl@100
   845
            maskedTextBoxMinFontSize.Enabled = cds.ScaleToFit;
sl@100
   846
            labelMinFontSize.Enabled = cds.ScaleToFit;
sl@100
   847
            maskedTextBoxMinFontSize.Text = cds.MinFontSize.ToString();
StephaneLenclud@106
   848
			maskedTextBoxScrollingSpeed.Text = cds.ScrollingSpeedInPixelsPerSecond.ToString();
sl@48
   849
            comboBoxDisplayType.SelectedIndex = cds.DisplayType;
sl@48
   850
            timer.Interval = cds.TimerInterval;
sl@48
   851
            maskedTextBoxTimerInterval.Text = cds.TimerInterval.ToString();
sl@100
   852
            textBoxScrollLoopSeparator.Text = cds.Separator;
sl@58
   853
            //
sl@58
   854
            SetupPixelDelegates();
sl@48
   855
sl@7
   856
            if (iDisplay.IsOpen())
sl@7
   857
            {
StephaneLenclud@103
   858
				//We have a display connection
StephaneLenclud@103
   859
				//Reflect that in our UI
StephaneLenclud@103
   860
StephaneLenclud@103
   861
				tableLayoutPanel.Enabled = true;
StephaneLenclud@105
   862
				panelDisplay.Enabled = true;
StephaneLenclud@103
   863
sl@48
   864
                //Only setup brightness if display is open
sl@48
   865
                trackBarBrightness.Minimum = iDisplay.MinBrightness();
sl@48
   866
                trackBarBrightness.Maximum = iDisplay.MaxBrightness();
StephaneLenclud@105
   867
				if (cds.Brightness < iDisplay.MinBrightness() || cds.Brightness > iDisplay.MaxBrightness())
StephaneLenclud@105
   868
				{
StephaneLenclud@105
   869
					//Brightness out of range, this can occur when using auto-detect
StephaneLenclud@105
   870
					//Use max brightness instead
StephaneLenclud@105
   871
					trackBarBrightness.Value = iDisplay.MaxBrightness();
StephaneLenclud@105
   872
					iDisplay.SetBrightness(iDisplay.MaxBrightness());
StephaneLenclud@105
   873
				}
StephaneLenclud@105
   874
				else
StephaneLenclud@105
   875
				{
StephaneLenclud@105
   876
					trackBarBrightness.Value = cds.Brightness;
StephaneLenclud@105
   877
					iDisplay.SetBrightness(cds.Brightness);
StephaneLenclud@105
   878
				}
StephaneLenclud@105
   879
StephaneLenclud@105
   880
				//Try compute the steps to something that makes sense
sl@48
   881
                trackBarBrightness.LargeChange = Math.Max(1, (iDisplay.MaxBrightness() - iDisplay.MinBrightness()) / 5);
sl@48
   882
                trackBarBrightness.SmallChange = 1;
StephaneLenclud@105
   883
                
sl@48
   884
                //
sl@7
   885
                buttonFill.Enabled = true;
sl@7
   886
                buttonClear.Enabled = true;
sl@7
   887
                buttonOpen.Enabled = false;
sl@7
   888
                buttonClose.Enabled = true;
sl@7
   889
                trackBarBrightness.Enabled = true;
sl@10
   890
                toolStripStatusLabelConnect.Text = "Connected - " + iDisplay.Vendor() + " - " + iDisplay.Product();
sl@10
   891
                //+ " - " + iDisplay.SerialNumber();
sl@52
   892
sl@52
   893
                if (iDisplay.SupportPowerOnOff())
sl@52
   894
                {
sl@52
   895
                    buttonPowerOn.Enabled = true;
sl@52
   896
                    buttonPowerOff.Enabled = true;
sl@52
   897
                }
sl@52
   898
                else
sl@52
   899
                {
sl@52
   900
                    buttonPowerOn.Enabled = false;
sl@52
   901
                    buttonPowerOff.Enabled = false;
sl@52
   902
                }
sl@53
   903
sl@53
   904
                if (iDisplay.SupportClock())
sl@53
   905
                {
sl@53
   906
                    buttonShowClock.Enabled = true;
sl@53
   907
                    buttonHideClock.Enabled = true;
sl@53
   908
                }
sl@53
   909
                else
sl@53
   910
                {
sl@53
   911
                    buttonShowClock.Enabled = false;
sl@53
   912
                    buttonHideClock.Enabled = false;
sl@53
   913
                }
sl@7
   914
            }
sl@7
   915
            else
sl@7
   916
            {
StephaneLenclud@103
   917
				//Display is connection not available
StephaneLenclud@103
   918
				//Reflect that in our UI
StephaneLenclud@103
   919
				tableLayoutPanel.Enabled = false;
StephaneLenclud@105
   920
				panelDisplay.Enabled = false;
sl@7
   921
                buttonFill.Enabled = false;
sl@7
   922
                buttonClear.Enabled = false;
sl@7
   923
                buttonOpen.Enabled = true;
sl@7
   924
                buttonClose.Enabled = false;
sl@7
   925
                trackBarBrightness.Enabled = false;
sl@52
   926
                buttonPowerOn.Enabled = false;
sl@52
   927
                buttonPowerOff.Enabled = false;
sl@53
   928
                buttonShowClock.Enabled = false;
sl@53
   929
                buttonHideClock.Enabled = false;
sl@9
   930
                toolStripStatusLabelConnect.Text = "Disconnected";
sl@48
   931
                toolStripStatusLabelPower.Text = "N/A";
sl@7
   932
            }
StephaneLenclud@106
   933
sl@7
   934
        }
sl@9
   935
sl@13
   936
sl@13
   937
sl@9
   938
        private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
sl@9
   939
        {
sl@16
   940
            //Save our show borders setting
sl@13
   941
            tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
sl@48
   942
            cds.ShowBorders = checkBoxShowBorders.Checked;
sl@9
   943
            Properties.Settings.Default.Save();
sl@57
   944
            CheckFontHeight();
sl@9
   945
        }
sl@13
   946
sl@13
   947
        private void checkBoxConnectOnStartup_CheckedChanged(object sender, EventArgs e)
sl@13
   948
        {
sl@16
   949
            //Save our connect on startup setting
sl@13
   950
            Properties.Settings.Default.DisplayConnectOnStartup = checkBoxConnectOnStartup.Checked;
sl@13
   951
            Properties.Settings.Default.Save();
sl@13
   952
        }
sl@13
   953
sl@94
   954
		private void checkBoxMinimizeToTray_CheckedChanged(object sender, EventArgs e)
sl@94
   955
		{
sl@94
   956
			//Save our "Minimize to tray" setting
sl@94
   957
			Properties.Settings.Default.MinimizeToTray = checkBoxMinimizeToTray.Checked;
sl@94
   958
			Properties.Settings.Default.Save();
sl@94
   959
sl@94
   960
		}
sl@94
   961
sl@94
   962
		private void checkBoxStartMinimized_CheckedChanged(object sender, EventArgs e)
sl@94
   963
		{
sl@94
   964
			//Save our "Start minimized" setting
sl@94
   965
			Properties.Settings.Default.StartMinimized = checkBoxStartMinimized.Checked;
sl@94
   966
			Properties.Settings.Default.Save();
sl@94
   967
		}
sl@94
   968
sl@94
   969
		private void checkBoxAutoStart_CheckedChanged(object sender, EventArgs e)
sl@94
   970
		{
sl@94
   971
			iStartupManager.Startup = checkBoxAutoStart.Checked;
sl@94
   972
		}
sl@94
   973
sl@94
   974
sl@16
   975
        private void checkBoxReverseScreen_CheckedChanged(object sender, EventArgs e)
sl@16
   976
        {
sl@16
   977
            //Save our reverse screen setting
sl@48
   978
            cds.ReverseScreen = checkBoxReverseScreen.Checked;
sl@16
   979
            Properties.Settings.Default.Save();
sl@58
   980
            SetupPixelDelegates();
sl@16
   981
        }
sl@16
   982
sl@57
   983
        private void checkBoxInverseColors_CheckedChanged(object sender, EventArgs e)
sl@57
   984
        {
sl@57
   985
            //Save our inverse colors setting
sl@57
   986
            cds.InverseColors = checkBoxInverseColors.Checked;
sl@57
   987
            Properties.Settings.Default.Save();
sl@58
   988
            SetupPixelDelegates();
sl@57
   989
        }
sl@57
   990
sl@100
   991
        private void checkBoxScaleToFit_CheckedChanged(object sender, EventArgs e)
sl@100
   992
        {
sl@100
   993
            //Save our scale to fit setting
sl@100
   994
            cds.ScaleToFit = checkBoxScaleToFit.Checked;
sl@100
   995
            Properties.Settings.Default.Save();
sl@100
   996
            //
sl@100
   997
            labelMinFontSize.Enabled = cds.ScaleToFit;
sl@100
   998
            maskedTextBoxMinFontSize.Enabled = cds.ScaleToFit;
sl@100
   999
        }
sl@100
  1000
sl@14
  1001
        private void MainForm_Resize(object sender, EventArgs e)
sl@14
  1002
        {
sl@14
  1003
            if (WindowState == FormWindowState.Minimized)
sl@14
  1004
            {
sl@14
  1005
                // Do some stuff
sl@14
  1006
                //iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14
  1007
                iCreateBitmap = true;
sl@14
  1008
            }
sl@14
  1009
        }
sl@14
  1010
sl@17
  1011
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
sl@17
  1012
        {
StephaneLenclud@105
  1013
			CloseDisplayConnection();
sl@17
  1014
            StopServer();
sl@32
  1015
            e.Cancel = iClosing;
sl@17
  1016
        }
sl@17
  1017
sl@17
  1018
        public void StartServer()
sl@17
  1019
        {
sl@17
  1020
            iServiceHost = new ServiceHost
sl@17
  1021
                (
sl@55
  1022
                    typeof(Session),
sl@20
  1023
                    new Uri[] { new Uri("net.tcp://localhost:8001/") }
sl@17
  1024
                );
sl@17
  1025
sl@55
  1026
            iServiceHost.AddServiceEndpoint(typeof(IService), new NetTcpBinding(SecurityMode.None, true), "DisplayService");
sl@17
  1027
            iServiceHost.Open();
sl@17
  1028
        }
sl@17
  1029
sl@17
  1030
        public void StopServer()
sl@17
  1031
        {
sl@32
  1032
            if (iClients.Count > 0 && !iClosing)
sl@29
  1033
            {
sl@29
  1034
                //Tell our clients
sl@32
  1035
                iClosing = true;
sl@29
  1036
                BroadcastCloseEvent();
sl@29
  1037
            }
sl@32
  1038
            else if (iClosing)
sl@32
  1039
            {
sl@32
  1040
                if (MessageBox.Show("Force exit?", "Waiting for clients...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
sl@32
  1041
                {
sl@32
  1042
                    iClosing = false; //We make sure we force close if asked twice
sl@32
  1043
                }
sl@32
  1044
            }
sl@32
  1045
            else
sl@36
  1046
            {
sl@32
  1047
                //We removed that as it often lags for some reason
sl@32
  1048
                //iServiceHost.Close();
sl@32
  1049
            }
sl@17
  1050
        }
sl@17
  1051
sl@21
  1052
        public void BroadcastCloseEvent()
sl@21
  1053
        {
sl@31
  1054
            Trace.TraceInformation("BroadcastCloseEvent - start");
sl@31
  1055
sl@21
  1056
            var inactiveClients = new List<string>();
sl@21
  1057
            foreach (var client in iClients)
sl@21
  1058
            {
sl@21
  1059
                //if (client.Key != eventData.ClientName)
sl@21
  1060
                {
sl@21
  1061
                    try
sl@21
  1062
                    {
sl@31
  1063
                        Trace.TraceInformation("BroadcastCloseEvent - " + client.Key);
sl@33
  1064
                        client.Value.Callback.OnCloseOrder(/*eventData*/);
sl@21
  1065
                    }
sl@21
  1066
                    catch (Exception ex)
sl@21
  1067
                    {
sl@21
  1068
                        inactiveClients.Add(client.Key);
sl@21
  1069
                    }
sl@21
  1070
                }
sl@21
  1071
            }
sl@21
  1072
sl@21
  1073
            if (inactiveClients.Count > 0)
sl@21
  1074
            {
sl@21
  1075
                foreach (var client in inactiveClients)
sl@21
  1076
                {
sl@21
  1077
                    iClients.Remove(client);
sl@30
  1078
                    Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(client, false)[0]);
sl@21
  1079
                }
sl@21
  1080
            }
sl@97
  1081
sl@97
  1082
			if (iClients.Count==0)
sl@97
  1083
			{
sl@97
  1084
				ClearLayout();
sl@97
  1085
			}
sl@21
  1086
        }
sl@21
  1087
sl@97
  1088
		/// <summary>
sl@97
  1089
		/// Just remove all our fields.
sl@97
  1090
		/// </summary>
sl@97
  1091
		private void ClearLayout()
sl@97
  1092
		{
sl@97
  1093
			tableLayoutPanel.Controls.Clear();
sl@97
  1094
			tableLayoutPanel.RowStyles.Clear();
sl@97
  1095
			tableLayoutPanel.ColumnStyles.Clear();
sl@97
  1096
		}
sl@97
  1097
StephaneLenclud@106
  1098
		/// <summary>
StephaneLenclud@106
  1099
		/// Just launch a demo client.
StephaneLenclud@106
  1100
		/// </summary>
StephaneLenclud@106
  1101
		private void StartNewClient(string aTopText = "", string aBottomText = "")
StephaneLenclud@106
  1102
		{
StephaneLenclud@106
  1103
			Thread clientThread = new Thread(SharpDisplayClient.Program.MainWithParams);
StephaneLenclud@106
  1104
			SharpDisplayClient.StartParams myParams = new SharpDisplayClient.StartParams(new Point(this.Right, this.Top),aTopText,aBottomText);
StephaneLenclud@106
  1105
			clientThread.Start(myParams);
StephaneLenclud@106
  1106
			BringToFront();
StephaneLenclud@106
  1107
		}
StephaneLenclud@106
  1108
sl@25
  1109
        private void buttonStartClient_Click(object sender, EventArgs e)
sl@25
  1110
        {
StephaneLenclud@106
  1111
			StartNewClient();
sl@25
  1112
        }
sl@25
  1113
sl@27
  1114
        private void buttonSuspend_Click(object sender, EventArgs e)
sl@27
  1115
        {
sl@52
  1116
            LastTickTime = DateTime.Now; //Reset timer to prevent jump
sl@27
  1117
            timer.Enabled = !timer.Enabled;
sl@27
  1118
            if (!timer.Enabled)
sl@27
  1119
            {
sl@52
  1120
                buttonSuspend.Text = "Run";
sl@27
  1121
            }
sl@27
  1122
            else
sl@27
  1123
            {
sl@27
  1124
                buttonSuspend.Text = "Pause";
sl@27
  1125
            }
sl@27
  1126
        }
sl@27
  1127
sl@29
  1128
        private void buttonCloseClients_Click(object sender, EventArgs e)
sl@29
  1129
        {
sl@29
  1130
            BroadcastCloseEvent();
sl@29
  1131
        }
sl@29
  1132
sl@30
  1133
        private void treeViewClients_AfterSelect(object sender, TreeViewEventArgs e)
sl@30
  1134
        {
sl@21
  1135
sl@30
  1136
        }
sl@30
  1137
sl@36
  1138
sl@30
  1139
        /// <summary>
sl@36
  1140
        ///
sl@30
  1141
        /// </summary>
sl@30
  1142
        /// <param name="aSessionId"></param>
sl@30
  1143
        /// <param name="aCallback"></param>
sl@55
  1144
        public void AddClientThreadSafe(string aSessionId, ICallback aCallback)
sl@30
  1145
        {
sl@33
  1146
            if (this.InvokeRequired)
sl@30
  1147
            {
sl@30
  1148
                //Not in the proper thread, invoke ourselves
sl@30
  1149
                AddClientDelegate d = new AddClientDelegate(AddClientThreadSafe);
sl@30
  1150
                this.Invoke(d, new object[] { aSessionId, aCallback });
sl@30
  1151
            }
sl@30
  1152
            else
sl@30
  1153
            {
sl@30
  1154
                //We are in the proper thread
sl@30
  1155
                //Add this session to our collection of clients
sl@33
  1156
                ClientData newClient = new ClientData(aSessionId, aCallback);
sl@33
  1157
                Program.iMainForm.iClients.Add(aSessionId, newClient);
sl@30
  1158
                //Add this session to our UI
sl@33
  1159
                UpdateClientTreeViewNode(newClient);
sl@30
  1160
            }
sl@30
  1161
        }
sl@30
  1162
sl@30
  1163
        /// <summary>
sl@36
  1164
        ///
sl@30
  1165
        /// </summary>
sl@30
  1166
        /// <param name="aSessionId"></param>
sl@30
  1167
        public void RemoveClientThreadSafe(string aSessionId)
sl@30
  1168
        {
sl@33
  1169
            if (this.InvokeRequired)
sl@30
  1170
            {
sl@30
  1171
                //Not in the proper thread, invoke ourselves
sl@30
  1172
                RemoveClientDelegate d = new RemoveClientDelegate(RemoveClientThreadSafe);
sl@30
  1173
                this.Invoke(d, new object[] { aSessionId });
sl@30
  1174
            }
sl@30
  1175
            else
sl@30
  1176
            {
sl@30
  1177
                //We are in the proper thread
sl@33
  1178
                //Remove this session from both client collection and UI tree view
sl@30
  1179
                if (Program.iMainForm.iClients.Keys.Contains(aSessionId))
sl@30
  1180
                {
sl@30
  1181
                    Program.iMainForm.iClients.Remove(aSessionId);
sl@30
  1182
                    Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(aSessionId, false)[0]);
sl@32
  1183
                }
sl@32
  1184
sl@97
  1185
				if (iClients.Count == 0)
sl@97
  1186
				{
sl@97
  1187
					//Clear our screen when last client disconnects
sl@97
  1188
					ClearLayout();
sl@97
  1189
sl@97
  1190
					if (iClosing)
sl@97
  1191
					{
sl@97
  1192
						//We were closing our form
sl@97
  1193
						//All clients are now closed
sl@97
  1194
						//Just resume our close operation
sl@97
  1195
						iClosing = false;
sl@97
  1196
						Close();
sl@97
  1197
					}
sl@97
  1198
				}
sl@30
  1199
            }
sl@30
  1200
        }
sl@30
  1201
sl@30
  1202
        /// <summary>
sl@36
  1203
        ///
sl@30
  1204
        /// </summary>
sl@62
  1205
        /// <param name="aSessionId"></param>
sl@72
  1206
        /// <param name="aLayout"></param>
sl@62
  1207
        public void SetClientLayoutThreadSafe(string aSessionId, TableLayout aLayout)
sl@62
  1208
        {
sl@62
  1209
            if (this.InvokeRequired)
sl@62
  1210
            {
sl@62
  1211
                //Not in the proper thread, invoke ourselves
sl@62
  1212
                SetLayoutDelegate d = new SetLayoutDelegate(SetClientLayoutThreadSafe);
sl@62
  1213
                this.Invoke(d, new object[] { aSessionId, aLayout });
sl@62
  1214
            }
sl@62
  1215
            else
sl@62
  1216
            {
sl@62
  1217
                ClientData client = iClients[aSessionId];
sl@62
  1218
                if (client != null)
sl@62
  1219
                {
sl@62
  1220
                    client.Layout = aLayout;
sl@65
  1221
                    UpdateTableLayoutPanel(client);
sl@62
  1222
                    //
sl@62
  1223
                    UpdateClientTreeViewNode(client);
sl@62
  1224
                }
sl@62
  1225
            }
sl@62
  1226
        }
sl@62
  1227
sl@62
  1228
        /// <summary>
sl@62
  1229
        ///
sl@62
  1230
        /// </summary>
sl@67
  1231
        /// <param name="aSessionId"></param>
sl@72
  1232
        /// <param name="aField"></param>
sl@75
  1233
        public void SetClientFieldThreadSafe(string aSessionId, DataField aField)
sl@30
  1234
        {
sl@33
  1235
            if (this.InvokeRequired)
sl@30
  1236
            {
sl@30
  1237
                //Not in the proper thread, invoke ourselves
sl@79
  1238
                SetFieldDelegate d = new SetFieldDelegate(SetClientFieldThreadSafe);
sl@72
  1239
                this.Invoke(d, new object[] { aSessionId, aField });
sl@30
  1240
            }
sl@30
  1241
            else
sl@30
  1242
            {
sl@75
  1243
                //We are in the proper thread
sl@75
  1244
                //Call the non-thread-safe variant
sl@75
  1245
                SetClientField(aSessionId, aField);
sl@75
  1246
            }
sl@75
  1247
        }
sl@75
  1248
sl@75
  1249
        /// <summary>
sl@79
  1250
        ///
sl@75
  1251
        /// </summary>
sl@75
  1252
        /// <param name="aSessionId"></param>
sl@75
  1253
        /// <param name="aField"></param>
sl@75
  1254
        private void SetClientField(string aSessionId, DataField aField)
sl@79
  1255
        {
sl@75
  1256
            SetCurrentClient(aSessionId);
sl@75
  1257
            ClientData client = iClients[aSessionId];
sl@75
  1258
            if (client != null)
sl@75
  1259
            {
sl@76
  1260
                bool somethingChanged = false;
sl@76
  1261
sl@75
  1262
                //Make sure all our fields are in place
sl@75
  1263
                while (client.Fields.Count < (aField.Index + 1))
sl@30
  1264
                {
sl@75
  1265
                    //Add a text field with proper index
sl@75
  1266
                    client.Fields.Add(new DataField(client.Fields.Count));
sl@76
  1267
                    somethingChanged = true;
sl@75
  1268
                }
sl@75
  1269
sl@75
  1270
                if (client.Fields[aField.Index].IsSameLayout(aField))
sl@75
  1271
                {
sl@75
  1272
                    //Same layout just update our field
sl@75
  1273
                    client.Fields[aField.Index] = aField;
sl@75
  1274
                    //
sl@75
  1275
                    if (aField.IsText && tableLayoutPanel.Controls[aField.Index] is MarqueeLabel)
sl@79
  1276
                    {
sl@75
  1277
                        //Text field control already in place, just change the text
sl@72
  1278
                        MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[aField.Index];
sl@76
  1279
                        somethingChanged = (label.Text != aField.Text || label.TextAlign != aField.Alignment);
sl@72
  1280
                        label.Text = aField.Text;
sl@72
  1281
                        label.TextAlign = aField.Alignment;
sl@68
  1282
                    }
sl@75
  1283
                    else if (aField.IsBitmap && tableLayoutPanel.Controls[aField.Index] is PictureBox)
sl@75
  1284
                    {
sl@76
  1285
                        somethingChanged = true; //TODO: Bitmap comp or should we leave that to clients?
sl@75
  1286
                        //Bitmap field control already in place just change the bitmap
sl@75
  1287
                        PictureBox pictureBox = (PictureBox)tableLayoutPanel.Controls[aField.Index];
sl@75
  1288
                        pictureBox.Image = aField.Bitmap;
sl@75
  1289
                    }
sl@68
  1290
                    else
sl@68
  1291
                    {
sl@76
  1292
                        somethingChanged = true;
sl@75
  1293
                        //The requested control in our layout it not of the correct type
sl@68
  1294
                        //Wrong control type, re-create them all
sl@68
  1295
                        UpdateTableLayoutPanel(iCurrentClientData);
sl@68
  1296
                    }
sl@30
  1297
                }
sl@75
  1298
                else
sl@75
  1299
                {
sl@76
  1300
                    somethingChanged = true;
sl@75
  1301
                    //Different layout, need to rebuild it
sl@75
  1302
                    client.Fields[aField.Index] = aField;
sl@75
  1303
                    UpdateTableLayoutPanel(iCurrentClientData);
sl@75
  1304
                }
sl@75
  1305
sl@75
  1306
                //
sl@76
  1307
                if (somethingChanged)
sl@76
  1308
                {
sl@76
  1309
                    UpdateClientTreeViewNode(client);
sl@76
  1310
                }
sl@30
  1311
            }
sl@30
  1312
        }
sl@30
  1313
sl@30
  1314
        /// <summary>
sl@36
  1315
        ///
sl@30
  1316
        /// </summary>
sl@30
  1317
        /// <param name="aTexts"></param>
sl@75
  1318
        public void SetClientFieldsThreadSafe(string aSessionId, System.Collections.Generic.IList<DataField> aFields)
sl@30
  1319
        {
sl@33
  1320
            if (this.InvokeRequired)
sl@30
  1321
            {
sl@30
  1322
                //Not in the proper thread, invoke ourselves
sl@75
  1323
                SetFieldsDelegate d = new SetFieldsDelegate(SetClientFieldsThreadSafe);
sl@72
  1324
                this.Invoke(d, new object[] { aSessionId, aFields });
sl@30
  1325
            }
sl@30
  1326
            else
sl@30
  1327
            {
sl@75
  1328
                //Put each our text fields in a label control
sl@75
  1329
                foreach (DataField field in aFields)
sl@30
  1330
                {
sl@75
  1331
                    SetClientField(aSessionId, field);
sl@30
  1332
                }
sl@30
  1333
            }
sl@32
  1334
        }
sl@30
  1335
sl@67
  1336
        /// <summary>
sl@67
  1337
        ///
sl@67
  1338
        /// </summary>
sl@67
  1339
        /// <param name="aSessionId"></param>
sl@32
  1340
        /// <param name="aName"></param>
sl@32
  1341
        public void SetClientNameThreadSafe(string aSessionId, string aName)
sl@32
  1342
        {
sl@32
  1343
            if (this.InvokeRequired)
sl@32
  1344
            {
sl@32
  1345
                //Not in the proper thread, invoke ourselves
sl@32
  1346
                SetClientNameDelegate d = new SetClientNameDelegate(SetClientNameThreadSafe);
sl@32
  1347
                this.Invoke(d, new object[] { aSessionId, aName });
sl@32
  1348
            }
sl@32
  1349
            else
sl@32
  1350
            {
sl@32
  1351
                //We are in the proper thread
sl@33
  1352
                //Get our client
sl@33
  1353
                ClientData client = iClients[aSessionId];
sl@33
  1354
                if (client != null)
sl@32
  1355
                {
sl@33
  1356
                    //Set its name
sl@33
  1357
                    client.Name = aName;
sl@33
  1358
                    //Update our tree-view
sl@33
  1359
                    UpdateClientTreeViewNode(client);
sl@33
  1360
                }
sl@33
  1361
            }
sl@33
  1362
        }
sl@33
  1363
sl@33
  1364
        /// <summary>
sl@36
  1365
        ///
sl@33
  1366
        /// </summary>
sl@33
  1367
        /// <param name="aClient"></param>
sl@33
  1368
        private void UpdateClientTreeViewNode(ClientData aClient)
sl@33
  1369
        {
sl@33
  1370
            if (aClient == null)
sl@33
  1371
            {
sl@33
  1372
                return;
sl@33
  1373
            }
sl@33
  1374
sl@33
  1375
            TreeNode node = null;
sl@33
  1376
            //Check that our client node already exists
sl@33
  1377
            //Get our client root node using its key which is our session ID
sl@33
  1378
            TreeNode[] nodes = treeViewClients.Nodes.Find(aClient.SessionId, false);
sl@33
  1379
            if (nodes.Count()>0)
sl@33
  1380
            {
sl@33
  1381
                //We already have a node for that client
sl@33
  1382
                node = nodes[0];
sl@33
  1383
                //Clear children as we are going to recreate them below
sl@33
  1384
                node.Nodes.Clear();
sl@33
  1385
            }
sl@33
  1386
            else
sl@33
  1387
            {
sl@33
  1388
                //Client node does not exists create a new one
sl@33
  1389
                treeViewClients.Nodes.Add(aClient.SessionId, aClient.SessionId);
sl@33
  1390
                node = treeViewClients.Nodes.Find(aClient.SessionId, false)[0];
sl@33
  1391
            }
sl@33
  1392
sl@33
  1393
            if (node != null)
sl@33
  1394
            {
sl@33
  1395
                //Change its name
sl@33
  1396
                if (aClient.Name != "")
sl@33
  1397
                {
sl@33
  1398
                    //We have a name, us it as text for our root node
sl@33
  1399
                    node.Text = aClient.Name;
sl@32
  1400
                    //Add a child with SessionId
sl@33
  1401
                    node.Nodes.Add(new TreeNode(aClient.SessionId));
sl@33
  1402
                }
sl@33
  1403
                else
sl@33
  1404
                {
sl@33
  1405
                    //No name, use session ID instead
sl@33
  1406
                    node.Text = aClient.SessionId;
sl@33
  1407
                }
sl@36
  1408
sl@67
  1409
                if (aClient.Fields.Count > 0)
sl@33
  1410
                {
sl@33
  1411
                    //Create root node for our texts
sl@70
  1412
                    TreeNode textsRoot = new TreeNode("Fields");
sl@33
  1413
                    node.Nodes.Add(textsRoot);
sl@33
  1414
                    //For each text add a new entry
sl@67
  1415
                    foreach (DataField field in aClient.Fields)
sl@33
  1416
                    {
sl@75
  1417
                        if (!field.IsBitmap)
sl@67
  1418
                        {
sl@72
  1419
                            DataField textField = (DataField)field;
sl@70
  1420
                            textsRoot.Nodes.Add(new TreeNode("[Text]" + textField.Text));
sl@67
  1421
                        }
sl@67
  1422
                        else
sl@67
  1423
                        {
sl@72
  1424
                            textsRoot.Nodes.Add(new TreeNode("[Bitmap]"));
sl@70
  1425
                        }
sl@33
  1426
                    }
sl@32
  1427
                }
sl@34
  1428
sl@34
  1429
                node.ExpandAll();
sl@32
  1430
            }
sl@30
  1431
        }
sl@17
  1432
sl@60
  1433
        /// <summary>
sl@60
  1434
        /// Update our table layout row styles to make sure each rows have similar height
sl@60
  1435
        /// </summary>
sl@60
  1436
        private void UpdateTableLayoutRowStyles()
sl@60
  1437
        {
sl@60
  1438
            foreach (RowStyle rowStyle in tableLayoutPanel.RowStyles)
sl@60
  1439
            {
sl@60
  1440
                rowStyle.SizeType = SizeType.Percent;
sl@60
  1441
                rowStyle.Height = 100 / tableLayoutPanel.RowCount;
sl@60
  1442
            }
sl@60
  1443
        }
sl@60
  1444
sl@70
  1445
        /// DEPRECATED
sl@60
  1446
        /// <summary>
sl@61
  1447
        /// Empty and recreate our table layout with the given number of columns and rows.
sl@61
  1448
        /// Sizes of rows and columns are uniform.
sl@60
  1449
        /// </summary>
sl@60
  1450
        /// <param name="aColumn"></param>
sl@60
  1451
        /// <param name="aRow"></param>
sl@62
  1452
        private void UpdateTableLayoutPanel(int aColumn, int aRow)
sl@60
  1453
        {
sl@61
  1454
            tableLayoutPanel.Controls.Clear();
sl@61
  1455
            tableLayoutPanel.RowStyles.Clear();
sl@61
  1456
            tableLayoutPanel.ColumnStyles.Clear();
sl@61
  1457
            tableLayoutPanel.RowCount = 0;
sl@61
  1458
            tableLayoutPanel.ColumnCount = 0;
sl@60
  1459
sl@61
  1460
            while (tableLayoutPanel.RowCount < aRow)
sl@61
  1461
            {
sl@61
  1462
                tableLayoutPanel.RowCount++;
sl@61
  1463
            }
sl@60
  1464
sl@61
  1465
            while (tableLayoutPanel.ColumnCount < aColumn)
sl@61
  1466
            {
sl@61
  1467
                tableLayoutPanel.ColumnCount++;
sl@61
  1468
            }
sl@61
  1469
sl@61
  1470
            for (int i = 0; i < tableLayoutPanel.ColumnCount; i++)
sl@61
  1471
            {
sl@61
  1472
                //Create our column styles
sl@61
  1473
                this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100 / tableLayoutPanel.ColumnCount));
sl@61
  1474
sl@61
  1475
                for (int j = 0; j < tableLayoutPanel.RowCount; j++)
sl@61
  1476
                {
sl@61
  1477
                    if (i == 0)
sl@61
  1478
                    {
sl@61
  1479
                        //Create our row styles
sl@61
  1480
                        this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100 / tableLayoutPanel.RowCount));
sl@61
  1481
                    }
sl@61
  1482
sl@61
  1483
                    MarqueeLabel control = new SharpDisplayManager.MarqueeLabel();
sl@61
  1484
                    control.AutoEllipsis = true;
sl@61
  1485
                    control.AutoSize = true;
sl@61
  1486
                    control.BackColor = System.Drawing.Color.Transparent;
sl@61
  1487
                    control.Dock = System.Windows.Forms.DockStyle.Fill;
sl@61
  1488
                    control.Location = new System.Drawing.Point(1, 1);
sl@61
  1489
                    control.Margin = new System.Windows.Forms.Padding(0);
sl@61
  1490
                    control.Name = "marqueeLabelCol" + aColumn + "Row" + aRow;
sl@61
  1491
                    control.OwnTimer = false;
sl@61
  1492
                    control.PixelsPerSecond = 64;
sl@100
  1493
                    control.Separator = cds.Separator;
sl@100
  1494
                    control.MinFontSize = cds.MinFontSize;
sl@100
  1495
                    control.ScaleToFit = cds.ScaleToFit;
sl@61
  1496
                    //control.Size = new System.Drawing.Size(254, 30);
sl@61
  1497
                    //control.TabIndex = 2;
sl@61
  1498
                    control.Font = cds.Font;
sl@61
  1499
                    control.Text = "ABCDEFGHIJKLMNOPQRST-0123456789";
sl@61
  1500
                    control.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
sl@61
  1501
                    control.UseCompatibleTextRendering = true;
sl@61
  1502
                    //
sl@61
  1503
                    tableLayoutPanel.Controls.Add(control, i, j);
sl@61
  1504
                }
sl@61
  1505
            }
sl@38
  1506
sl@62
  1507
            CheckFontHeight();
sl@38
  1508
        }
sl@38
  1509
sl@63
  1510
sl@63
  1511
        /// <summary>
sl@63
  1512
        /// Update our display table layout.
sl@63
  1513
        /// </summary>
sl@63
  1514
        /// <param name="aLayout"></param>
sl@65
  1515
        private void UpdateTableLayoutPanel(ClientData aClient)
sl@63
  1516
        {
StephaneLenclud@106
  1517
			if (aClient == null)
StephaneLenclud@106
  1518
			{
StephaneLenclud@106
  1519
				//Just drop it
StephaneLenclud@106
  1520
				return;
StephaneLenclud@106
  1521
			}
StephaneLenclud@106
  1522
StephaneLenclud@106
  1523
sl@65
  1524
            TableLayout layout = aClient.Layout;
sl@70
  1525
            int fieldCount = 0;
sl@70
  1526
sl@63
  1527
            tableLayoutPanel.Controls.Clear();
sl@63
  1528
            tableLayoutPanel.RowStyles.Clear();
sl@63
  1529
            tableLayoutPanel.ColumnStyles.Clear();
sl@63
  1530
            tableLayoutPanel.RowCount = 0;
sl@63
  1531
            tableLayoutPanel.ColumnCount = 0;
sl@63
  1532
sl@65
  1533
            while (tableLayoutPanel.RowCount < layout.Rows.Count)
sl@63
  1534
            {
sl@63
  1535
                tableLayoutPanel.RowCount++;
sl@63
  1536
            }
sl@63
  1537
sl@65
  1538
            while (tableLayoutPanel.ColumnCount < layout.Columns.Count)
sl@63
  1539
            {
sl@63
  1540
                tableLayoutPanel.ColumnCount++;
sl@63
  1541
            }
sl@63
  1542
sl@63
  1543
            for (int i = 0; i < tableLayoutPanel.ColumnCount; i++)
sl@63
  1544
            {
sl@63
  1545
                //Create our column styles
sl@65
  1546
                this.tableLayoutPanel.ColumnStyles.Add(layout.Columns[i]);
sl@63
  1547
sl@63
  1548
                for (int j = 0; j < tableLayoutPanel.RowCount; j++)
sl@63
  1549
                {
sl@63
  1550
                    if (i == 0)
sl@63
  1551
                    {
sl@63
  1552
                        //Create our row styles
sl@65
  1553
                        this.tableLayoutPanel.RowStyles.Add(layout.Rows[j]);
sl@63
  1554
                    }
sl@63
  1555
sl@70
  1556
                    //Check if we already have a control
sl@70
  1557
                    Control existingControl = tableLayoutPanel.GetControlFromPosition(i,j);
sl@70
  1558
                    if (existingControl!=null)
sl@70
  1559
                    {
sl@70
  1560
                        //We already have a control in that cell as a results of row/col spanning
sl@70
  1561
                        //Move on to next cell then
sl@70
  1562
                        continue;
sl@70
  1563
                    }
sl@70
  1564
sl@70
  1565
                    fieldCount++;
sl@70
  1566
sl@69
  1567
                    //Check if a client field already exists for that cell
sl@69
  1568
                    if (aClient.Fields.Count <= tableLayoutPanel.Controls.Count)
sl@65
  1569
                    {
sl@69
  1570
                        //No client field specified, create a text field by default
sl@72
  1571
                        aClient.Fields.Add(new DataField(aClient.Fields.Count));
sl@65
  1572
                    }
sl@68
  1573
sl@69
  1574
                    //Create a control corresponding to the field specified for that cell
sl@70
  1575
                    DataField field = aClient.Fields[tableLayoutPanel.Controls.Count];
sl@70
  1576
                    Control control = CreateControlForDataField(field);
sl@70
  1577
sl@69
  1578
                    //Add newly created control to our table layout at the specified row and column
sl@63
  1579
                    tableLayoutPanel.Controls.Add(control, i, j);
sl@70
  1580
                    //Make sure we specify row and column span for that new control
sl@70
  1581
                    tableLayoutPanel.SetRowSpan(control,field.RowSpan);
sl@70
  1582
                    tableLayoutPanel.SetColumnSpan(control, field.ColumnSpan);
sl@63
  1583
                }
sl@63
  1584
            }
sl@63
  1585
sl@70
  1586
            //
sl@70
  1587
            while (aClient.Fields.Count > fieldCount)
sl@70
  1588
            {
sl@70
  1589
                //We have too much fields for this layout
sl@70
  1590
                //Just discard them until we get there
sl@70
  1591
                aClient.Fields.RemoveAt(aClient.Fields.Count-1);
sl@70
  1592
            }
sl@70
  1593
sl@63
  1594
            CheckFontHeight();
sl@63
  1595
        }
sl@63
  1596
sl@68
  1597
        /// <summary>
sl@70
  1598
        /// Check our type of data field and create corresponding control
sl@68
  1599
        /// </summary>
sl@68
  1600
        /// <param name="aField"></param>
sl@69
  1601
        private Control CreateControlForDataField(DataField aField)
sl@68
  1602
        {
sl@68
  1603
            Control control=null;
sl@75
  1604
            if (!aField.IsBitmap)
sl@68
  1605
            {
sl@68
  1606
                MarqueeLabel label = new SharpDisplayManager.MarqueeLabel();
sl@68
  1607
                label.AutoEllipsis = true;
sl@68
  1608
                label.AutoSize = true;
sl@68
  1609
                label.BackColor = System.Drawing.Color.Transparent;
sl@68
  1610
                label.Dock = System.Windows.Forms.DockStyle.Fill;
sl@68
  1611
                label.Location = new System.Drawing.Point(1, 1);
sl@68
  1612
                label.Margin = new System.Windows.Forms.Padding(0);
sl@68
  1613
                label.Name = "marqueeLabel" + aField.Index;
sl@68
  1614
                label.OwnTimer = false;
StephaneLenclud@106
  1615
                label.PixelsPerSecond = cds.ScrollingSpeedInPixelsPerSecond;
sl@100
  1616
                label.Separator = cds.Separator;
sl@100
  1617
                label.MinFontSize = cds.MinFontSize;
sl@100
  1618
                label.ScaleToFit = cds.ScaleToFit;
sl@68
  1619
                //control.Size = new System.Drawing.Size(254, 30);
sl@68
  1620
                //control.TabIndex = 2;
sl@68
  1621
                label.Font = cds.Font;
sl@68
  1622
StephaneLenclud@106
  1623
				label.TextAlign = aField.Alignment;
sl@68
  1624
                label.UseCompatibleTextRendering = true;
sl@72
  1625
                label.Text = aField.Text;
sl@68
  1626
                //
sl@68
  1627
                control = label;
sl@68
  1628
            }
sl@72
  1629
            else
sl@68
  1630
            {
sl@68
  1631
                //Create picture box
sl@68
  1632
                PictureBox picture = new PictureBox();
sl@68
  1633
                picture.AutoSize = true;
sl@68
  1634
                picture.BackColor = System.Drawing.Color.Transparent;
sl@68
  1635
                picture.Dock = System.Windows.Forms.DockStyle.Fill;
sl@68
  1636
                picture.Location = new System.Drawing.Point(1, 1);
sl@68
  1637
                picture.Margin = new System.Windows.Forms.Padding(0);
sl@68
  1638
                picture.Name = "pictureBox" + aField;
sl@68
  1639
                //Set our image
sl@72
  1640
                picture.Image = aField.Bitmap;
sl@68
  1641
                //
sl@68
  1642
                control = picture;
sl@68
  1643
            }
sl@68
  1644
sl@69
  1645
            return control;
sl@68
  1646
        }
sl@68
  1647
StephaneLenclud@103
  1648
		/// <summary>
StephaneLenclud@103
  1649
		/// Called when the user selected a new display type.
StephaneLenclud@103
  1650
		/// </summary>
StephaneLenclud@103
  1651
		/// <param name="sender"></param>
StephaneLenclud@103
  1652
		/// <param name="e"></param>
sl@46
  1653
        private void comboBoxDisplayType_SelectedIndexChanged(object sender, EventArgs e)
sl@46
  1654
        {
StephaneLenclud@103
  1655
			//Store the selected display type in our settings
sl@48
  1656
            Properties.Settings.Default.CurrentDisplayIndex = comboBoxDisplayType.SelectedIndex;
sl@48
  1657
            cds.DisplayType = comboBoxDisplayType.SelectedIndex;
sl@46
  1658
            Properties.Settings.Default.Save();
StephaneLenclud@103
  1659
StephaneLenclud@103
  1660
			//Try re-opening the display connection if we were already connected.
StephaneLenclud@103
  1661
			//Otherwise just update our status to reflect display type change.
sl@51
  1662
            if (iDisplay.IsOpen())
sl@51
  1663
            {
sl@51
  1664
                OpenDisplayConnection();
sl@51
  1665
            }
sl@51
  1666
            else
sl@51
  1667
            {
sl@51
  1668
                UpdateStatus();
sl@51
  1669
            }
sl@46
  1670
        }
sl@46
  1671
sl@47
  1672
        private void maskedTextBoxTimerInterval_TextChanged(object sender, EventArgs e)
sl@47
  1673
        {
sl@47
  1674
            if (maskedTextBoxTimerInterval.Text != "")
sl@47
  1675
            {
sl@51
  1676
                int interval = Convert.ToInt32(maskedTextBoxTimerInterval.Text);
sl@51
  1677
sl@51
  1678
                if (interval > 0)
sl@51
  1679
                {
sl@51
  1680
                    timer.Interval = interval;
sl@51
  1681
                    cds.TimerInterval = timer.Interval;
sl@51
  1682
                    Properties.Settings.Default.Save();
sl@51
  1683
                }
sl@47
  1684
            }
sl@47
  1685
        }
sl@47
  1686
sl@100
  1687
        private void maskedTextBoxMinFontSize_TextChanged(object sender, EventArgs e)
sl@100
  1688
        {
sl@100
  1689
            if (maskedTextBoxMinFontSize.Text != "")
sl@100
  1690
            {
sl@100
  1691
                int minFontSize = Convert.ToInt32(maskedTextBoxMinFontSize.Text);
sl@100
  1692
sl@100
  1693
                if (minFontSize > 0)
sl@100
  1694
                {
sl@100
  1695
                    cds.MinFontSize = minFontSize;
sl@100
  1696
                    Properties.Settings.Default.Save();
StephaneLenclud@106
  1697
					//We need to recreate our layout for that change to take effect
StephaneLenclud@106
  1698
					UpdateTableLayoutPanel(iCurrentClientData);
sl@100
  1699
                }
sl@100
  1700
            }
sl@100
  1701
        }
sl@100
  1702
StephaneLenclud@106
  1703
StephaneLenclud@106
  1704
		private void maskedTextBoxScrollingSpeed_TextChanged(object sender, EventArgs e)
StephaneLenclud@106
  1705
		{
StephaneLenclud@106
  1706
			if (maskedTextBoxScrollingSpeed.Text != "")
StephaneLenclud@106
  1707
			{
StephaneLenclud@106
  1708
				int scrollingSpeed = Convert.ToInt32(maskedTextBoxScrollingSpeed.Text);
StephaneLenclud@106
  1709
StephaneLenclud@106
  1710
				if (scrollingSpeed > 0)
StephaneLenclud@106
  1711
				{
StephaneLenclud@106
  1712
					cds.ScrollingSpeedInPixelsPerSecond = scrollingSpeed;
StephaneLenclud@106
  1713
					Properties.Settings.Default.Save();
StephaneLenclud@106
  1714
					//We need to recreate our layout for that change to take effect
StephaneLenclud@106
  1715
					UpdateTableLayoutPanel(iCurrentClientData);
StephaneLenclud@106
  1716
				}
StephaneLenclud@106
  1717
			}
StephaneLenclud@106
  1718
		}
StephaneLenclud@106
  1719
sl@100
  1720
        private void textBoxScrollLoopSeparator_TextChanged(object sender, EventArgs e)
sl@100
  1721
        {
sl@100
  1722
            cds.Separator = textBoxScrollLoopSeparator.Text;
sl@100
  1723
            Properties.Settings.Default.Save();
StephaneLenclud@110
  1724
StephaneLenclud@110
  1725
			//Update our text fields
StephaneLenclud@110
  1726
			foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
StephaneLenclud@110
  1727
			{
StephaneLenclud@110
  1728
				ctrl.Separator = cds.Separator;
StephaneLenclud@110
  1729
			}
StephaneLenclud@110
  1730
sl@100
  1731
        }
sl@100
  1732
sl@52
  1733
        private void buttonPowerOn_Click(object sender, EventArgs e)
sl@52
  1734
        {
sl@52
  1735
            iDisplay.PowerOn();
sl@52
  1736
        }
sl@52
  1737
sl@52
  1738
        private void buttonPowerOff_Click(object sender, EventArgs e)
sl@52
  1739
        {
sl@52
  1740
            iDisplay.PowerOff();
sl@52
  1741
        }
sl@52
  1742
sl@53
  1743
        private void buttonShowClock_Click(object sender, EventArgs e)
sl@53
  1744
        {
sl@53
  1745
            iDisplay.ShowClock();
sl@53
  1746
        }
sl@53
  1747
sl@53
  1748
        private void buttonHideClock_Click(object sender, EventArgs e)
sl@53
  1749
        {
sl@53
  1750
            iDisplay.HideClock();
sl@53
  1751
        }
sl@88
  1752
sl@88
  1753
        private void buttonUpdate_Click(object sender, EventArgs e)
sl@88
  1754
        {
sl@88
  1755
            InstallUpdateSyncWithInfo();
sl@88
  1756
        }
sl@88
  1757
sl@88
  1758
sl@88
  1759
        private void InstallUpdateSyncWithInfo()
sl@88
  1760
        {
sl@88
  1761
            UpdateCheckInfo info = null;
sl@88
  1762
sl@88
  1763
            if (ApplicationDeployment.IsNetworkDeployed)
sl@88
  1764
            {
sl@88
  1765
                ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
sl@88
  1766
sl@88
  1767
                try
sl@88
  1768
                {
sl@88
  1769
                    info = ad.CheckForDetailedUpdate();
sl@88
  1770
sl@88
  1771
                }
sl@88
  1772
                catch (DeploymentDownloadException dde)
sl@88
  1773
                {
sl@88
  1774
                    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
  1775
                    return;
sl@88
  1776
                }
sl@88
  1777
                catch (InvalidDeploymentException ide)
sl@88
  1778
                {
sl@88
  1779
                    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
  1780
                    return;
sl@88
  1781
                }
sl@88
  1782
                catch (InvalidOperationException ioe)
sl@88
  1783
                {
sl@88
  1784
                    MessageBox.Show("This application cannot be updated. It is likely not a ClickOnce application. Error: " + ioe.Message);
sl@88
  1785
                    return;
sl@88
  1786
                }
sl@88
  1787
sl@90
  1788
				if (info.UpdateAvailable)
sl@90
  1789
				{
sl@90
  1790
					Boolean doUpdate = true;
sl@88
  1791
sl@90
  1792
					if (!info.IsUpdateRequired)
sl@90
  1793
					{
sl@90
  1794
						DialogResult dr = MessageBox.Show("An update is available. Would you like to update the application now?", "Update Available", MessageBoxButtons.OKCancel);
sl@90
  1795
						if (!(DialogResult.OK == dr))
sl@90
  1796
						{
sl@90
  1797
							doUpdate = false;
sl@90
  1798
						}
sl@90
  1799
					}
sl@90
  1800
					else
sl@90
  1801
					{
sl@90
  1802
						// Display a message that the app MUST reboot. Display the minimum required version.
sl@90
  1803
						MessageBox.Show("This application has detected a mandatory update from your current " +
sl@90
  1804
							"version to version " + info.MinimumRequiredVersion.ToString() +
sl@90
  1805
							". The application will now install the update and restart.",
sl@90
  1806
							"Update Available", MessageBoxButtons.OK,
sl@90
  1807
							MessageBoxIcon.Information);
sl@90
  1808
					}
sl@88
  1809
sl@90
  1810
					if (doUpdate)
sl@90
  1811
					{
sl@90
  1812
						try
sl@90
  1813
						{
sl@90
  1814
							ad.Update();
sl@90
  1815
							MessageBox.Show("The application has been upgraded, and will now restart.");
sl@90
  1816
							Application.Restart();
sl@90
  1817
						}
sl@90
  1818
						catch (DeploymentDownloadException dde)
sl@90
  1819
						{
sl@90
  1820
							MessageBox.Show("Cannot install the latest version of the application. \n\nPlease check your network connection, or try again later. Error: " + dde);
sl@90
  1821
							return;
sl@90
  1822
						}
sl@90
  1823
					}
sl@90
  1824
				}
sl@90
  1825
				else
sl@90
  1826
				{
sl@90
  1827
					MessageBox.Show("You are already running the latest version.", "Application up-to-date");
sl@90
  1828
				}
sl@88
  1829
            }
sl@88
  1830
        }
sl@92
  1831
sl@94
  1832
sl@94
  1833
		/// <summary>
sl@99
  1834
		/// Used to
sl@94
  1835
		/// </summary>
sl@94
  1836
		private void SysTrayHideShow()
sl@92
  1837
		{
sl@94
  1838
			Visible = !Visible;
sl@94
  1839
			if (Visible)
sl@94
  1840
			{
sl@94
  1841
				Activate();
sl@94
  1842
				WindowState = FormWindowState.Normal;
sl@94
  1843
			}
sl@92
  1844
		}
sl@94
  1845
sl@94
  1846
		/// <summary>
sl@94
  1847
		/// Use to handle minimize events.
sl@94
  1848
		/// </summary>
sl@94
  1849
		/// <param name="sender"></param>
sl@94
  1850
		/// <param name="e"></param>
sl@94
  1851
		private void MainForm_SizeChanged(object sender, EventArgs e)
sl@94
  1852
		{
sl@94
  1853
			if (WindowState == FormWindowState.Minimized && Properties.Settings.Default.MinimizeToTray)
sl@94
  1854
			{
sl@94
  1855
				if (Visible)
sl@94
  1856
				{
sl@94
  1857
					SysTrayHideShow();
sl@94
  1858
				}
sl@94
  1859
			}
sl@99
  1860
sl@94
  1861
		}
sl@94
  1862
StephaneLenclud@105
  1863
		/// <summary>
StephaneLenclud@105
  1864
		/// 
StephaneLenclud@105
  1865
		/// </summary>
StephaneLenclud@105
  1866
		/// <param name="sender"></param>
StephaneLenclud@105
  1867
		/// <param name="e"></param>
StephaneLenclud@105
  1868
		private void tableLayoutPanel_SizeChanged(object sender, EventArgs e)
StephaneLenclud@105
  1869
		{
StephaneLenclud@105
  1870
			//Our table layout size has changed which means our display size has changed.
StephaneLenclud@105
  1871
			//We need to re-create our bitmap.
StephaneLenclud@105
  1872
			iCreateBitmap = true;
StephaneLenclud@105
  1873
		}
sl@100
  1874
sl@0
  1875
    }
sl@34
  1876
sl@34
  1877
    /// <summary>
sl@34
  1878
    /// A UI thread copy of a client relevant data.
sl@34
  1879
    /// Keeping this copy in the UI thread helps us deal with threading issues.
sl@34
  1880
    /// </summary>
sl@34
  1881
    public class ClientData
sl@34
  1882
    {
sl@55
  1883
        public ClientData(string aSessionId, ICallback aCallback)
sl@34
  1884
        {
sl@34
  1885
            SessionId = aSessionId;
sl@34
  1886
            Name = "";
sl@67
  1887
            Fields = new List<DataField>();
sl@62
  1888
            Layout = new TableLayout(1, 2); //Default to one column and two rows
sl@34
  1889
            Callback = aCallback;
sl@34
  1890
        }
sl@34
  1891
sl@34
  1892
        public string SessionId { get; set; }
sl@34
  1893
        public string Name { get; set; }
sl@67
  1894
        public List<DataField> Fields { get; set; }
sl@62
  1895
        public TableLayout Layout { get; set; }
sl@55
  1896
        public ICallback Callback { get; set; }
sl@34
  1897
    }
sl@0
  1898
}