Server/MainForm.cs
author sl
Sat, 30 Aug 2014 18:45:06 +0200
changeset 46 0c0ee86760ea
parent 45 b5a0fa4770d3
child 47 c9e3d1389d06
permissions -rw-r--r--
Adding support for display type selection.
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@25
    16
//
sl@22
    17
using SharpDisplayInterface;
sl@25
    18
using SharpDisplayClient;
sl@14
    19
sl@0
    20
sl@0
    21
namespace SharpDisplayManager
sl@0
    22
{
sl@0
    23
    public partial class MainForm : Form
sl@0
    24
    {
sl@2
    25
        DateTime LastTickTime;
sl@3
    26
        Display iDisplay;
sl@14
    27
        System.Drawing.Bitmap iBmp;
sl@14
    28
        bool iCreateBitmap; //Workaround render to bitmap issues when minimized
sl@17
    29
        ServiceHost iServiceHost;
sl@21
    30
        /// <summary>
sl@21
    31
        /// Our collection of clients
sl@21
    32
        /// </summary>
sl@33
    33
        public Dictionary<string, ClientData> iClients;
sl@29
    34
        public bool iClosing;
sl@2
    35
sl@0
    36
        public MainForm()
sl@0
    37
        {
sl@2
    38
            LastTickTime = DateTime.Now;
sl@3
    39
            iDisplay = new Display();
sl@33
    40
            iClients = new Dictionary<string, ClientData>();
sl@2
    41
sl@0
    42
            InitializeComponent();
sl@7
    43
            UpdateStatus();
sl@13
    44
sl@8
    45
            //Load settings
sl@8
    46
            marqueeLabelTop.Font = Properties.Settings.Default.DisplayFont;
sl@8
    47
            marqueeLabelBottom.Font = Properties.Settings.Default.DisplayFont;
sl@9
    48
            checkBoxShowBorders.Checked = Properties.Settings.Default.DisplayShowBorders;
sl@13
    49
            checkBoxConnectOnStartup.Checked = Properties.Settings.Default.DisplayConnectOnStartup;
sl@16
    50
            checkBoxReverseScreen.Checked = Properties.Settings.Default.DisplayReverseScreen;
sl@46
    51
            comboBoxDisplayType.SelectedIndex = Properties.Settings.Default.DisplayType;
sl@13
    52
            //
sl@13
    53
            tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
sl@14
    54
            //We have a bug when drawing minimized and reusing our bitmap
sl@14
    55
            iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14
    56
            iCreateBitmap = false;
sl@0
    57
        }
sl@0
    58
sl@13
    59
        private void MainForm_Load(object sender, EventArgs e)
sl@13
    60
        {
sl@17
    61
            StartServer();
sl@17
    62
sl@37
    63
            //
sl@37
    64
            CheckFontHeight();
sl@37
    65
            //
sl@37
    66
sl@37
    67
sl@13
    68
            if (Properties.Settings.Default.DisplayConnectOnStartup)
sl@13
    69
            {
sl@46
    70
                OpenDisplayConnection();
sl@13
    71
            }
sl@13
    72
        }
sl@13
    73
sl@13
    74
sl@0
    75
        private void buttonFont_Click(object sender, EventArgs e)
sl@0
    76
        {
sl@0
    77
            //fontDialog.ShowColor = true;
sl@0
    78
            //fontDialog.ShowApply = true;
sl@0
    79
            fontDialog.ShowEffects = true;
sl@11
    80
            fontDialog.Font = marqueeLabelTop.Font;
sl@28
    81
sl@28
    82
            fontDialog.FixedPitchOnly = checkBoxFixedPitchFontOnly.Checked;
sl@28
    83
sl@0
    84
            //fontDialog.ShowHelp = true;
sl@0
    85
sl@0
    86
            //fontDlg.MaxSize = 40;
sl@0
    87
            //fontDlg.MinSize = 22;
sl@0
    88
sl@0
    89
            //fontDialog.Parent = this;
sl@0
    90
            //fontDialog.StartPosition = FormStartPosition.CenterParent;
sl@0
    91
sl@0
    92
            //DlgBox.ShowDialog(fontDialog);
sl@0
    93
sl@0
    94
            //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
sl@0
    95
            if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
sl@0
    96
            {
sl@0
    97
sl@4
    98
                //MsgBox.Show("MessageBox MsgBox", "MsgBox caption");
sl@0
    99
sl@0
   100
                //MessageBox.Show("Ok");
sl@4
   101
                marqueeLabelTop.Font = fontDialog.Font;
sl@4
   102
                marqueeLabelBottom.Font = fontDialog.Font;
sl@8
   103
                Properties.Settings.Default.DisplayFont = fontDialog.Font;
sl@8
   104
                Properties.Settings.Default.Save();
sl@36
   105
                //
sl@37
   106
                CheckFontHeight();
sl@37
   107
            }
sl@37
   108
        }
sl@36
   109
sl@37
   110
        /// <summary>
sl@38
   111
        ///
sl@37
   112
        /// </summary>
sl@37
   113
        void CheckFontHeight()
sl@37
   114
        {
sl@37
   115
            if (marqueeLabelBottom.Font.Height > marqueeLabelBottom.Height)
sl@37
   116
            {
sl@37
   117
                labelWarning.Text = "WARNING: Selected font is too height by " + (marqueeLabelBottom.Font.Height - marqueeLabelBottom.Height) + " pixels!";
sl@37
   118
                labelWarning.Visible = true;
sl@0
   119
            }
sl@37
   120
            else
sl@37
   121
            {
sl@37
   122
                labelWarning.Visible = false;
sl@37
   123
            }
sl@37
   124
sl@0
   125
        }
sl@0
   126
sl@0
   127
        private void buttonCapture_Click(object sender, EventArgs e)
sl@0
   128
        {
sl@0
   129
            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height);
sl@0
   130
            tableLayoutPanel.DrawToBitmap(bmp, tableLayoutPanel.ClientRectangle);
sl@14
   131
            //Bitmap bmpToSave = new Bitmap(bmp);
sl@14
   132
            bmp.Save("D:\\capture.png");
sl@14
   133
sl@17
   134
            marqueeLabelTop.Text = "Sweet";
sl@17
   135
sl@14
   136
            /*
sl@14
   137
            string outputFileName = "d:\\capture.png";
sl@14
   138
            using (MemoryStream memory = new MemoryStream())
sl@14
   139
            {
sl@14
   140
                using (FileStream fs = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
sl@14
   141
                {
sl@14
   142
                    bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
sl@14
   143
                    byte[] bytes = memory.ToArray();
sl@14
   144
                    fs.Write(bytes, 0, bytes.Length);
sl@14
   145
                }
sl@14
   146
            }
sl@14
   147
             */
sl@14
   148
sl@0
   149
        }
sl@2
   150
sl@12
   151
        private void CheckForRequestResults()
sl@12
   152
        {
sl@12
   153
            if (iDisplay.IsRequestPending())
sl@12
   154
            {
sl@12
   155
                switch (iDisplay.AttemptRequestCompletion())
sl@12
   156
                {
sl@12
   157
                    case Display.TMiniDisplayRequest.EMiniDisplayRequestPowerSupplyStatus:
sl@12
   158
                        if (iDisplay.PowerSupplyStatus())
sl@12
   159
                        {
sl@12
   160
                            toolStripStatusLabelPower.Text = "ON";
sl@12
   161
                        }
sl@12
   162
                        else
sl@12
   163
                        {
sl@12
   164
                            toolStripStatusLabelPower.Text = "OFF";
sl@12
   165
                        }
sl@12
   166
                        //Issue next request then
sl@12
   167
                        iDisplay.RequestDeviceId();
sl@12
   168
                        break;
sl@12
   169
sl@12
   170
                    case Display.TMiniDisplayRequest.EMiniDisplayRequestDeviceId:
sl@12
   171
                        toolStripStatusLabelConnect.Text += " - " + iDisplay.DeviceId();
sl@12
   172
                        //Issue next request then
sl@12
   173
                        iDisplay.RequestFirmwareRevision();
sl@12
   174
                        break;
sl@12
   175
sl@12
   176
                    case Display.TMiniDisplayRequest.EMiniDisplayRequestFirmwareRevision:
sl@12
   177
                        toolStripStatusLabelConnect.Text += " v" + iDisplay.FirmwareRevision();
sl@12
   178
                        //No more request to issue
sl@12
   179
                        break;
sl@12
   180
                }
sl@12
   181
            }
sl@12
   182
        }
sl@12
   183
sl@16
   184
sl@16
   185
        public delegate int CoordinateTranslationDelegate(System.Drawing.Bitmap aBmp, int aInt);
sl@16
   186
sl@16
   187
sl@16
   188
        public static int ScreenReversedX(System.Drawing.Bitmap aBmp, int aX)
sl@16
   189
        {
sl@16
   190
            return aBmp.Width - aX - 1;
sl@16
   191
        }
sl@16
   192
sl@16
   193
        public int ScreenReversedY(System.Drawing.Bitmap aBmp, int aY)
sl@16
   194
        {
sl@16
   195
            return iBmp.Height - aY - 1;
sl@16
   196
        }
sl@16
   197
sl@16
   198
        public int ScreenX(System.Drawing.Bitmap aBmp, int aX)
sl@16
   199
        {
sl@16
   200
            return aX;
sl@16
   201
        }
sl@16
   202
sl@16
   203
        public int ScreenY(System.Drawing.Bitmap aBmp, int aY)
sl@16
   204
        {
sl@16
   205
            return aY;
sl@16
   206
        }
sl@16
   207
sl@16
   208
sl@16
   209
        //This is our timer tick responsible to perform our render
sl@2
   210
        private void timer_Tick(object sender, EventArgs e)
sl@14
   211
        {
sl@2
   212
            //Update our animations
sl@2
   213
            DateTime NewTickTime = DateTime.Now;
sl@2
   214
sl@2
   215
            marqueeLabelTop.UpdateAnimation(LastTickTime, NewTickTime);
sl@2
   216
            marqueeLabelBottom.UpdateAnimation(LastTickTime, NewTickTime);
sl@2
   217
sl@4
   218
            //Update our display
sl@4
   219
            if (iDisplay.IsOpen())
sl@4
   220
            {
sl@12
   221
                CheckForRequestResults();
sl@12
   222
sl@22
   223
                //Draw to bitmap
sl@14
   224
                if (iCreateBitmap)
sl@14
   225
                {
sl@14
   226
                    iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14
   227
                }
sl@14
   228
                tableLayoutPanel.DrawToBitmap(iBmp, tableLayoutPanel.ClientRectangle);
sl@14
   229
                //iBmp.Save("D:\\capture.png");
sl@16
   230
sl@16
   231
                //Select proper coordinate translation functions
sl@16
   232
                //We used delegate/function pointer to support reverse screen without doing an extra test on each pixels
sl@16
   233
                CoordinateTranslationDelegate screenX;
sl@16
   234
                CoordinateTranslationDelegate screenY;
sl@16
   235
sl@16
   236
                if (Properties.Settings.Default.DisplayReverseScreen)
sl@16
   237
                {
sl@16
   238
                    screenX = ScreenReversedX;
sl@16
   239
                    screenY = ScreenReversedY;
sl@16
   240
                }
sl@16
   241
                else
sl@16
   242
                {
sl@16
   243
                    screenX = ScreenX;
sl@16
   244
                    screenY = ScreenY;
sl@16
   245
                }
sl@22
   246
sl@7
   247
                //Send it to our display
sl@14
   248
                for (int i = 0; i < iBmp.Width; i++)
sl@4
   249
                {
sl@14
   250
                    for (int j = 0; j < iBmp.Height; j++)
sl@4
   251
                    {
sl@4
   252
                        unchecked
sl@4
   253
                        {
sl@14
   254
                            uint color = (uint)iBmp.GetPixel(i, j).ToArgb();
sl@14
   255
                            //For some reason when the app is minimized in the task bar only the alpha of our color is set.
sl@14
   256
                            //Thus that strange test for rendering to work both when the app is in the task bar and when it isn't.
sl@16
   257
                            iDisplay.SetPixel(screenX(iBmp, i), screenY(iBmp, j), Convert.ToInt32(!(color != 0xFF000000)));
sl@4
   258
                        }
sl@4
   259
                    }
sl@4
   260
                }
sl@4
   261
sl@4
   262
                iDisplay.SwapBuffers();
sl@4
   263
sl@4
   264
            }
sl@8
   265
sl@8
   266
            //Compute instant FPS
sl@8
   267
            toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " FPS";
sl@8
   268
sl@8
   269
            LastTickTime = NewTickTime;
sl@8
   270
sl@2
   271
        }
sl@3
   272
sl@46
   273
        private void OpenDisplayConnection()
sl@3
   274
        {
sl@46
   275
            CloseDisplayConnection();
sl@46
   276
sl@46
   277
            if (iDisplay.Open((Display.TMiniDisplayType)Properties.Settings.Default.DisplayType))
sl@3
   278
            {
sl@7
   279
                UpdateStatus();
sl@12
   280
                iDisplay.RequestPowerSupplyStatus();
sl@3
   281
            }
sl@7
   282
            else
sl@7
   283
            {
sl@7
   284
                UpdateStatus();
sl@7
   285
                toolStripStatusLabelConnect.Text = "Connection error";
sl@7
   286
            }
sl@46
   287
        }
sl@7
   288
sl@46
   289
        private void CloseDisplayConnection()
sl@46
   290
        {
sl@46
   291
            iDisplay.Close();
sl@46
   292
            UpdateStatus();
sl@46
   293
        }
sl@46
   294
sl@46
   295
        private void buttonOpen_Click(object sender, EventArgs e)
sl@46
   296
        {
sl@46
   297
            OpenDisplayConnection();
sl@3
   298
        }
sl@3
   299
sl@3
   300
        private void buttonClose_Click(object sender, EventArgs e)
sl@3
   301
        {
sl@46
   302
            CloseDisplayConnection();
sl@3
   303
        }
sl@3
   304
sl@3
   305
        private void buttonClear_Click(object sender, EventArgs e)
sl@3
   306
        {
sl@3
   307
            iDisplay.Clear();
sl@3
   308
            iDisplay.SwapBuffers();
sl@3
   309
        }
sl@3
   310
sl@3
   311
        private void buttonFill_Click(object sender, EventArgs e)
sl@3
   312
        {
sl@3
   313
            iDisplay.Fill();
sl@3
   314
            iDisplay.SwapBuffers();
sl@3
   315
        }
sl@3
   316
sl@3
   317
        private void trackBarBrightness_Scroll(object sender, EventArgs e)
sl@3
   318
        {
sl@9
   319
            Properties.Settings.Default.DisplayBrightness = trackBarBrightness.Value;
sl@9
   320
            Properties.Settings.Default.Save();
sl@3
   321
            iDisplay.SetBrightness(trackBarBrightness.Value);
sl@9
   322
sl@3
   323
        }
sl@7
   324
sl@7
   325
        private void UpdateStatus()
sl@7
   326
        {
sl@7
   327
            if (iDisplay.IsOpen())
sl@7
   328
            {
sl@7
   329
                buttonFill.Enabled = true;
sl@7
   330
                buttonClear.Enabled = true;
sl@7
   331
                buttonOpen.Enabled = false;
sl@7
   332
                buttonClose.Enabled = true;
sl@7
   333
                trackBarBrightness.Enabled = true;
sl@7
   334
                trackBarBrightness.Minimum = iDisplay.MinBrightness();
sl@11
   335
                trackBarBrightness.Maximum = iDisplay.MaxBrightness();
sl@9
   336
                trackBarBrightness.Value = Properties.Settings.Default.DisplayBrightness;
sl@9
   337
                trackBarBrightness.LargeChange = Math.Max(1,(iDisplay.MaxBrightness() - iDisplay.MinBrightness())/5);
sl@9
   338
                trackBarBrightness.SmallChange = 1;
sl@9
   339
                iDisplay.SetBrightness(Properties.Settings.Default.DisplayBrightness);
sl@9
   340
sl@10
   341
                toolStripStatusLabelConnect.Text = "Connected - " + iDisplay.Vendor() + " - " + iDisplay.Product();
sl@10
   342
                //+ " - " + iDisplay.SerialNumber();
sl@7
   343
            }
sl@7
   344
            else
sl@7
   345
            {
sl@7
   346
                buttonFill.Enabled = false;
sl@7
   347
                buttonClear.Enabled = false;
sl@7
   348
                buttonOpen.Enabled = true;
sl@7
   349
                buttonClose.Enabled = false;
sl@7
   350
                trackBarBrightness.Enabled = false;
sl@9
   351
                toolStripStatusLabelConnect.Text = "Disconnected";
sl@7
   352
            }
sl@7
   353
        }
sl@9
   354
sl@13
   355
sl@13
   356
sl@9
   357
        private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
sl@9
   358
        {
sl@16
   359
            //Save our show borders setting
sl@13
   360
            tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
sl@9
   361
            Properties.Settings.Default.DisplayShowBorders = checkBoxShowBorders.Checked;
sl@9
   362
            Properties.Settings.Default.Save();
sl@9
   363
        }
sl@13
   364
sl@13
   365
        private void checkBoxConnectOnStartup_CheckedChanged(object sender, EventArgs e)
sl@13
   366
        {
sl@16
   367
            //Save our connect on startup setting
sl@13
   368
            Properties.Settings.Default.DisplayConnectOnStartup = checkBoxConnectOnStartup.Checked;
sl@13
   369
            Properties.Settings.Default.Save();
sl@13
   370
        }
sl@13
   371
sl@16
   372
        private void checkBoxReverseScreen_CheckedChanged(object sender, EventArgs e)
sl@16
   373
        {
sl@16
   374
            //Save our reverse screen setting
sl@16
   375
            Properties.Settings.Default.DisplayReverseScreen = checkBoxReverseScreen.Checked;
sl@16
   376
            Properties.Settings.Default.Save();
sl@16
   377
        }
sl@16
   378
sl@14
   379
        private void MainForm_Resize(object sender, EventArgs e)
sl@14
   380
        {
sl@14
   381
            if (WindowState == FormWindowState.Minimized)
sl@14
   382
            {
sl@14
   383
                // Do some stuff
sl@14
   384
                //iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14
   385
                iCreateBitmap = true;
sl@14
   386
            }
sl@14
   387
        }
sl@14
   388
sl@17
   389
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
sl@17
   390
        {
sl@17
   391
            StopServer();
sl@32
   392
            e.Cancel = iClosing;
sl@17
   393
        }
sl@17
   394
sl@17
   395
        public void StartServer()
sl@17
   396
        {
sl@17
   397
            iServiceHost = new ServiceHost
sl@17
   398
                (
sl@17
   399
                    typeof(DisplayServer),
sl@20
   400
                    new Uri[] { new Uri("net.tcp://localhost:8001/") }
sl@17
   401
                );
sl@17
   402
sl@30
   403
            iServiceHost.AddServiceEndpoint(typeof(IDisplayService), new NetTcpBinding(SecurityMode.None,true), "DisplayService");
sl@17
   404
            iServiceHost.Open();
sl@17
   405
        }
sl@17
   406
sl@17
   407
        public void StopServer()
sl@17
   408
        {
sl@32
   409
            if (iClients.Count > 0 && !iClosing)
sl@29
   410
            {
sl@29
   411
                //Tell our clients
sl@32
   412
                iClosing = true;
sl@29
   413
                BroadcastCloseEvent();
sl@29
   414
            }
sl@32
   415
            else if (iClosing)
sl@32
   416
            {
sl@32
   417
                if (MessageBox.Show("Force exit?", "Waiting for clients...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
sl@32
   418
                {
sl@32
   419
                    iClosing = false; //We make sure we force close if asked twice
sl@32
   420
                }
sl@32
   421
            }
sl@32
   422
            else
sl@36
   423
            {
sl@32
   424
                //We removed that as it often lags for some reason
sl@32
   425
                //iServiceHost.Close();
sl@32
   426
            }
sl@17
   427
        }
sl@17
   428
sl@21
   429
        public void BroadcastCloseEvent()
sl@21
   430
        {
sl@31
   431
            Trace.TraceInformation("BroadcastCloseEvent - start");
sl@31
   432
sl@21
   433
            var inactiveClients = new List<string>();
sl@21
   434
            foreach (var client in iClients)
sl@21
   435
            {
sl@21
   436
                //if (client.Key != eventData.ClientName)
sl@21
   437
                {
sl@21
   438
                    try
sl@21
   439
                    {
sl@31
   440
                        Trace.TraceInformation("BroadcastCloseEvent - " + client.Key);
sl@33
   441
                        client.Value.Callback.OnCloseOrder(/*eventData*/);
sl@21
   442
                    }
sl@21
   443
                    catch (Exception ex)
sl@21
   444
                    {
sl@21
   445
                        inactiveClients.Add(client.Key);
sl@21
   446
                    }
sl@21
   447
                }
sl@21
   448
            }
sl@21
   449
sl@21
   450
            if (inactiveClients.Count > 0)
sl@21
   451
            {
sl@21
   452
                foreach (var client in inactiveClients)
sl@21
   453
                {
sl@21
   454
                    iClients.Remove(client);
sl@30
   455
                    Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(client, false)[0]);
sl@21
   456
                }
sl@21
   457
            }
sl@21
   458
        }
sl@21
   459
sl@25
   460
        private void buttonStartClient_Click(object sender, EventArgs e)
sl@25
   461
        {
sl@25
   462
            Thread clientThread = new Thread(SharpDisplayClient.Program.Main);
sl@25
   463
            clientThread.Start();
sl@36
   464
            BringToFront();
sl@25
   465
        }
sl@25
   466
sl@27
   467
        private void buttonSuspend_Click(object sender, EventArgs e)
sl@27
   468
        {
sl@27
   469
            timer.Enabled = !timer.Enabled;
sl@27
   470
            if (!timer.Enabled)
sl@27
   471
            {
sl@27
   472
                buttonSuspend.Text = "Suspend";
sl@27
   473
            }
sl@27
   474
            else
sl@27
   475
            {
sl@27
   476
                buttonSuspend.Text = "Pause";
sl@27
   477
            }
sl@27
   478
        }
sl@27
   479
sl@29
   480
        private void buttonCloseClients_Click(object sender, EventArgs e)
sl@29
   481
        {
sl@29
   482
            BroadcastCloseEvent();
sl@29
   483
        }
sl@29
   484
sl@30
   485
        private void treeViewClients_AfterSelect(object sender, TreeViewEventArgs e)
sl@30
   486
        {
sl@21
   487
sl@30
   488
        }
sl@30
   489
sl@36
   490
        //Delegates are used for our thread safe method
sl@30
   491
        public delegate void AddClientDelegate(string aSessionId, IDisplayServiceCallback aCallback);
sl@30
   492
        public delegate void RemoveClientDelegate(string aSessionId);
sl@43
   493
        public delegate void SetTextDelegate(string SessionId, TextField aTextField);
sl@43
   494
        public delegate void SetTextsDelegate(string SessionId, System.Collections.Generic.IList<TextField> aTextFields);
sl@32
   495
        public delegate void SetClientNameDelegate(string aSessionId, string aName);
sl@30
   496
sl@36
   497
sl@30
   498
        /// <summary>
sl@36
   499
        ///
sl@30
   500
        /// </summary>
sl@30
   501
        /// <param name="aSessionId"></param>
sl@30
   502
        /// <param name="aCallback"></param>
sl@30
   503
        public void AddClientThreadSafe(string aSessionId, IDisplayServiceCallback aCallback)
sl@30
   504
        {
sl@33
   505
            if (this.InvokeRequired)
sl@30
   506
            {
sl@30
   507
                //Not in the proper thread, invoke ourselves
sl@30
   508
                AddClientDelegate d = new AddClientDelegate(AddClientThreadSafe);
sl@30
   509
                this.Invoke(d, new object[] { aSessionId, aCallback });
sl@30
   510
            }
sl@30
   511
            else
sl@30
   512
            {
sl@30
   513
                //We are in the proper thread
sl@30
   514
                //Add this session to our collection of clients
sl@33
   515
                ClientData newClient = new ClientData(aSessionId, aCallback);
sl@33
   516
                Program.iMainForm.iClients.Add(aSessionId, newClient);
sl@30
   517
                //Add this session to our UI
sl@33
   518
                UpdateClientTreeViewNode(newClient);
sl@30
   519
            }
sl@30
   520
        }
sl@30
   521
sl@30
   522
        /// <summary>
sl@36
   523
        ///
sl@30
   524
        /// </summary>
sl@30
   525
        /// <param name="aSessionId"></param>
sl@30
   526
        public void RemoveClientThreadSafe(string aSessionId)
sl@30
   527
        {
sl@33
   528
            if (this.InvokeRequired)
sl@30
   529
            {
sl@30
   530
                //Not in the proper thread, invoke ourselves
sl@30
   531
                RemoveClientDelegate d = new RemoveClientDelegate(RemoveClientThreadSafe);
sl@30
   532
                this.Invoke(d, new object[] { aSessionId });
sl@30
   533
            }
sl@30
   534
            else
sl@30
   535
            {
sl@30
   536
                //We are in the proper thread
sl@33
   537
                //Remove this session from both client collection and UI tree view
sl@30
   538
                if (Program.iMainForm.iClients.Keys.Contains(aSessionId))
sl@30
   539
                {
sl@30
   540
                    Program.iMainForm.iClients.Remove(aSessionId);
sl@30
   541
                    Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(aSessionId, false)[0]);
sl@32
   542
                }
sl@32
   543
sl@32
   544
                if (iClosing && iClients.Count == 0)
sl@32
   545
                {
sl@32
   546
                    //We were closing our form
sl@32
   547
                    //All clients are now closed
sl@32
   548
                    //Just resume our close operation
sl@32
   549
                    iClosing = false;
sl@32
   550
                    Close();
sl@32
   551
                }
sl@30
   552
            }
sl@30
   553
        }
sl@30
   554
sl@30
   555
        /// <summary>
sl@36
   556
        ///
sl@30
   557
        /// </summary>
sl@30
   558
        /// <param name="aLineIndex"></param>
sl@30
   559
        /// <param name="aText"></param>
sl@43
   560
        public void SetTextThreadSafe(string aSessionId, TextField aTextField)
sl@30
   561
        {
sl@33
   562
            if (this.InvokeRequired)
sl@30
   563
            {
sl@30
   564
                //Not in the proper thread, invoke ourselves
sl@30
   565
                SetTextDelegate d = new SetTextDelegate(SetTextThreadSafe);
sl@43
   566
                this.Invoke(d, new object[] { aSessionId, aTextField });
sl@30
   567
            }
sl@30
   568
            else
sl@30
   569
            {
sl@34
   570
                ClientData client = iClients[aSessionId];
sl@34
   571
                if (client != null)
sl@30
   572
                {
sl@34
   573
                    //Make sure all our texts are in place
sl@43
   574
                    while (client.Texts.Count < (aTextField.Index + 1))
sl@34
   575
                    {
sl@43
   576
                        //Add a text field with proper index
sl@43
   577
                        client.Texts.Add(new TextField(client.Texts.Count));
sl@34
   578
                    }
sl@43
   579
                    client.Texts[aTextField.Index] = aTextField;
sl@34
   580
sl@34
   581
                    //We are in the proper thread
sl@34
   582
                    //Only support two lines for now
sl@43
   583
                    if (aTextField.Index == 0)
sl@34
   584
                    {
sl@43
   585
                        marqueeLabelTop.Text = aTextField.Text;
sl@43
   586
                        marqueeLabelTop.TextAlign = aTextField.Alignment;
sl@34
   587
                    }
sl@43
   588
                    else if (aTextField.Index == 1)
sl@34
   589
                    {
sl@43
   590
                        marqueeLabelBottom.Text = aTextField.Text;
sl@43
   591
                        marqueeLabelBottom.TextAlign = aTextField.Alignment;
sl@34
   592
                    }
sl@34
   593
sl@34
   594
sl@34
   595
                    UpdateClientTreeViewNode(client);
sl@30
   596
                }
sl@30
   597
            }
sl@30
   598
        }
sl@30
   599
sl@30
   600
        /// <summary>
sl@36
   601
        ///
sl@30
   602
        /// </summary>
sl@30
   603
        /// <param name="aTexts"></param>
sl@43
   604
        public void SetTextsThreadSafe(string aSessionId, System.Collections.Generic.IList<TextField> aTextFields)
sl@30
   605
        {
sl@33
   606
            if (this.InvokeRequired)
sl@30
   607
            {
sl@30
   608
                //Not in the proper thread, invoke ourselves
sl@30
   609
                SetTextsDelegate d = new SetTextsDelegate(SetTextsThreadSafe);
sl@43
   610
                this.Invoke(d, new object[] { aSessionId, aTextFields });
sl@30
   611
            }
sl@30
   612
            else
sl@30
   613
            {
sl@43
   614
                //We are in the proper thread
sl@34
   615
                ClientData client = iClients[aSessionId];
sl@34
   616
                if (client != null)
sl@30
   617
                {
sl@43
   618
                    //Populate our client with the given text fields
sl@34
   619
                    int j = 0;
sl@43
   620
                    foreach (TextField textField in aTextFields)
sl@30
   621
                    {
sl@34
   622
                        if (client.Texts.Count < (j + 1))
sl@34
   623
                        {
sl@43
   624
                            client.Texts.Add(textField);
sl@34
   625
                        }
sl@34
   626
                        else
sl@34
   627
                        {
sl@43
   628
                            client.Texts[j] = textField;
sl@34
   629
                        }
sl@34
   630
                        j++;
sl@43
   631
                    }                    
sl@34
   632
                    //Only support two lines for now
sl@43
   633
                    for (int i = 0; i < aTextFields.Count; i++)
sl@30
   634
                    {
sl@43
   635
                        if (aTextFields[i].Index == 0)
sl@34
   636
                        {
sl@43
   637
                            marqueeLabelTop.Text = aTextFields[i].Text;
sl@43
   638
                            marqueeLabelTop.TextAlign = aTextFields[i].Alignment;
sl@34
   639
                        }
sl@43
   640
                        else if (aTextFields[i].Index == 1)
sl@34
   641
                        {
sl@43
   642
                            marqueeLabelBottom.Text = aTextFields[i].Text;
sl@43
   643
                            marqueeLabelBottom.TextAlign = aTextFields[i].Alignment;
sl@34
   644
                        }
sl@30
   645
                    }
sl@34
   646
sl@34
   647
sl@34
   648
                    UpdateClientTreeViewNode(client);
sl@30
   649
                }
sl@30
   650
            }
sl@32
   651
        }
sl@30
   652
sl@32
   653
sl@32
   654
        /// <summary>
sl@36
   655
        ///
sl@32
   656
        /// </summary>
sl@32
   657
        /// <param name="aSessionId"></param>
sl@32
   658
        /// <param name="aName"></param>
sl@32
   659
        public void SetClientNameThreadSafe(string aSessionId, string aName)
sl@32
   660
        {
sl@32
   661
            if (this.InvokeRequired)
sl@32
   662
            {
sl@32
   663
                //Not in the proper thread, invoke ourselves
sl@32
   664
                SetClientNameDelegate d = new SetClientNameDelegate(SetClientNameThreadSafe);
sl@32
   665
                this.Invoke(d, new object[] { aSessionId, aName });
sl@32
   666
            }
sl@32
   667
            else
sl@32
   668
            {
sl@32
   669
                //We are in the proper thread
sl@33
   670
                //Get our client
sl@33
   671
                ClientData client = iClients[aSessionId];
sl@33
   672
                if (client != null)
sl@32
   673
                {
sl@33
   674
                    //Set its name
sl@33
   675
                    client.Name = aName;
sl@33
   676
                    //Update our tree-view
sl@33
   677
                    UpdateClientTreeViewNode(client);
sl@33
   678
                }
sl@33
   679
            }
sl@33
   680
        }
sl@33
   681
sl@33
   682
        /// <summary>
sl@36
   683
        ///
sl@33
   684
        /// </summary>
sl@33
   685
        /// <param name="aClient"></param>
sl@33
   686
        private void UpdateClientTreeViewNode(ClientData aClient)
sl@33
   687
        {
sl@33
   688
            if (aClient == null)
sl@33
   689
            {
sl@33
   690
                return;
sl@33
   691
            }
sl@33
   692
sl@33
   693
            TreeNode node = null;
sl@33
   694
            //Check that our client node already exists
sl@33
   695
            //Get our client root node using its key which is our session ID
sl@33
   696
            TreeNode[] nodes = treeViewClients.Nodes.Find(aClient.SessionId, false);
sl@33
   697
            if (nodes.Count()>0)
sl@33
   698
            {
sl@33
   699
                //We already have a node for that client
sl@33
   700
                node = nodes[0];
sl@33
   701
                //Clear children as we are going to recreate them below
sl@33
   702
                node.Nodes.Clear();
sl@33
   703
            }
sl@33
   704
            else
sl@33
   705
            {
sl@33
   706
                //Client node does not exists create a new one
sl@33
   707
                treeViewClients.Nodes.Add(aClient.SessionId, aClient.SessionId);
sl@33
   708
                node = treeViewClients.Nodes.Find(aClient.SessionId, false)[0];
sl@33
   709
            }
sl@33
   710
sl@33
   711
            if (node != null)
sl@33
   712
            {
sl@33
   713
                //Change its name
sl@33
   714
                if (aClient.Name != "")
sl@33
   715
                {
sl@33
   716
                    //We have a name, us it as text for our root node
sl@33
   717
                    node.Text = aClient.Name;
sl@32
   718
                    //Add a child with SessionId
sl@33
   719
                    node.Nodes.Add(new TreeNode(aClient.SessionId));
sl@33
   720
                }
sl@33
   721
                else
sl@33
   722
                {
sl@33
   723
                    //No name, use session ID instead
sl@33
   724
                    node.Text = aClient.SessionId;
sl@33
   725
                }
sl@36
   726
sl@33
   727
                if (aClient.Texts.Count > 0)
sl@33
   728
                {
sl@33
   729
                    //Create root node for our texts
sl@33
   730
                    TreeNode textsRoot = new TreeNode("Text");
sl@33
   731
                    node.Nodes.Add(textsRoot);
sl@33
   732
                    //For each text add a new entry
sl@43
   733
                    foreach (TextField field in aClient.Texts)
sl@33
   734
                    {
sl@43
   735
                        textsRoot.Nodes.Add(new TreeNode(field.Text));
sl@33
   736
                    }
sl@32
   737
                }
sl@34
   738
sl@34
   739
                node.ExpandAll();
sl@32
   740
            }
sl@30
   741
        }
sl@17
   742
sl@38
   743
        private void buttonAddRow_Click(object sender, EventArgs e)
sl@38
   744
        {
sl@38
   745
            if (tableLayoutPanel.RowCount < 6)
sl@38
   746
            {
sl@38
   747
                tableLayoutPanel.RowCount++;
sl@38
   748
                CheckFontHeight();
sl@38
   749
            }
sl@38
   750
        }
sl@38
   751
sl@38
   752
        private void buttonRemoveRow_Click(object sender, EventArgs e)
sl@38
   753
        {
sl@38
   754
            if (tableLayoutPanel.RowCount > 1)
sl@38
   755
            {
sl@38
   756
                tableLayoutPanel.RowCount--;
sl@38
   757
                CheckFontHeight();
sl@38
   758
            }
sl@38
   759
        }
sl@38
   760
sl@38
   761
        private void buttonAddColumn_Click(object sender, EventArgs e)
sl@38
   762
        {
sl@38
   763
            if (tableLayoutPanel.ColumnCount < 8)
sl@38
   764
            {
sl@38
   765
                tableLayoutPanel.ColumnCount++;
sl@38
   766
                //CheckFontHeight();
sl@38
   767
            }
sl@38
   768
        }
sl@38
   769
sl@38
   770
        private void buttonRemoveColumn_Click(object sender, EventArgs e)
sl@38
   771
        {
sl@38
   772
            if (tableLayoutPanel.ColumnCount > 1)
sl@38
   773
            {
sl@38
   774
                tableLayoutPanel.ColumnCount--;
sl@38
   775
                //CheckFontHeight();
sl@38
   776
            }
sl@38
   777
        }
sl@38
   778
sl@41
   779
        private void buttonAlignLeft_Click(object sender, EventArgs e)
sl@41
   780
        {
sl@41
   781
            marqueeLabelTop.TextAlign = ContentAlignment.MiddleLeft;
sl@41
   782
            marqueeLabelBottom.TextAlign = ContentAlignment.MiddleLeft;
sl@41
   783
        }
sl@41
   784
sl@41
   785
        private void buttonAlignCenter_Click(object sender, EventArgs e)
sl@41
   786
        {
sl@41
   787
            marqueeLabelTop.TextAlign = ContentAlignment.MiddleCenter;
sl@41
   788
            marqueeLabelBottom.TextAlign = ContentAlignment.MiddleCenter;
sl@41
   789
        }
sl@41
   790
sl@41
   791
        private void buttonAlignRight_Click(object sender, EventArgs e)
sl@41
   792
        {
sl@41
   793
            marqueeLabelTop.TextAlign = ContentAlignment.MiddleRight;
sl@41
   794
            marqueeLabelBottom.TextAlign = ContentAlignment.MiddleRight;
sl@41
   795
        }
sl@36
   796
sl@46
   797
        private void comboBoxDisplayType_SelectedIndexChanged(object sender, EventArgs e)
sl@46
   798
        {
sl@46
   799
            Properties.Settings.Default.DisplayType = comboBoxDisplayType.SelectedIndex;
sl@46
   800
            Properties.Settings.Default.Save();
sl@46
   801
            OpenDisplayConnection();
sl@46
   802
        }
sl@46
   803
sl@0
   804
    }
sl@34
   805
sl@34
   806
    /// <summary>
sl@34
   807
    /// A UI thread copy of a client relevant data.
sl@34
   808
    /// Keeping this copy in the UI thread helps us deal with threading issues.
sl@34
   809
    /// </summary>
sl@34
   810
    public class ClientData
sl@34
   811
    {
sl@34
   812
        public ClientData(string aSessionId, IDisplayServiceCallback aCallback)
sl@34
   813
        {
sl@34
   814
            SessionId = aSessionId;
sl@34
   815
            Name = "";
sl@43
   816
            Texts = new List<TextField>();
sl@34
   817
            Callback = aCallback;
sl@34
   818
        }
sl@34
   819
sl@34
   820
        public string SessionId { get; set; }
sl@34
   821
        public string Name { get; set; }
sl@43
   822
        public List<TextField> Texts { get; set; }
sl@34
   823
        public IDisplayServiceCallback Callback { get; set; }
sl@34
   824
    }
sl@0
   825
}