Server/MainForm.cs
author sl
Mon, 22 Sep 2014 16:04:26 +0200
changeset 62 ac698f4e1b36
parent 61 5a24e79384be
child 63 cd9924457275
permissions -rw-r--r--
Adding the possibility for clients to define a basic layout.
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@25
    17
using SharpDisplayClient;
sl@55
    18
using SharpDisplay;
sl@0
    19
sl@0
    20
namespace SharpDisplayManager
sl@0
    21
{
sl@58
    22
    //Types declarations
sl@58
    23
    public delegate uint ColorProcessingDelegate(int aX, int aY, uint aPixel);
sl@58
    24
    public delegate int CoordinateTranslationDelegate(System.Drawing.Bitmap aBmp, int aInt);
sl@62
    25
    //Delegates are used for our thread safe method
sl@62
    26
    public delegate void AddClientDelegate(string aSessionId, ICallback aCallback);
sl@62
    27
    public delegate void RemoveClientDelegate(string aSessionId);
sl@62
    28
    public delegate void SetTextDelegate(string SessionId, TextField aTextField);
sl@62
    29
    public delegate void SetLayoutDelegate(string SessionId, TableLayout aLayout);
sl@62
    30
    public delegate void SetTextsDelegate(string SessionId, System.Collections.Generic.IList<TextField> aTextFields);
sl@62
    31
    public delegate void SetClientNameDelegate(string aSessionId, string aName);
sl@62
    32
sl@58
    33
sl@58
    34
    /// <summary>
sl@58
    35
    /// Our Display manager main form
sl@58
    36
    /// </summary>
sl@0
    37
    public partial class MainForm : Form
sl@0
    38
    {
sl@58
    39
sl@2
    40
        DateTime LastTickTime;
sl@3
    41
        Display iDisplay;
sl@14
    42
        System.Drawing.Bitmap iBmp;
sl@14
    43
        bool iCreateBitmap; //Workaround render to bitmap issues when minimized
sl@17
    44
        ServiceHost iServiceHost;
sl@21
    45
        /// <summary>
sl@21
    46
        /// Our collection of clients
sl@21
    47
        /// </summary>
sl@33
    48
        public Dictionary<string, ClientData> iClients;
sl@29
    49
        public bool iClosing;
sl@58
    50
        ColorProcessingDelegate iColorFx;
sl@58
    51
        CoordinateTranslationDelegate iScreenX;
sl@58
    52
        CoordinateTranslationDelegate iScreenY;
sl@2
    53
sl@0
    54
        public MainForm()
sl@0
    55
        {
sl@2
    56
            LastTickTime = DateTime.Now;
sl@3
    57
            iDisplay = new Display();
sl@33
    58
            iClients = new Dictionary<string, ClientData>();
sl@2
    59
sl@0
    60
            InitializeComponent();
sl@7
    61
            UpdateStatus();
sl@14
    62
            //We have a bug when drawing minimized and reusing our bitmap
sl@14
    63
            iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14
    64
            iCreateBitmap = false;
sl@57
    65
            //
sl@57
    66
            //this.tableLayoutPanel.CellPaint += new TableLayoutCellPaintEventHandler(tableLayoutPanel_CellPaint);
sl@0
    67
        }
sl@0
    68
sl@13
    69
        private void MainForm_Load(object sender, EventArgs e)
sl@13
    70
        {
sl@17
    71
            StartServer();
sl@17
    72
sl@13
    73
            if (Properties.Settings.Default.DisplayConnectOnStartup)
sl@13
    74
            {
sl@46
    75
                OpenDisplayConnection();
sl@13
    76
            }
sl@13
    77
        }
sl@13
    78
sl@57
    79
        //Testing that stuff
sl@57
    80
        private void tableLayoutPanel_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
sl@57
    81
        {
sl@57
    82
            var panel = sender as TableLayoutPanel;
sl@57
    83
            //e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
sl@57
    84
            var rectangle = e.CellBounds;
sl@57
    85
            using (var pen = new Pen(Color.Black, 1))
sl@57
    86
            {
sl@57
    87
                pen.Alignment = System.Drawing.Drawing2D.PenAlignment.Center;
sl@57
    88
                pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
sl@57
    89
sl@57
    90
                if (e.Row == (panel.RowCount - 1))
sl@57
    91
                {
sl@57
    92
                    rectangle.Height -= 1;
sl@57
    93
                }
sl@57
    94
sl@57
    95
                if (e.Column == (panel.ColumnCount - 1))
sl@57
    96
                {
sl@57
    97
                    rectangle.Width -= 1;
sl@57
    98
                }
sl@57
    99
sl@57
   100
                e.Graphics.DrawRectangle(pen, rectangle);
sl@57
   101
            }
sl@57
   102
        }
sl@57
   103
sl@13
   104
sl@0
   105
        private void buttonFont_Click(object sender, EventArgs e)
sl@0
   106
        {
sl@0
   107
            //fontDialog.ShowColor = true;
sl@0
   108
            //fontDialog.ShowApply = true;
sl@0
   109
            fontDialog.ShowEffects = true;
sl@60
   110
            MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[0];
sl@60
   111
            fontDialog.Font = label.Font;
sl@28
   112
sl@28
   113
            fontDialog.FixedPitchOnly = checkBoxFixedPitchFontOnly.Checked;
sl@28
   114
sl@0
   115
            //fontDialog.ShowHelp = true;
sl@0
   116
sl@0
   117
            //fontDlg.MaxSize = 40;
sl@0
   118
            //fontDlg.MinSize = 22;
sl@0
   119
sl@0
   120
            //fontDialog.Parent = this;
sl@0
   121
            //fontDialog.StartPosition = FormStartPosition.CenterParent;
sl@0
   122
sl@0
   123
            //DlgBox.ShowDialog(fontDialog);
sl@0
   124
sl@0
   125
            //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
sl@0
   126
            if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
sl@0
   127
            {
sl@0
   128
sl@4
   129
                //MsgBox.Show("MessageBox MsgBox", "MsgBox caption");
sl@0
   130
sl@0
   131
                //MessageBox.Show("Ok");
sl@60
   132
                foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
sl@60
   133
                {
sl@60
   134
                    ctrl.Font = fontDialog.Font;
sl@60
   135
                }
sl@48
   136
                cds.Font = fontDialog.Font;
sl@8
   137
                Properties.Settings.Default.Save();
sl@36
   138
                //
sl@37
   139
                CheckFontHeight();
sl@37
   140
            }
sl@37
   141
        }
sl@36
   142
sl@37
   143
        /// <summary>
sl@38
   144
        ///
sl@37
   145
        /// </summary>
sl@37
   146
        void CheckFontHeight()
sl@37
   147
        {
sl@54
   148
            //Show font height and width
sl@54
   149
            labelFontHeight.Text = "Font height: " + cds.Font.Height;
sl@54
   150
            float charWidth = IsFixedWidth(cds.Font);
sl@54
   151
            if (charWidth == 0.0f)
sl@54
   152
            {
sl@54
   153
                labelFontWidth.Visible = false;
sl@54
   154
            }
sl@54
   155
            else
sl@54
   156
            {
sl@54
   157
                labelFontWidth.Visible = true;
sl@54
   158
                labelFontWidth.Text = "Font width: " + charWidth;
sl@54
   159
            }
sl@54
   160
sl@54
   161
            //Now check font height and show a warning if needed.
sl@60
   162
            MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[0];
sl@60
   163
            if (label.Font.Height > label.Height)
sl@37
   164
            {
sl@60
   165
                labelWarning.Text = "WARNING: Selected font is too height by " + (label.Font.Height - label.Height) + " pixels!";
sl@37
   166
                labelWarning.Visible = true;
sl@0
   167
            }
sl@37
   168
            else
sl@37
   169
            {
sl@37
   170
                labelWarning.Visible = false;
sl@37
   171
            }
sl@37
   172
sl@0
   173
        }
sl@0
   174
sl@0
   175
        private void buttonCapture_Click(object sender, EventArgs e)
sl@0
   176
        {
sl@0
   177
            System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height);
sl@0
   178
            tableLayoutPanel.DrawToBitmap(bmp, tableLayoutPanel.ClientRectangle);
sl@14
   179
            //Bitmap bmpToSave = new Bitmap(bmp);
sl@14
   180
            bmp.Save("D:\\capture.png");
sl@14
   181
sl@60
   182
            ((MarqueeLabel)tableLayoutPanel.Controls[0]).Text = "Captured";
sl@17
   183
sl@14
   184
            /*
sl@14
   185
            string outputFileName = "d:\\capture.png";
sl@14
   186
            using (MemoryStream memory = new MemoryStream())
sl@14
   187
            {
sl@14
   188
                using (FileStream fs = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
sl@14
   189
                {
sl@14
   190
                    bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
sl@14
   191
                    byte[] bytes = memory.ToArray();
sl@14
   192
                    fs.Write(bytes, 0, bytes.Length);
sl@14
   193
                }
sl@14
   194
            }
sl@14
   195
             */
sl@14
   196
sl@0
   197
        }
sl@2
   198
sl@12
   199
        private void CheckForRequestResults()
sl@12
   200
        {
sl@12
   201
            if (iDisplay.IsRequestPending())
sl@12
   202
            {
sl@12
   203
                switch (iDisplay.AttemptRequestCompletion())
sl@12
   204
                {
sl@51
   205
                    case Display.TMiniDisplayRequest.EMiniDisplayRequestFirmwareRevision:
sl@51
   206
                        toolStripStatusLabelConnect.Text += " v" + iDisplay.FirmwareRevision();
sl@51
   207
                        //Issue next request then
sl@51
   208
                        iDisplay.RequestPowerSupplyStatus();
sl@51
   209
                        break;
sl@51
   210
sl@12
   211
                    case Display.TMiniDisplayRequest.EMiniDisplayRequestPowerSupplyStatus:
sl@12
   212
                        if (iDisplay.PowerSupplyStatus())
sl@12
   213
                        {
sl@12
   214
                            toolStripStatusLabelPower.Text = "ON";
sl@12
   215
                        }
sl@12
   216
                        else
sl@12
   217
                        {
sl@12
   218
                            toolStripStatusLabelPower.Text = "OFF";
sl@12
   219
                        }
sl@12
   220
                        //Issue next request then
sl@12
   221
                        iDisplay.RequestDeviceId();
sl@12
   222
                        break;
sl@12
   223
sl@12
   224
                    case Display.TMiniDisplayRequest.EMiniDisplayRequestDeviceId:
sl@12
   225
                        toolStripStatusLabelConnect.Text += " - " + iDisplay.DeviceId();
sl@12
   226
                        //No more request to issue
sl@12
   227
                        break;
sl@12
   228
                }
sl@12
   229
            }
sl@12
   230
        }
sl@12
   231
sl@58
   232
        public static uint ColorWhiteIsOn(int aX, int aY, uint aPixel)
sl@58
   233
        {
sl@58
   234
            if ((aPixel & 0x00FFFFFF) == 0x00FFFFFF)
sl@58
   235
            {
sl@58
   236
                return 0xFFFFFFFF;
sl@58
   237
            }
sl@58
   238
            return 0x00000000;
sl@58
   239
        }
sl@16
   240
sl@58
   241
        public static uint ColorUntouched(int aX, int aY, uint aPixel)
sl@57
   242
        {
sl@57
   243
            return aPixel;
sl@57
   244
        }
sl@57
   245
sl@58
   246
        public static uint ColorInversed(int aX, int aY, uint aPixel)
sl@57
   247
        {
sl@57
   248
            return ~aPixel;
sl@57
   249
        }
sl@57
   250
sl@58
   251
        public static uint ColorChessboard(int aX, int aY, uint aPixel)
sl@58
   252
        {
sl@58
   253
            if ((aX % 2 == 0) && (aY % 2 == 0))
sl@58
   254
            {
sl@58
   255
                return ~aPixel;
sl@58
   256
            }
sl@58
   257
            else if ((aX % 2 != 0) && (aY % 2 != 0))
sl@58
   258
            {
sl@58
   259
                return ~aPixel;
sl@58
   260
            }
sl@58
   261
            return 0x00000000;
sl@58
   262
        }
sl@58
   263
sl@16
   264
sl@16
   265
        public static int ScreenReversedX(System.Drawing.Bitmap aBmp, int aX)
sl@16
   266
        {
sl@16
   267
            return aBmp.Width - aX - 1;
sl@16
   268
        }
sl@16
   269
sl@16
   270
        public int ScreenReversedY(System.Drawing.Bitmap aBmp, int aY)
sl@16
   271
        {
sl@16
   272
            return iBmp.Height - aY - 1;
sl@16
   273
        }
sl@16
   274
sl@16
   275
        public int ScreenX(System.Drawing.Bitmap aBmp, int aX)
sl@16
   276
        {
sl@16
   277
            return aX;
sl@16
   278
        }
sl@16
   279
sl@16
   280
        public int ScreenY(System.Drawing.Bitmap aBmp, int aY)
sl@16
   281
        {
sl@16
   282
            return aY;
sl@16
   283
        }
sl@16
   284
sl@58
   285
        /// <summary>
sl@58
   286
        /// Select proper pixel delegates according to our current settings.
sl@58
   287
        /// </summary>
sl@58
   288
        private void SetupPixelDelegates()
sl@58
   289
        {
sl@59
   290
            //Select our pixel processing routine
sl@58
   291
            if (cds.InverseColors)
sl@58
   292
            {
sl@58
   293
                //iColorFx = ColorChessboard;
sl@58
   294
                iColorFx = ColorInversed;
sl@58
   295
            }
sl@58
   296
            else
sl@58
   297
            {
sl@58
   298
                iColorFx = ColorWhiteIsOn;
sl@58
   299
            }
sl@58
   300
sl@58
   301
            //Select proper coordinate translation functions
sl@58
   302
            //We used delegate/function pointer to support reverse screen without doing an extra test on each pixels
sl@58
   303
            if (cds.ReverseScreen)
sl@58
   304
            {
sl@58
   305
                iScreenX = ScreenReversedX;
sl@58
   306
                iScreenY = ScreenReversedY;
sl@58
   307
            }
sl@58
   308
            else
sl@58
   309
            {
sl@58
   310
                iScreenX = ScreenX;
sl@58
   311
                iScreenY = ScreenY;
sl@58
   312
            }
sl@58
   313
sl@58
   314
        }
sl@16
   315
sl@16
   316
        //This is our timer tick responsible to perform our render
sl@2
   317
        private void timer_Tick(object sender, EventArgs e)
sl@14
   318
        {
sl@2
   319
            //Update our animations
sl@2
   320
            DateTime NewTickTime = DateTime.Now;
sl@2
   321
sl@60
   322
            //Update animation for all our marquees
sl@60
   323
            foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
sl@60
   324
            {
sl@60
   325
                ctrl.UpdateAnimation(LastTickTime, NewTickTime);
sl@60
   326
            }
sl@60
   327
sl@2
   328
sl@4
   329
            //Update our display
sl@4
   330
            if (iDisplay.IsOpen())
sl@4
   331
            {
sl@12
   332
                CheckForRequestResults();
sl@12
   333
sl@22
   334
                //Draw to bitmap
sl@14
   335
                if (iCreateBitmap)
sl@14
   336
                {
sl@14
   337
                    iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14
   338
                }
sl@14
   339
                tableLayoutPanel.DrawToBitmap(iBmp, tableLayoutPanel.ClientRectangle);
sl@14
   340
                //iBmp.Save("D:\\capture.png");
sl@16
   341
sl@7
   342
                //Send it to our display
sl@14
   343
                for (int i = 0; i < iBmp.Width; i++)
sl@4
   344
                {
sl@14
   345
                    for (int j = 0; j < iBmp.Height; j++)
sl@4
   346
                    {
sl@4
   347
                        unchecked
sl@4
   348
                        {
sl@58
   349
                            //Get our processed pixel coordinates
sl@58
   350
                            int x = iScreenX(iBmp, i);
sl@58
   351
                            int y = iScreenY(iBmp, j);
sl@58
   352
                            //Get pixel color
sl@14
   353
                            uint color = (uint)iBmp.GetPixel(i, j).ToArgb();
sl@57
   354
                            //Apply color effects
sl@58
   355
                            color = iColorFx(x,y,color);
sl@58
   356
                            //Now set our pixel
sl@58
   357
                            iDisplay.SetPixel(x, y, color);
sl@4
   358
                        }
sl@4
   359
                    }
sl@4
   360
                }
sl@4
   361
sl@4
   362
                iDisplay.SwapBuffers();
sl@4
   363
sl@4
   364
            }
sl@8
   365
sl@8
   366
            //Compute instant FPS
sl@47
   367
            toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " / " + (1000/timer.Interval).ToString() + " FPS";
sl@8
   368
sl@8
   369
            LastTickTime = NewTickTime;
sl@8
   370
sl@2
   371
        }
sl@3
   372
sl@46
   373
        private void OpenDisplayConnection()
sl@3
   374
        {
sl@46
   375
            CloseDisplayConnection();
sl@46
   376
sl@48
   377
            if (iDisplay.Open((Display.TMiniDisplayType)cds.DisplayType))
sl@3
   378
            {
sl@7
   379
                UpdateStatus();
sl@51
   380
                iDisplay.RequestFirmwareRevision();
sl@3
   381
            }
sl@7
   382
            else
sl@7
   383
            {
sl@7
   384
                UpdateStatus();
sl@7
   385
                toolStripStatusLabelConnect.Text = "Connection error";
sl@7
   386
            }
sl@46
   387
        }
sl@7
   388
sl@46
   389
        private void CloseDisplayConnection()
sl@46
   390
        {
sl@46
   391
            iDisplay.Close();
sl@46
   392
            UpdateStatus();
sl@46
   393
        }
sl@46
   394
sl@46
   395
        private void buttonOpen_Click(object sender, EventArgs e)
sl@46
   396
        {
sl@46
   397
            OpenDisplayConnection();
sl@3
   398
        }
sl@3
   399
sl@3
   400
        private void buttonClose_Click(object sender, EventArgs e)
sl@3
   401
        {
sl@46
   402
            CloseDisplayConnection();
sl@3
   403
        }
sl@3
   404
sl@3
   405
        private void buttonClear_Click(object sender, EventArgs e)
sl@3
   406
        {
sl@3
   407
            iDisplay.Clear();
sl@3
   408
            iDisplay.SwapBuffers();
sl@3
   409
        }
sl@3
   410
sl@3
   411
        private void buttonFill_Click(object sender, EventArgs e)
sl@3
   412
        {
sl@3
   413
            iDisplay.Fill();
sl@3
   414
            iDisplay.SwapBuffers();
sl@3
   415
        }
sl@3
   416
sl@3
   417
        private void trackBarBrightness_Scroll(object sender, EventArgs e)
sl@3
   418
        {
sl@48
   419
            cds.Brightness = trackBarBrightness.Value;
sl@9
   420
            Properties.Settings.Default.Save();
sl@3
   421
            iDisplay.SetBrightness(trackBarBrightness.Value);
sl@9
   422
sl@3
   423
        }
sl@7
   424
sl@48
   425
sl@48
   426
        /// <summary>
sl@48
   427
        /// CDS stands for Current Display Settings
sl@48
   428
        /// </summary>
sl@50
   429
        private DisplaySettings cds
sl@48
   430
        {
sl@48
   431
            get
sl@48
   432
            {
sl@50
   433
                DisplaysSettings settings = Properties.Settings.Default.DisplaySettings;
sl@51
   434
                if (settings == null)
sl@51
   435
                {
sl@51
   436
                    settings = new DisplaysSettings();
sl@51
   437
                    settings.Init();
sl@51
   438
                    Properties.Settings.Default.DisplaySettings = settings;
sl@51
   439
                }
sl@48
   440
sl@48
   441
                //Make sure all our settings have been created
sl@48
   442
                while (settings.Displays.Count <= Properties.Settings.Default.CurrentDisplayIndex)
sl@48
   443
                {
sl@50
   444
                    settings.Displays.Add(new DisplaySettings());
sl@48
   445
                }
sl@48
   446
sl@50
   447
                DisplaySettings displaySettings = settings.Displays[Properties.Settings.Default.CurrentDisplayIndex];
sl@48
   448
                return displaySettings;
sl@48
   449
            }
sl@48
   450
        }
sl@48
   451
sl@54
   452
        /// <summary>
sl@54
   453
        /// Check if the given font has a fixed character pitch.
sl@54
   454
        /// </summary>
sl@54
   455
        /// <param name="ft"></param>
sl@54
   456
        /// <returns>0.0f if this is not a monospace font, otherwise returns the character width.</returns>
sl@54
   457
        public float IsFixedWidth(Font ft)
sl@54
   458
        {
sl@54
   459
            Graphics g = CreateGraphics();
sl@54
   460
            char[] charSizes = new char[] { 'i', 'a', 'Z', '%', '#', 'a', 'B', 'l', 'm', ',', '.' };
sl@54
   461
            float charWidth = g.MeasureString("I", ft, Int32.MaxValue, StringFormat.GenericTypographic).Width;
sl@54
   462
sl@54
   463
            bool fixedWidth = true;
sl@54
   464
sl@54
   465
            foreach (char c in charSizes)
sl@54
   466
                if (g.MeasureString(c.ToString(), ft, Int32.MaxValue, StringFormat.GenericTypographic).Width != charWidth)
sl@54
   467
                    fixedWidth = false;
sl@54
   468
sl@54
   469
            if (fixedWidth)
sl@54
   470
            {
sl@54
   471
                return charWidth;
sl@54
   472
            }
sl@54
   473
sl@54
   474
            return 0.0f;
sl@54
   475
        }
sl@54
   476
sl@7
   477
        private void UpdateStatus()
sl@7
   478
        {
sl@48
   479
            //Synchronize UI with settings
sl@48
   480
            //Load settings
sl@54
   481
            checkBoxShowBorders.Checked = cds.ShowBorders;
sl@54
   482
            tableLayoutPanel.CellBorderStyle = (cds.ShowBorders ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
sl@60
   483
sl@60
   484
            //Set the proper font to each of our labels
sl@60
   485
            foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
sl@60
   486
            {
sl@60
   487
                ctrl.Font = cds.Font;
sl@60
   488
            }
sl@60
   489
sl@54
   490
            CheckFontHeight();
sl@48
   491
            checkBoxConnectOnStartup.Checked = Properties.Settings.Default.DisplayConnectOnStartup;
sl@48
   492
            checkBoxReverseScreen.Checked = cds.ReverseScreen;
sl@57
   493
            checkBoxInverseColors.Checked = cds.InverseColors;
sl@48
   494
            comboBoxDisplayType.SelectedIndex = cds.DisplayType;
sl@48
   495
            timer.Interval = cds.TimerInterval;
sl@48
   496
            maskedTextBoxTimerInterval.Text = cds.TimerInterval.ToString();
sl@58
   497
            //
sl@58
   498
            SetupPixelDelegates();
sl@48
   499
sl@7
   500
            if (iDisplay.IsOpen())
sl@7
   501
            {
sl@48
   502
                //Only setup brightness if display is open
sl@48
   503
                trackBarBrightness.Minimum = iDisplay.MinBrightness();
sl@48
   504
                trackBarBrightness.Maximum = iDisplay.MaxBrightness();
sl@48
   505
                trackBarBrightness.Value = cds.Brightness;
sl@48
   506
                trackBarBrightness.LargeChange = Math.Max(1, (iDisplay.MaxBrightness() - iDisplay.MinBrightness()) / 5);
sl@48
   507
                trackBarBrightness.SmallChange = 1;
sl@48
   508
                iDisplay.SetBrightness(cds.Brightness);
sl@48
   509
                //
sl@7
   510
                buttonFill.Enabled = true;
sl@7
   511
                buttonClear.Enabled = true;
sl@7
   512
                buttonOpen.Enabled = false;
sl@7
   513
                buttonClose.Enabled = true;
sl@7
   514
                trackBarBrightness.Enabled = true;
sl@10
   515
                toolStripStatusLabelConnect.Text = "Connected - " + iDisplay.Vendor() + " - " + iDisplay.Product();
sl@10
   516
                //+ " - " + iDisplay.SerialNumber();
sl@52
   517
sl@52
   518
                if (iDisplay.SupportPowerOnOff())
sl@52
   519
                {
sl@52
   520
                    buttonPowerOn.Enabled = true;
sl@52
   521
                    buttonPowerOff.Enabled = true;
sl@52
   522
                }
sl@52
   523
                else
sl@52
   524
                {
sl@52
   525
                    buttonPowerOn.Enabled = false;
sl@52
   526
                    buttonPowerOff.Enabled = false;
sl@52
   527
                }
sl@53
   528
sl@53
   529
                if (iDisplay.SupportClock())
sl@53
   530
                {
sl@53
   531
                    buttonShowClock.Enabled = true;
sl@53
   532
                    buttonHideClock.Enabled = true;
sl@53
   533
                }
sl@53
   534
                else
sl@53
   535
                {
sl@53
   536
                    buttonShowClock.Enabled = false;
sl@53
   537
                    buttonHideClock.Enabled = false;
sl@53
   538
                }
sl@7
   539
            }
sl@7
   540
            else
sl@7
   541
            {
sl@7
   542
                buttonFill.Enabled = false;
sl@7
   543
                buttonClear.Enabled = false;
sl@7
   544
                buttonOpen.Enabled = true;
sl@7
   545
                buttonClose.Enabled = false;
sl@7
   546
                trackBarBrightness.Enabled = false;
sl@52
   547
                buttonPowerOn.Enabled = false;
sl@52
   548
                buttonPowerOff.Enabled = false;
sl@53
   549
                buttonShowClock.Enabled = false;
sl@53
   550
                buttonHideClock.Enabled = false;
sl@9
   551
                toolStripStatusLabelConnect.Text = "Disconnected";
sl@48
   552
                toolStripStatusLabelPower.Text = "N/A";
sl@7
   553
            }
sl@7
   554
        }
sl@9
   555
sl@13
   556
sl@13
   557
sl@9
   558
        private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
sl@9
   559
        {
sl@16
   560
            //Save our show borders setting
sl@13
   561
            tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
sl@48
   562
            cds.ShowBorders = checkBoxShowBorders.Checked;
sl@9
   563
            Properties.Settings.Default.Save();
sl@57
   564
            CheckFontHeight();
sl@9
   565
        }
sl@13
   566
sl@13
   567
        private void checkBoxConnectOnStartup_CheckedChanged(object sender, EventArgs e)
sl@13
   568
        {
sl@16
   569
            //Save our connect on startup setting
sl@13
   570
            Properties.Settings.Default.DisplayConnectOnStartup = checkBoxConnectOnStartup.Checked;
sl@13
   571
            Properties.Settings.Default.Save();
sl@13
   572
        }
sl@13
   573
sl@16
   574
        private void checkBoxReverseScreen_CheckedChanged(object sender, EventArgs e)
sl@16
   575
        {
sl@16
   576
            //Save our reverse screen setting
sl@48
   577
            cds.ReverseScreen = checkBoxReverseScreen.Checked;
sl@16
   578
            Properties.Settings.Default.Save();
sl@58
   579
            SetupPixelDelegates();
sl@16
   580
        }
sl@16
   581
sl@57
   582
        private void checkBoxInverseColors_CheckedChanged(object sender, EventArgs e)
sl@57
   583
        {
sl@57
   584
            //Save our inverse colors setting
sl@57
   585
            cds.InverseColors = checkBoxInverseColors.Checked;
sl@57
   586
            Properties.Settings.Default.Save();
sl@58
   587
            SetupPixelDelegates();
sl@57
   588
        }
sl@57
   589
sl@14
   590
        private void MainForm_Resize(object sender, EventArgs e)
sl@14
   591
        {
sl@14
   592
            if (WindowState == FormWindowState.Minimized)
sl@14
   593
            {
sl@14
   594
                // Do some stuff
sl@14
   595
                //iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14
   596
                iCreateBitmap = true;
sl@14
   597
            }
sl@14
   598
        }
sl@14
   599
sl@17
   600
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
sl@17
   601
        {
sl@17
   602
            StopServer();
sl@32
   603
            e.Cancel = iClosing;
sl@17
   604
        }
sl@17
   605
sl@17
   606
        public void StartServer()
sl@17
   607
        {
sl@17
   608
            iServiceHost = new ServiceHost
sl@17
   609
                (
sl@55
   610
                    typeof(Session),
sl@20
   611
                    new Uri[] { new Uri("net.tcp://localhost:8001/") }
sl@17
   612
                );
sl@17
   613
sl@55
   614
            iServiceHost.AddServiceEndpoint(typeof(IService), new NetTcpBinding(SecurityMode.None, true), "DisplayService");
sl@17
   615
            iServiceHost.Open();
sl@17
   616
        }
sl@17
   617
sl@17
   618
        public void StopServer()
sl@17
   619
        {
sl@32
   620
            if (iClients.Count > 0 && !iClosing)
sl@29
   621
            {
sl@29
   622
                //Tell our clients
sl@32
   623
                iClosing = true;
sl@29
   624
                BroadcastCloseEvent();
sl@29
   625
            }
sl@32
   626
            else if (iClosing)
sl@32
   627
            {
sl@32
   628
                if (MessageBox.Show("Force exit?", "Waiting for clients...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
sl@32
   629
                {
sl@32
   630
                    iClosing = false; //We make sure we force close if asked twice
sl@32
   631
                }
sl@32
   632
            }
sl@32
   633
            else
sl@36
   634
            {
sl@32
   635
                //We removed that as it often lags for some reason
sl@32
   636
                //iServiceHost.Close();
sl@32
   637
            }
sl@17
   638
        }
sl@17
   639
sl@21
   640
        public void BroadcastCloseEvent()
sl@21
   641
        {
sl@31
   642
            Trace.TraceInformation("BroadcastCloseEvent - start");
sl@31
   643
sl@21
   644
            var inactiveClients = new List<string>();
sl@21
   645
            foreach (var client in iClients)
sl@21
   646
            {
sl@21
   647
                //if (client.Key != eventData.ClientName)
sl@21
   648
                {
sl@21
   649
                    try
sl@21
   650
                    {
sl@31
   651
                        Trace.TraceInformation("BroadcastCloseEvent - " + client.Key);
sl@33
   652
                        client.Value.Callback.OnCloseOrder(/*eventData*/);
sl@21
   653
                    }
sl@21
   654
                    catch (Exception ex)
sl@21
   655
                    {
sl@21
   656
                        inactiveClients.Add(client.Key);
sl@21
   657
                    }
sl@21
   658
                }
sl@21
   659
            }
sl@21
   660
sl@21
   661
            if (inactiveClients.Count > 0)
sl@21
   662
            {
sl@21
   663
                foreach (var client in inactiveClients)
sl@21
   664
                {
sl@21
   665
                    iClients.Remove(client);
sl@30
   666
                    Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(client, false)[0]);
sl@21
   667
                }
sl@21
   668
            }
sl@21
   669
        }
sl@21
   670
sl@25
   671
        private void buttonStartClient_Click(object sender, EventArgs e)
sl@25
   672
        {
sl@25
   673
            Thread clientThread = new Thread(SharpDisplayClient.Program.Main);
sl@25
   674
            clientThread.Start();
sl@36
   675
            BringToFront();
sl@25
   676
        }
sl@25
   677
sl@27
   678
        private void buttonSuspend_Click(object sender, EventArgs e)
sl@27
   679
        {
sl@52
   680
            LastTickTime = DateTime.Now; //Reset timer to prevent jump
sl@27
   681
            timer.Enabled = !timer.Enabled;
sl@27
   682
            if (!timer.Enabled)
sl@27
   683
            {
sl@52
   684
                buttonSuspend.Text = "Run";
sl@27
   685
            }
sl@27
   686
            else
sl@27
   687
            {
sl@27
   688
                buttonSuspend.Text = "Pause";
sl@27
   689
            }
sl@27
   690
        }
sl@27
   691
sl@29
   692
        private void buttonCloseClients_Click(object sender, EventArgs e)
sl@29
   693
        {
sl@29
   694
            BroadcastCloseEvent();
sl@29
   695
        }
sl@29
   696
sl@30
   697
        private void treeViewClients_AfterSelect(object sender, TreeViewEventArgs e)
sl@30
   698
        {
sl@21
   699
sl@30
   700
        }
sl@30
   701
sl@36
   702
sl@30
   703
        /// <summary>
sl@36
   704
        ///
sl@30
   705
        /// </summary>
sl@30
   706
        /// <param name="aSessionId"></param>
sl@30
   707
        /// <param name="aCallback"></param>
sl@55
   708
        public void AddClientThreadSafe(string aSessionId, ICallback aCallback)
sl@30
   709
        {
sl@33
   710
            if (this.InvokeRequired)
sl@30
   711
            {
sl@30
   712
                //Not in the proper thread, invoke ourselves
sl@30
   713
                AddClientDelegate d = new AddClientDelegate(AddClientThreadSafe);
sl@30
   714
                this.Invoke(d, new object[] { aSessionId, aCallback });
sl@30
   715
            }
sl@30
   716
            else
sl@30
   717
            {
sl@30
   718
                //We are in the proper thread
sl@30
   719
                //Add this session to our collection of clients
sl@33
   720
                ClientData newClient = new ClientData(aSessionId, aCallback);
sl@33
   721
                Program.iMainForm.iClients.Add(aSessionId, newClient);
sl@30
   722
                //Add this session to our UI
sl@33
   723
                UpdateClientTreeViewNode(newClient);
sl@30
   724
            }
sl@30
   725
        }
sl@30
   726
sl@30
   727
        /// <summary>
sl@36
   728
        ///
sl@30
   729
        /// </summary>
sl@30
   730
        /// <param name="aSessionId"></param>
sl@30
   731
        public void RemoveClientThreadSafe(string aSessionId)
sl@30
   732
        {
sl@33
   733
            if (this.InvokeRequired)
sl@30
   734
            {
sl@30
   735
                //Not in the proper thread, invoke ourselves
sl@30
   736
                RemoveClientDelegate d = new RemoveClientDelegate(RemoveClientThreadSafe);
sl@30
   737
                this.Invoke(d, new object[] { aSessionId });
sl@30
   738
            }
sl@30
   739
            else
sl@30
   740
            {
sl@30
   741
                //We are in the proper thread
sl@33
   742
                //Remove this session from both client collection and UI tree view
sl@30
   743
                if (Program.iMainForm.iClients.Keys.Contains(aSessionId))
sl@30
   744
                {
sl@30
   745
                    Program.iMainForm.iClients.Remove(aSessionId);
sl@30
   746
                    Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(aSessionId, false)[0]);
sl@32
   747
                }
sl@32
   748
sl@32
   749
                if (iClosing && iClients.Count == 0)
sl@32
   750
                {
sl@32
   751
                    //We were closing our form
sl@32
   752
                    //All clients are now closed
sl@32
   753
                    //Just resume our close operation
sl@32
   754
                    iClosing = false;
sl@32
   755
                    Close();
sl@32
   756
                }
sl@30
   757
            }
sl@30
   758
        }
sl@30
   759
sl@30
   760
        /// <summary>
sl@36
   761
        ///
sl@30
   762
        /// </summary>
sl@62
   763
        /// <param name="aSessionId"></param>
sl@62
   764
        /// <param name="aTextField"></param>
sl@62
   765
        public void SetClientLayoutThreadSafe(string aSessionId, TableLayout aLayout)
sl@62
   766
        {
sl@62
   767
            if (this.InvokeRequired)
sl@62
   768
            {
sl@62
   769
                //Not in the proper thread, invoke ourselves
sl@62
   770
                SetLayoutDelegate d = new SetLayoutDelegate(SetClientLayoutThreadSafe);
sl@62
   771
                this.Invoke(d, new object[] { aSessionId, aLayout });
sl@62
   772
            }
sl@62
   773
            else
sl@62
   774
            {
sl@62
   775
                ClientData client = iClients[aSessionId];
sl@62
   776
                if (client != null)
sl@62
   777
                {
sl@62
   778
                    client.Layout = aLayout;
sl@62
   779
                    UpdateTableLayoutPanel(client.Layout.ColumnCount, client.Layout.RowCount);
sl@62
   780
                    //
sl@62
   781
                    UpdateClientTreeViewNode(client);
sl@62
   782
                }
sl@62
   783
            }
sl@62
   784
        }
sl@62
   785
sl@62
   786
        /// <summary>
sl@62
   787
        ///
sl@62
   788
        /// </summary>
sl@30
   789
        /// <param name="aLineIndex"></param>
sl@30
   790
        /// <param name="aText"></param>
sl@43
   791
        public void SetTextThreadSafe(string aSessionId, TextField aTextField)
sl@30
   792
        {
sl@33
   793
            if (this.InvokeRequired)
sl@30
   794
            {
sl@30
   795
                //Not in the proper thread, invoke ourselves
sl@30
   796
                SetTextDelegate d = new SetTextDelegate(SetTextThreadSafe);
sl@43
   797
                this.Invoke(d, new object[] { aSessionId, aTextField });
sl@30
   798
            }
sl@30
   799
            else
sl@30
   800
            {
sl@34
   801
                ClientData client = iClients[aSessionId];
sl@34
   802
                if (client != null)
sl@30
   803
                {
sl@34
   804
                    //Make sure all our texts are in place
sl@43
   805
                    while (client.Texts.Count < (aTextField.Index + 1))
sl@34
   806
                    {
sl@43
   807
                        //Add a text field with proper index
sl@43
   808
                        client.Texts.Add(new TextField(client.Texts.Count));
sl@34
   809
                    }
sl@43
   810
                    client.Texts[aTextField.Index] = aTextField;
sl@34
   811
sl@34
   812
                    //We are in the proper thread
sl@60
   813
                    MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[aTextField.Index];
sl@60
   814
                    label.Text = aTextField.Text;
sl@60
   815
                    label.TextAlign = aTextField.Alignment;
sl@60
   816
                    //
sl@34
   817
                    UpdateClientTreeViewNode(client);
sl@30
   818
                }
sl@30
   819
            }
sl@30
   820
        }
sl@30
   821
sl@30
   822
        /// <summary>
sl@36
   823
        ///
sl@30
   824
        /// </summary>
sl@30
   825
        /// <param name="aTexts"></param>
sl@43
   826
        public void SetTextsThreadSafe(string aSessionId, System.Collections.Generic.IList<TextField> aTextFields)
sl@30
   827
        {
sl@33
   828
            if (this.InvokeRequired)
sl@30
   829
            {
sl@30
   830
                //Not in the proper thread, invoke ourselves
sl@30
   831
                SetTextsDelegate d = new SetTextsDelegate(SetTextsThreadSafe);
sl@43
   832
                this.Invoke(d, new object[] { aSessionId, aTextFields });
sl@30
   833
            }
sl@30
   834
            else
sl@30
   835
            {
sl@43
   836
                //We are in the proper thread
sl@34
   837
                ClientData client = iClients[aSessionId];
sl@34
   838
                if (client != null)
sl@30
   839
                {
sl@43
   840
                    //Populate our client with the given text fields
sl@34
   841
                    int j = 0;
sl@43
   842
                    foreach (TextField textField in aTextFields)
sl@30
   843
                    {
sl@34
   844
                        if (client.Texts.Count < (j + 1))
sl@34
   845
                        {
sl@43
   846
                            client.Texts.Add(textField);
sl@34
   847
                        }
sl@34
   848
                        else
sl@34
   849
                        {
sl@43
   850
                            client.Texts[j] = textField;
sl@34
   851
                        }
sl@34
   852
                        j++;
sl@54
   853
                    }
sl@34
   854
                    //Only support two lines for now
sl@43
   855
                    for (int i = 0; i < aTextFields.Count; i++)
sl@30
   856
                    {
sl@60
   857
                        MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[aTextFields[i].Index];
sl@60
   858
                        label.Text = aTextFields[i].Text;
sl@60
   859
                        label.TextAlign = aTextFields[i].Alignment;
sl@30
   860
                    }
sl@34
   861
sl@34
   862
sl@34
   863
                    UpdateClientTreeViewNode(client);
sl@30
   864
                }
sl@30
   865
            }
sl@32
   866
        }
sl@30
   867
sl@32
   868
sl@32
   869
        /// <summary>
sl@36
   870
        ///
sl@32
   871
        /// </summary>
sl@32
   872
        /// <param name="aSessionId"></param>
sl@32
   873
        /// <param name="aName"></param>
sl@32
   874
        public void SetClientNameThreadSafe(string aSessionId, string aName)
sl@32
   875
        {
sl@32
   876
            if (this.InvokeRequired)
sl@32
   877
            {
sl@32
   878
                //Not in the proper thread, invoke ourselves
sl@32
   879
                SetClientNameDelegate d = new SetClientNameDelegate(SetClientNameThreadSafe);
sl@32
   880
                this.Invoke(d, new object[] { aSessionId, aName });
sl@32
   881
            }
sl@32
   882
            else
sl@32
   883
            {
sl@32
   884
                //We are in the proper thread
sl@33
   885
                //Get our client
sl@33
   886
                ClientData client = iClients[aSessionId];
sl@33
   887
                if (client != null)
sl@32
   888
                {
sl@33
   889
                    //Set its name
sl@33
   890
                    client.Name = aName;
sl@33
   891
                    //Update our tree-view
sl@33
   892
                    UpdateClientTreeViewNode(client);
sl@33
   893
                }
sl@33
   894
            }
sl@33
   895
        }
sl@33
   896
sl@33
   897
        /// <summary>
sl@36
   898
        ///
sl@33
   899
        /// </summary>
sl@33
   900
        /// <param name="aClient"></param>
sl@33
   901
        private void UpdateClientTreeViewNode(ClientData aClient)
sl@33
   902
        {
sl@33
   903
            if (aClient == null)
sl@33
   904
            {
sl@33
   905
                return;
sl@33
   906
            }
sl@33
   907
sl@33
   908
            TreeNode node = null;
sl@33
   909
            //Check that our client node already exists
sl@33
   910
            //Get our client root node using its key which is our session ID
sl@33
   911
            TreeNode[] nodes = treeViewClients.Nodes.Find(aClient.SessionId, false);
sl@33
   912
            if (nodes.Count()>0)
sl@33
   913
            {
sl@33
   914
                //We already have a node for that client
sl@33
   915
                node = nodes[0];
sl@33
   916
                //Clear children as we are going to recreate them below
sl@33
   917
                node.Nodes.Clear();
sl@33
   918
            }
sl@33
   919
            else
sl@33
   920
            {
sl@33
   921
                //Client node does not exists create a new one
sl@33
   922
                treeViewClients.Nodes.Add(aClient.SessionId, aClient.SessionId);
sl@33
   923
                node = treeViewClients.Nodes.Find(aClient.SessionId, false)[0];
sl@33
   924
            }
sl@33
   925
sl@33
   926
            if (node != null)
sl@33
   927
            {
sl@33
   928
                //Change its name
sl@33
   929
                if (aClient.Name != "")
sl@33
   930
                {
sl@33
   931
                    //We have a name, us it as text for our root node
sl@33
   932
                    node.Text = aClient.Name;
sl@32
   933
                    //Add a child with SessionId
sl@33
   934
                    node.Nodes.Add(new TreeNode(aClient.SessionId));
sl@33
   935
                }
sl@33
   936
                else
sl@33
   937
                {
sl@33
   938
                    //No name, use session ID instead
sl@33
   939
                    node.Text = aClient.SessionId;
sl@33
   940
                }
sl@36
   941
sl@33
   942
                if (aClient.Texts.Count > 0)
sl@33
   943
                {
sl@33
   944
                    //Create root node for our texts
sl@33
   945
                    TreeNode textsRoot = new TreeNode("Text");
sl@33
   946
                    node.Nodes.Add(textsRoot);
sl@33
   947
                    //For each text add a new entry
sl@43
   948
                    foreach (TextField field in aClient.Texts)
sl@33
   949
                    {
sl@43
   950
                        textsRoot.Nodes.Add(new TreeNode(field.Text));
sl@33
   951
                    }
sl@32
   952
                }
sl@34
   953
sl@34
   954
                node.ExpandAll();
sl@32
   955
            }
sl@30
   956
        }
sl@17
   957
sl@38
   958
        private void buttonAddRow_Click(object sender, EventArgs e)
sl@38
   959
        {
sl@38
   960
            if (tableLayoutPanel.RowCount < 6)
sl@38
   961
            {
sl@62
   962
                UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount, tableLayoutPanel.RowCount + 1);
sl@38
   963
            }
sl@38
   964
        }
sl@38
   965
sl@38
   966
        private void buttonRemoveRow_Click(object sender, EventArgs e)
sl@38
   967
        {
sl@38
   968
            if (tableLayoutPanel.RowCount > 1)
sl@38
   969
            {
sl@62
   970
                UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount, tableLayoutPanel.RowCount - 1);
sl@38
   971
            }
sl@60
   972
sl@60
   973
            UpdateTableLayoutRowStyles();
sl@60
   974
        }
sl@60
   975
sl@62
   976
        private void buttonAddColumn_Click(object sender, EventArgs e)
sl@62
   977
        {
sl@62
   978
            if (tableLayoutPanel.ColumnCount < 8)
sl@62
   979
            {
sl@62
   980
                UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount + 1, tableLayoutPanel.RowCount);
sl@62
   981
            }
sl@62
   982
        }
sl@62
   983
sl@62
   984
        private void buttonRemoveColumn_Click(object sender, EventArgs e)
sl@62
   985
        {
sl@62
   986
            if (tableLayoutPanel.ColumnCount > 1)
sl@62
   987
            {
sl@62
   988
                UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount - 1, tableLayoutPanel.RowCount);
sl@62
   989
            }
sl@62
   990
        }
sl@62
   991
sl@62
   992
sl@60
   993
        /// <summary>
sl@60
   994
        /// Update our table layout row styles to make sure each rows have similar height
sl@60
   995
        /// </summary>
sl@60
   996
        private void UpdateTableLayoutRowStyles()
sl@60
   997
        {
sl@60
   998
            foreach (RowStyle rowStyle in tableLayoutPanel.RowStyles)
sl@60
   999
            {
sl@60
  1000
                rowStyle.SizeType = SizeType.Percent;
sl@60
  1001
                rowStyle.Height = 100 / tableLayoutPanel.RowCount;
sl@60
  1002
            }
sl@60
  1003
        }
sl@60
  1004
sl@60
  1005
        /// <summary>
sl@61
  1006
        /// Empty and recreate our table layout with the given number of columns and rows.
sl@61
  1007
        /// Sizes of rows and columns are uniform.
sl@60
  1008
        /// </summary>
sl@60
  1009
        /// <param name="aColumn"></param>
sl@60
  1010
        /// <param name="aRow"></param>
sl@62
  1011
        private void UpdateTableLayoutPanel(int aColumn, int aRow)
sl@60
  1012
        {
sl@61
  1013
            tableLayoutPanel.Controls.Clear();
sl@61
  1014
            tableLayoutPanel.RowStyles.Clear();
sl@61
  1015
            tableLayoutPanel.ColumnStyles.Clear();
sl@61
  1016
            tableLayoutPanel.RowCount = 0;
sl@61
  1017
            tableLayoutPanel.ColumnCount = 0;
sl@60
  1018
sl@61
  1019
            while (tableLayoutPanel.RowCount < aRow)
sl@61
  1020
            {
sl@61
  1021
                tableLayoutPanel.RowCount++;
sl@61
  1022
            }
sl@60
  1023
sl@61
  1024
            while (tableLayoutPanel.ColumnCount < aColumn)
sl@61
  1025
            {
sl@61
  1026
                tableLayoutPanel.ColumnCount++;
sl@61
  1027
            }
sl@61
  1028
sl@61
  1029
            for (int i = 0; i < tableLayoutPanel.ColumnCount; i++)
sl@61
  1030
            {
sl@61
  1031
                //Create our column styles
sl@61
  1032
                this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100 / tableLayoutPanel.ColumnCount));
sl@61
  1033
sl@61
  1034
                for (int j = 0; j < tableLayoutPanel.RowCount; j++)
sl@61
  1035
                {
sl@61
  1036
                    if (i == 0)
sl@61
  1037
                    {
sl@61
  1038
                        //Create our row styles
sl@61
  1039
                        this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100 / tableLayoutPanel.RowCount));
sl@61
  1040
                    }
sl@61
  1041
sl@61
  1042
                    MarqueeLabel control = new SharpDisplayManager.MarqueeLabel();
sl@61
  1043
                    control.AutoEllipsis = true;
sl@61
  1044
                    control.AutoSize = true;
sl@61
  1045
                    control.BackColor = System.Drawing.Color.Transparent;
sl@61
  1046
                    control.Dock = System.Windows.Forms.DockStyle.Fill;
sl@61
  1047
                    control.Location = new System.Drawing.Point(1, 1);
sl@61
  1048
                    control.Margin = new System.Windows.Forms.Padding(0);
sl@61
  1049
                    control.Name = "marqueeLabelCol" + aColumn + "Row" + aRow;
sl@61
  1050
                    control.OwnTimer = false;
sl@61
  1051
                    control.PixelsPerSecond = 64;
sl@61
  1052
                    control.Separator = "|";
sl@61
  1053
                    //control.Size = new System.Drawing.Size(254, 30);
sl@61
  1054
                    //control.TabIndex = 2;
sl@61
  1055
                    control.Font = cds.Font;
sl@61
  1056
                    control.Text = "ABCDEFGHIJKLMNOPQRST-0123456789";
sl@61
  1057
                    control.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
sl@61
  1058
                    control.UseCompatibleTextRendering = true;
sl@61
  1059
                    //
sl@61
  1060
                    tableLayoutPanel.Controls.Add(control, i, j);
sl@61
  1061
                }
sl@61
  1062
            }
sl@38
  1063
sl@62
  1064
            CheckFontHeight();
sl@38
  1065
        }
sl@38
  1066
sl@41
  1067
        private void buttonAlignLeft_Click(object sender, EventArgs e)
sl@41
  1068
        {
sl@60
  1069
            foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
sl@60
  1070
            {
sl@60
  1071
                ctrl.TextAlign = ContentAlignment.MiddleLeft;
sl@60
  1072
            }
sl@41
  1073
        }
sl@41
  1074
sl@41
  1075
        private void buttonAlignCenter_Click(object sender, EventArgs e)
sl@41
  1076
        {
sl@60
  1077
            foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
sl@60
  1078
            {
sl@60
  1079
                ctrl.TextAlign = ContentAlignment.MiddleCenter;
sl@60
  1080
            }
sl@41
  1081
        }
sl@41
  1082
sl@41
  1083
        private void buttonAlignRight_Click(object sender, EventArgs e)
sl@41
  1084
        {
sl@60
  1085
            foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
sl@60
  1086
            {
sl@60
  1087
                ctrl.TextAlign = ContentAlignment.MiddleRight;
sl@60
  1088
            }
sl@41
  1089
        }
sl@36
  1090
sl@46
  1091
        private void comboBoxDisplayType_SelectedIndexChanged(object sender, EventArgs e)
sl@46
  1092
        {
sl@48
  1093
            Properties.Settings.Default.CurrentDisplayIndex = comboBoxDisplayType.SelectedIndex;
sl@48
  1094
            cds.DisplayType = comboBoxDisplayType.SelectedIndex;
sl@46
  1095
            Properties.Settings.Default.Save();
sl@51
  1096
            if (iDisplay.IsOpen())
sl@51
  1097
            {
sl@51
  1098
                OpenDisplayConnection();
sl@51
  1099
            }
sl@51
  1100
            else
sl@51
  1101
            {
sl@51
  1102
                UpdateStatus();
sl@51
  1103
            }
sl@46
  1104
        }
sl@46
  1105
sl@47
  1106
sl@47
  1107
        private void maskedTextBoxTimerInterval_TextChanged(object sender, EventArgs e)
sl@47
  1108
        {
sl@47
  1109
            if (maskedTextBoxTimerInterval.Text != "")
sl@47
  1110
            {
sl@51
  1111
                int interval = Convert.ToInt32(maskedTextBoxTimerInterval.Text);
sl@51
  1112
sl@51
  1113
                if (interval > 0)
sl@51
  1114
                {
sl@51
  1115
                    timer.Interval = interval;
sl@51
  1116
                    cds.TimerInterval = timer.Interval;
sl@51
  1117
                    Properties.Settings.Default.Save();
sl@51
  1118
                }
sl@47
  1119
            }
sl@47
  1120
        }
sl@47
  1121
sl@52
  1122
        private void buttonPowerOn_Click(object sender, EventArgs e)
sl@52
  1123
        {
sl@52
  1124
            iDisplay.PowerOn();
sl@52
  1125
        }
sl@52
  1126
sl@52
  1127
        private void buttonPowerOff_Click(object sender, EventArgs e)
sl@52
  1128
        {
sl@52
  1129
            iDisplay.PowerOff();
sl@52
  1130
        }
sl@52
  1131
sl@53
  1132
        private void buttonShowClock_Click(object sender, EventArgs e)
sl@53
  1133
        {
sl@53
  1134
            iDisplay.ShowClock();
sl@53
  1135
        }
sl@53
  1136
sl@53
  1137
        private void buttonHideClock_Click(object sender, EventArgs e)
sl@53
  1138
        {
sl@53
  1139
            iDisplay.HideClock();
sl@53
  1140
        }
sl@0
  1141
    }
sl@34
  1142
sl@34
  1143
    /// <summary>
sl@34
  1144
    /// A UI thread copy of a client relevant data.
sl@34
  1145
    /// Keeping this copy in the UI thread helps us deal with threading issues.
sl@34
  1146
    /// </summary>
sl@34
  1147
    public class ClientData
sl@34
  1148
    {
sl@55
  1149
        public ClientData(string aSessionId, ICallback aCallback)
sl@34
  1150
        {
sl@34
  1151
            SessionId = aSessionId;
sl@34
  1152
            Name = "";
sl@43
  1153
            Texts = new List<TextField>();
sl@62
  1154
            Layout = new TableLayout(1, 2); //Default to one column and two rows
sl@34
  1155
            Callback = aCallback;
sl@34
  1156
        }
sl@34
  1157
sl@34
  1158
        public string SessionId { get; set; }
sl@34
  1159
        public string Name { get; set; }
sl@43
  1160
        public List<TextField> Texts { get; set; }
sl@62
  1161
        public TableLayout Layout { get; set; }
sl@55
  1162
        public ICallback Callback { get; set; }
sl@34
  1163
    }
sl@0
  1164
}