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