Adding bitmap field object.
2 using System.Collections.Generic;
3 using System.ComponentModel;
8 using System.Threading.Tasks;
9 using System.Windows.Forms;
11 using CodeProject.Dialog;
12 using System.Drawing.Imaging;
13 using System.ServiceModel;
14 using System.Threading;
15 using System.Diagnostics;
17 using SharpDisplayClient;
20 namespace SharpDisplayManager
23 public delegate uint ColorProcessingDelegate(int aX, int aY, uint aPixel);
24 public delegate int CoordinateTranslationDelegate(System.Drawing.Bitmap aBmp, int aInt);
25 //Delegates are used for our thread safe method
26 public delegate void AddClientDelegate(string aSessionId, ICallback aCallback);
27 public delegate void RemoveClientDelegate(string aSessionId);
28 public delegate void SetTextDelegate(string SessionId, TextField aTextField);
29 public delegate void SetLayoutDelegate(string SessionId, TableLayout aLayout);
30 public delegate void SetTextsDelegate(string SessionId, System.Collections.Generic.IList<TextField> aTextFields);
31 public delegate void SetClientNameDelegate(string aSessionId, string aName);
35 /// Our Display manager main form
37 public partial class MainForm : Form
40 DateTime LastTickTime;
42 System.Drawing.Bitmap iBmp;
43 bool iCreateBitmap; //Workaround render to bitmap issues when minimized
44 ServiceHost iServiceHost;
45 // Our collection of clients sorted by session id.
46 public Dictionary<string, ClientData> iClients;
47 // The name of the client which informations are currently displayed.
48 public string iCurrentClientSessionId;
49 ClientData iCurrentClientData;
52 //Function pointer for pixel color filtering
53 ColorProcessingDelegate iColorFx;
54 //Function pointer for pixel X coordinate intercept
55 CoordinateTranslationDelegate iScreenX;
56 //Function pointer for pixel Y coordinate intercept
57 CoordinateTranslationDelegate iScreenY;
61 iCurrentClientSessionId = "";
62 iCurrentClientData = null;
63 LastTickTime = DateTime.Now;
64 iDisplay = new Display();
65 iClients = new Dictionary<string, ClientData>();
67 InitializeComponent();
69 //We have a bug when drawing minimized and reusing our bitmap
70 iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
71 iCreateBitmap = false;
74 private void MainForm_Load(object sender, EventArgs e)
78 if (Properties.Settings.Default.DisplayConnectOnStartup)
80 OpenDisplayConnection();
85 /// Set our current client.
86 /// This will take care of applying our client layout and set data fields.
88 /// <param name="aSessionId"></param>
89 void SetCurrentClient(string aSessionId)
91 if (aSessionId == iCurrentClientSessionId)
93 //Given client is already the current one.
94 //Don't bother changing anything then.
98 //Set current client ID.
99 iCurrentClientSessionId = aSessionId;
100 //Fetch and set current client data.
101 iCurrentClientData = iClients[aSessionId];
102 //Apply layout and set data fields.
103 UpdateTableLayoutPanel(iCurrentClientData);
106 private void buttonFont_Click(object sender, EventArgs e)
108 //fontDialog.ShowColor = true;
109 //fontDialog.ShowApply = true;
110 fontDialog.ShowEffects = true;
111 MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[0];
112 fontDialog.Font = label.Font;
114 fontDialog.FixedPitchOnly = checkBoxFixedPitchFontOnly.Checked;
116 //fontDialog.ShowHelp = true;
118 //fontDlg.MaxSize = 40;
119 //fontDlg.MinSize = 22;
121 //fontDialog.Parent = this;
122 //fontDialog.StartPosition = FormStartPosition.CenterParent;
124 //DlgBox.ShowDialog(fontDialog);
126 //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
127 if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
130 //MsgBox.Show("MessageBox MsgBox", "MsgBox caption");
132 //MessageBox.Show("Ok");
133 foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
135 ctrl.Font = fontDialog.Font;
137 cds.Font = fontDialog.Font;
138 Properties.Settings.Default.Save();
147 void CheckFontHeight()
149 //Show font height and width
150 labelFontHeight.Text = "Font height: " + cds.Font.Height;
151 float charWidth = IsFixedWidth(cds.Font);
152 if (charWidth == 0.0f)
154 labelFontWidth.Visible = false;
158 labelFontWidth.Visible = true;
159 labelFontWidth.Text = "Font width: " + charWidth;
162 //Now check font height and show a warning if needed.
163 MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[0];
164 if (label.Font.Height > label.Height)
166 labelWarning.Text = "WARNING: Selected font is too height by " + (label.Font.Height - label.Height) + " pixels!";
167 labelWarning.Visible = true;
171 labelWarning.Visible = false;
176 private void buttonCapture_Click(object sender, EventArgs e)
178 System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height);
179 tableLayoutPanel.DrawToBitmap(bmp, tableLayoutPanel.ClientRectangle);
180 //Bitmap bmpToSave = new Bitmap(bmp);
181 bmp.Save("D:\\capture.png");
183 ((MarqueeLabel)tableLayoutPanel.Controls[0]).Text = "Captured";
186 string outputFileName = "d:\\capture.png";
187 using (MemoryStream memory = new MemoryStream())
189 using (FileStream fs = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
191 bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
192 byte[] bytes = memory.ToArray();
193 fs.Write(bytes, 0, bytes.Length);
200 private void CheckForRequestResults()
202 if (iDisplay.IsRequestPending())
204 switch (iDisplay.AttemptRequestCompletion())
206 case Display.TMiniDisplayRequest.EMiniDisplayRequestFirmwareRevision:
207 toolStripStatusLabelConnect.Text += " v" + iDisplay.FirmwareRevision();
208 //Issue next request then
209 iDisplay.RequestPowerSupplyStatus();
212 case Display.TMiniDisplayRequest.EMiniDisplayRequestPowerSupplyStatus:
213 if (iDisplay.PowerSupplyStatus())
215 toolStripStatusLabelPower.Text = "ON";
219 toolStripStatusLabelPower.Text = "OFF";
221 //Issue next request then
222 iDisplay.RequestDeviceId();
225 case Display.TMiniDisplayRequest.EMiniDisplayRequestDeviceId:
226 toolStripStatusLabelConnect.Text += " - " + iDisplay.DeviceId();
227 //No more request to issue
233 public static uint ColorWhiteIsOn(int aX, int aY, uint aPixel)
235 if ((aPixel & 0x00FFFFFF) == 0x00FFFFFF)
242 public static uint ColorUntouched(int aX, int aY, uint aPixel)
247 public static uint ColorInversed(int aX, int aY, uint aPixel)
252 public static uint ColorChessboard(int aX, int aY, uint aPixel)
254 if ((aX % 2 == 0) && (aY % 2 == 0))
258 else if ((aX % 2 != 0) && (aY % 2 != 0))
266 public static int ScreenReversedX(System.Drawing.Bitmap aBmp, int aX)
268 return aBmp.Width - aX - 1;
271 public int ScreenReversedY(System.Drawing.Bitmap aBmp, int aY)
273 return iBmp.Height - aY - 1;
276 public int ScreenX(System.Drawing.Bitmap aBmp, int aX)
281 public int ScreenY(System.Drawing.Bitmap aBmp, int aY)
287 /// Select proper pixel delegates according to our current settings.
289 private void SetupPixelDelegates()
291 //Select our pixel processing routine
292 if (cds.InverseColors)
294 //iColorFx = ColorChessboard;
295 iColorFx = ColorInversed;
299 iColorFx = ColorWhiteIsOn;
302 //Select proper coordinate translation functions
303 //We used delegate/function pointer to support reverse screen without doing an extra test on each pixels
304 if (cds.ReverseScreen)
306 iScreenX = ScreenReversedX;
307 iScreenY = ScreenReversedY;
317 //This is our timer tick responsible to perform our render
318 private void timer_Tick(object sender, EventArgs e)
320 //Update our animations
321 DateTime NewTickTime = DateTime.Now;
323 //Update animation for all our marquees
324 foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
326 ctrl.UpdateAnimation(LastTickTime, NewTickTime);
331 if (iDisplay.IsOpen())
333 CheckForRequestResults();
338 iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
340 tableLayoutPanel.DrawToBitmap(iBmp, tableLayoutPanel.ClientRectangle);
341 //iBmp.Save("D:\\capture.png");
343 //Send it to our display
344 for (int i = 0; i < iBmp.Width; i++)
346 for (int j = 0; j < iBmp.Height; j++)
350 //Get our processed pixel coordinates
351 int x = iScreenX(iBmp, i);
352 int y = iScreenY(iBmp, j);
354 uint color = (uint)iBmp.GetPixel(i, j).ToArgb();
355 //Apply color effects
356 color = iColorFx(x,y,color);
358 iDisplay.SetPixel(x, y, color);
363 iDisplay.SwapBuffers();
367 //Compute instant FPS
368 toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " / " + (1000/timer.Interval).ToString() + " FPS";
370 LastTickTime = NewTickTime;
374 private void OpenDisplayConnection()
376 CloseDisplayConnection();
378 if (iDisplay.Open((Display.TMiniDisplayType)cds.DisplayType))
381 iDisplay.RequestFirmwareRevision();
386 toolStripStatusLabelConnect.Text = "Connection error";
390 private void CloseDisplayConnection()
396 private void buttonOpen_Click(object sender, EventArgs e)
398 OpenDisplayConnection();
401 private void buttonClose_Click(object sender, EventArgs e)
403 CloseDisplayConnection();
406 private void buttonClear_Click(object sender, EventArgs e)
409 iDisplay.SwapBuffers();
412 private void buttonFill_Click(object sender, EventArgs e)
415 iDisplay.SwapBuffers();
418 private void trackBarBrightness_Scroll(object sender, EventArgs e)
420 cds.Brightness = trackBarBrightness.Value;
421 Properties.Settings.Default.Save();
422 iDisplay.SetBrightness(trackBarBrightness.Value);
428 /// CDS stands for Current Display Settings
430 private DisplaySettings cds
434 DisplaysSettings settings = Properties.Settings.Default.DisplaysSettings;
435 if (settings == null)
437 settings = new DisplaysSettings();
439 Properties.Settings.Default.DisplaysSettings = settings;
442 //Make sure all our settings have been created
443 while (settings.Displays.Count <= Properties.Settings.Default.CurrentDisplayIndex)
445 settings.Displays.Add(new DisplaySettings());
448 DisplaySettings displaySettings = settings.Displays[Properties.Settings.Default.CurrentDisplayIndex];
449 return displaySettings;
454 /// Check if the given font has a fixed character pitch.
456 /// <param name="ft"></param>
457 /// <returns>0.0f if this is not a monospace font, otherwise returns the character width.</returns>
458 public float IsFixedWidth(Font ft)
460 Graphics g = CreateGraphics();
461 char[] charSizes = new char[] { 'i', 'a', 'Z', '%', '#', 'a', 'B', 'l', 'm', ',', '.' };
462 float charWidth = g.MeasureString("I", ft, Int32.MaxValue, StringFormat.GenericTypographic).Width;
464 bool fixedWidth = true;
466 foreach (char c in charSizes)
467 if (g.MeasureString(c.ToString(), ft, Int32.MaxValue, StringFormat.GenericTypographic).Width != charWidth)
478 private void UpdateStatus()
480 //Synchronize UI with settings
482 checkBoxShowBorders.Checked = cds.ShowBorders;
483 tableLayoutPanel.CellBorderStyle = (cds.ShowBorders ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
485 //Set the proper font to each of our labels
486 foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
488 ctrl.Font = cds.Font;
492 checkBoxConnectOnStartup.Checked = Properties.Settings.Default.DisplayConnectOnStartup;
493 checkBoxReverseScreen.Checked = cds.ReverseScreen;
494 checkBoxInverseColors.Checked = cds.InverseColors;
495 comboBoxDisplayType.SelectedIndex = cds.DisplayType;
496 timer.Interval = cds.TimerInterval;
497 maskedTextBoxTimerInterval.Text = cds.TimerInterval.ToString();
499 SetupPixelDelegates();
501 if (iDisplay.IsOpen())
503 //Only setup brightness if display is open
504 trackBarBrightness.Minimum = iDisplay.MinBrightness();
505 trackBarBrightness.Maximum = iDisplay.MaxBrightness();
506 trackBarBrightness.Value = cds.Brightness;
507 trackBarBrightness.LargeChange = Math.Max(1, (iDisplay.MaxBrightness() - iDisplay.MinBrightness()) / 5);
508 trackBarBrightness.SmallChange = 1;
509 iDisplay.SetBrightness(cds.Brightness);
511 buttonFill.Enabled = true;
512 buttonClear.Enabled = true;
513 buttonOpen.Enabled = false;
514 buttonClose.Enabled = true;
515 trackBarBrightness.Enabled = true;
516 toolStripStatusLabelConnect.Text = "Connected - " + iDisplay.Vendor() + " - " + iDisplay.Product();
517 //+ " - " + iDisplay.SerialNumber();
519 if (iDisplay.SupportPowerOnOff())
521 buttonPowerOn.Enabled = true;
522 buttonPowerOff.Enabled = true;
526 buttonPowerOn.Enabled = false;
527 buttonPowerOff.Enabled = false;
530 if (iDisplay.SupportClock())
532 buttonShowClock.Enabled = true;
533 buttonHideClock.Enabled = true;
537 buttonShowClock.Enabled = false;
538 buttonHideClock.Enabled = false;
543 buttonFill.Enabled = false;
544 buttonClear.Enabled = false;
545 buttonOpen.Enabled = true;
546 buttonClose.Enabled = false;
547 trackBarBrightness.Enabled = false;
548 buttonPowerOn.Enabled = false;
549 buttonPowerOff.Enabled = false;
550 buttonShowClock.Enabled = false;
551 buttonHideClock.Enabled = false;
552 toolStripStatusLabelConnect.Text = "Disconnected";
553 toolStripStatusLabelPower.Text = "N/A";
559 private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
561 //Save our show borders setting
562 tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
563 cds.ShowBorders = checkBoxShowBorders.Checked;
564 Properties.Settings.Default.Save();
568 private void checkBoxConnectOnStartup_CheckedChanged(object sender, EventArgs e)
570 //Save our connect on startup setting
571 Properties.Settings.Default.DisplayConnectOnStartup = checkBoxConnectOnStartup.Checked;
572 Properties.Settings.Default.Save();
575 private void checkBoxReverseScreen_CheckedChanged(object sender, EventArgs e)
577 //Save our reverse screen setting
578 cds.ReverseScreen = checkBoxReverseScreen.Checked;
579 Properties.Settings.Default.Save();
580 SetupPixelDelegates();
583 private void checkBoxInverseColors_CheckedChanged(object sender, EventArgs e)
585 //Save our inverse colors setting
586 cds.InverseColors = checkBoxInverseColors.Checked;
587 Properties.Settings.Default.Save();
588 SetupPixelDelegates();
591 private void MainForm_Resize(object sender, EventArgs e)
593 if (WindowState == FormWindowState.Minimized)
596 //iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
597 iCreateBitmap = true;
601 private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
607 public void StartServer()
609 iServiceHost = new ServiceHost
612 new Uri[] { new Uri("net.tcp://localhost:8001/") }
615 iServiceHost.AddServiceEndpoint(typeof(IService), new NetTcpBinding(SecurityMode.None, true), "DisplayService");
619 public void StopServer()
621 if (iClients.Count > 0 && !iClosing)
625 BroadcastCloseEvent();
629 if (MessageBox.Show("Force exit?", "Waiting for clients...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
631 iClosing = false; //We make sure we force close if asked twice
636 //We removed that as it often lags for some reason
637 //iServiceHost.Close();
641 public void BroadcastCloseEvent()
643 Trace.TraceInformation("BroadcastCloseEvent - start");
645 var inactiveClients = new List<string>();
646 foreach (var client in iClients)
648 //if (client.Key != eventData.ClientName)
652 Trace.TraceInformation("BroadcastCloseEvent - " + client.Key);
653 client.Value.Callback.OnCloseOrder(/*eventData*/);
657 inactiveClients.Add(client.Key);
662 if (inactiveClients.Count > 0)
664 foreach (var client in inactiveClients)
666 iClients.Remove(client);
667 Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(client, false)[0]);
672 private void buttonStartClient_Click(object sender, EventArgs e)
674 Thread clientThread = new Thread(SharpDisplayClient.Program.Main);
675 clientThread.Start();
679 private void buttonSuspend_Click(object sender, EventArgs e)
681 LastTickTime = DateTime.Now; //Reset timer to prevent jump
682 timer.Enabled = !timer.Enabled;
685 buttonSuspend.Text = "Run";
689 buttonSuspend.Text = "Pause";
693 private void buttonCloseClients_Click(object sender, EventArgs e)
695 BroadcastCloseEvent();
698 private void treeViewClients_AfterSelect(object sender, TreeViewEventArgs e)
707 /// <param name="aSessionId"></param>
708 /// <param name="aCallback"></param>
709 public void AddClientThreadSafe(string aSessionId, ICallback aCallback)
711 if (this.InvokeRequired)
713 //Not in the proper thread, invoke ourselves
714 AddClientDelegate d = new AddClientDelegate(AddClientThreadSafe);
715 this.Invoke(d, new object[] { aSessionId, aCallback });
719 //We are in the proper thread
720 //Add this session to our collection of clients
721 ClientData newClient = new ClientData(aSessionId, aCallback);
722 Program.iMainForm.iClients.Add(aSessionId, newClient);
723 //Add this session to our UI
724 UpdateClientTreeViewNode(newClient);
731 /// <param name="aSessionId"></param>
732 public void RemoveClientThreadSafe(string aSessionId)
734 if (this.InvokeRequired)
736 //Not in the proper thread, invoke ourselves
737 RemoveClientDelegate d = new RemoveClientDelegate(RemoveClientThreadSafe);
738 this.Invoke(d, new object[] { aSessionId });
742 //We are in the proper thread
743 //Remove this session from both client collection and UI tree view
744 if (Program.iMainForm.iClients.Keys.Contains(aSessionId))
746 Program.iMainForm.iClients.Remove(aSessionId);
747 Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(aSessionId, false)[0]);
750 if (iClosing && iClients.Count == 0)
752 //We were closing our form
753 //All clients are now closed
754 //Just resume our close operation
764 /// <param name="aSessionId"></param>
765 /// <param name="aTextField"></param>
766 public void SetClientLayoutThreadSafe(string aSessionId, TableLayout aLayout)
768 if (this.InvokeRequired)
770 //Not in the proper thread, invoke ourselves
771 SetLayoutDelegate d = new SetLayoutDelegate(SetClientLayoutThreadSafe);
772 this.Invoke(d, new object[] { aSessionId, aLayout });
776 ClientData client = iClients[aSessionId];
779 client.Layout = aLayout;
780 UpdateTableLayoutPanel(client);
782 UpdateClientTreeViewNode(client);
790 /// <param name="aLineIndex"></param>
791 /// <param name="aText"></param>
792 public void SetClientTextThreadSafe(string aSessionId, TextField aTextField)
794 if (this.InvokeRequired)
796 //Not in the proper thread, invoke ourselves
797 SetTextDelegate d = new SetTextDelegate(SetClientTextThreadSafe);
798 this.Invoke(d, new object[] { aSessionId, aTextField });
802 SetCurrentClient(aSessionId);
803 ClientData client = iClients[aSessionId];
806 //Make sure all our texts are in place
807 while (client.Texts.Count < (aTextField.Index + 1))
809 //Add a text field with proper index
810 client.Texts.Add(new TextField(client.Texts.Count));
812 client.Texts[aTextField.Index] = aTextField;
814 //We are in the proper thread
815 MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[aTextField.Index];
816 label.Text = aTextField.Text;
817 label.TextAlign = aTextField.Alignment;
819 UpdateClientTreeViewNode(client);
827 /// <param name="aTexts"></param>
828 public void SetClientTextsThreadSafe(string aSessionId, System.Collections.Generic.IList<TextField> aTextFields)
830 if (this.InvokeRequired)
832 //Not in the proper thread, invoke ourselves
833 SetTextsDelegate d = new SetTextsDelegate(SetClientTextsThreadSafe);
834 this.Invoke(d, new object[] { aSessionId, aTextFields });
838 SetCurrentClient(aSessionId);
839 //We are in the proper thread
840 ClientData client = iClients[aSessionId];
843 //Populate our client with the given text fields
845 foreach (TextField textField in aTextFields)
847 if (client.Texts.Count < (j + 1))
849 client.Texts.Add(textField);
853 client.Texts[j] = textField;
857 //Put each our text fields in a label control
858 for (int i = 0; i < aTextFields.Count; i++)
860 MarqueeLabel label = (MarqueeLabel)tableLayoutPanel.Controls[aTextFields[i].Index];
861 label.Text = aTextFields[i].Text;
862 label.TextAlign = aTextFields[i].Alignment;
866 UpdateClientTreeViewNode(client);
875 /// <param name="aSessionId"></param>
876 /// <param name="aName"></param>
877 public void SetClientNameThreadSafe(string aSessionId, string aName)
879 if (this.InvokeRequired)
881 //Not in the proper thread, invoke ourselves
882 SetClientNameDelegate d = new SetClientNameDelegate(SetClientNameThreadSafe);
883 this.Invoke(d, new object[] { aSessionId, aName });
887 //We are in the proper thread
889 ClientData client = iClients[aSessionId];
894 //Update our tree-view
895 UpdateClientTreeViewNode(client);
903 /// <param name="aClient"></param>
904 private void UpdateClientTreeViewNode(ClientData aClient)
911 TreeNode node = null;
912 //Check that our client node already exists
913 //Get our client root node using its key which is our session ID
914 TreeNode[] nodes = treeViewClients.Nodes.Find(aClient.SessionId, false);
917 //We already have a node for that client
919 //Clear children as we are going to recreate them below
924 //Client node does not exists create a new one
925 treeViewClients.Nodes.Add(aClient.SessionId, aClient.SessionId);
926 node = treeViewClients.Nodes.Find(aClient.SessionId, false)[0];
932 if (aClient.Name != "")
934 //We have a name, us it as text for our root node
935 node.Text = aClient.Name;
936 //Add a child with SessionId
937 node.Nodes.Add(new TreeNode(aClient.SessionId));
941 //No name, use session ID instead
942 node.Text = aClient.SessionId;
945 if (aClient.Texts.Count > 0)
947 //Create root node for our texts
948 TreeNode textsRoot = new TreeNode("Text");
949 node.Nodes.Add(textsRoot);
950 //For each text add a new entry
951 foreach (TextField field in aClient.Texts)
953 textsRoot.Nodes.Add(new TreeNode(field.Text));
961 private void buttonAddRow_Click(object sender, EventArgs e)
963 if (tableLayoutPanel.RowCount < 6)
965 UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount, tableLayoutPanel.RowCount + 1);
969 private void buttonRemoveRow_Click(object sender, EventArgs e)
971 if (tableLayoutPanel.RowCount > 1)
973 UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount, tableLayoutPanel.RowCount - 1);
976 UpdateTableLayoutRowStyles();
979 private void buttonAddColumn_Click(object sender, EventArgs e)
981 if (tableLayoutPanel.ColumnCount < 8)
983 UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount + 1, tableLayoutPanel.RowCount);
987 private void buttonRemoveColumn_Click(object sender, EventArgs e)
989 if (tableLayoutPanel.ColumnCount > 1)
991 UpdateTableLayoutPanel(tableLayoutPanel.ColumnCount - 1, tableLayoutPanel.RowCount);
997 /// Update our table layout row styles to make sure each rows have similar height
999 private void UpdateTableLayoutRowStyles()
1001 foreach (RowStyle rowStyle in tableLayoutPanel.RowStyles)
1003 rowStyle.SizeType = SizeType.Percent;
1004 rowStyle.Height = 100 / tableLayoutPanel.RowCount;
1009 /// Empty and recreate our table layout with the given number of columns and rows.
1010 /// Sizes of rows and columns are uniform.
1012 /// <param name="aColumn"></param>
1013 /// <param name="aRow"></param>
1014 private void UpdateTableLayoutPanel(int aColumn, int aRow)
1016 tableLayoutPanel.Controls.Clear();
1017 tableLayoutPanel.RowStyles.Clear();
1018 tableLayoutPanel.ColumnStyles.Clear();
1019 tableLayoutPanel.RowCount = 0;
1020 tableLayoutPanel.ColumnCount = 0;
1022 while (tableLayoutPanel.RowCount < aRow)
1024 tableLayoutPanel.RowCount++;
1027 while (tableLayoutPanel.ColumnCount < aColumn)
1029 tableLayoutPanel.ColumnCount++;
1032 for (int i = 0; i < tableLayoutPanel.ColumnCount; i++)
1034 //Create our column styles
1035 this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100 / tableLayoutPanel.ColumnCount));
1037 for (int j = 0; j < tableLayoutPanel.RowCount; j++)
1041 //Create our row styles
1042 this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100 / tableLayoutPanel.RowCount));
1045 MarqueeLabel control = new SharpDisplayManager.MarqueeLabel();
1046 control.AutoEllipsis = true;
1047 control.AutoSize = true;
1048 control.BackColor = System.Drawing.Color.Transparent;
1049 control.Dock = System.Windows.Forms.DockStyle.Fill;
1050 control.Location = new System.Drawing.Point(1, 1);
1051 control.Margin = new System.Windows.Forms.Padding(0);
1052 control.Name = "marqueeLabelCol" + aColumn + "Row" + aRow;
1053 control.OwnTimer = false;
1054 control.PixelsPerSecond = 64;
1055 control.Separator = "|";
1056 //control.Size = new System.Drawing.Size(254, 30);
1057 //control.TabIndex = 2;
1058 control.Font = cds.Font;
1059 control.Text = "ABCDEFGHIJKLMNOPQRST-0123456789";
1060 control.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
1061 control.UseCompatibleTextRendering = true;
1063 tableLayoutPanel.Controls.Add(control, i, j);
1072 /// Update our display table layout.
1074 /// <param name="aLayout"></param>
1075 private void UpdateTableLayoutPanel(ClientData aClient)
1077 TableLayout layout = aClient.Layout;
1079 tableLayoutPanel.Controls.Clear();
1080 tableLayoutPanel.RowStyles.Clear();
1081 tableLayoutPanel.ColumnStyles.Clear();
1082 tableLayoutPanel.RowCount = 0;
1083 tableLayoutPanel.ColumnCount = 0;
1085 while (tableLayoutPanel.RowCount < layout.Rows.Count)
1087 tableLayoutPanel.RowCount++;
1090 while (tableLayoutPanel.ColumnCount < layout.Columns.Count)
1092 tableLayoutPanel.ColumnCount++;
1095 for (int i = 0; i < tableLayoutPanel.ColumnCount; i++)
1097 //Create our column styles
1098 this.tableLayoutPanel.ColumnStyles.Add(layout.Columns[i]);
1100 for (int j = 0; j < tableLayoutPanel.RowCount; j++)
1104 //Create our row styles
1105 this.tableLayoutPanel.RowStyles.Add(layout.Rows[j]);
1108 MarqueeLabel control = new SharpDisplayManager.MarqueeLabel();
1109 control.AutoEllipsis = true;
1110 control.AutoSize = true;
1111 control.BackColor = System.Drawing.Color.Transparent;
1112 control.Dock = System.Windows.Forms.DockStyle.Fill;
1113 control.Location = new System.Drawing.Point(1, 1);
1114 control.Margin = new System.Windows.Forms.Padding(0);
1115 control.Name = "marqueeLabelCol" + layout.Columns.Count + "Row" + layout.Rows.Count;
1116 control.OwnTimer = false;
1117 control.PixelsPerSecond = 64;
1118 control.Separator = "|";
1119 //control.Size = new System.Drawing.Size(254, 30);
1120 //control.TabIndex = 2;
1121 control.Font = cds.Font;
1123 //If we already have a text for that field
1124 if (aClient.Texts.Count > tableLayoutPanel.Controls.Count)
1126 control.Text = aClient.Texts[tableLayoutPanel.Controls.Count].Text;
1129 control.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
1130 control.UseCompatibleTextRendering = true;
1132 tableLayoutPanel.Controls.Add(control, i, j);
1140 private void buttonAlignLeft_Click(object sender, EventArgs e)
1142 foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
1144 ctrl.TextAlign = ContentAlignment.MiddleLeft;
1148 private void buttonAlignCenter_Click(object sender, EventArgs e)
1150 foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
1152 ctrl.TextAlign = ContentAlignment.MiddleCenter;
1156 private void buttonAlignRight_Click(object sender, EventArgs e)
1158 foreach (MarqueeLabel ctrl in tableLayoutPanel.Controls)
1160 ctrl.TextAlign = ContentAlignment.MiddleRight;
1164 private void comboBoxDisplayType_SelectedIndexChanged(object sender, EventArgs e)
1166 Properties.Settings.Default.CurrentDisplayIndex = comboBoxDisplayType.SelectedIndex;
1167 cds.DisplayType = comboBoxDisplayType.SelectedIndex;
1168 Properties.Settings.Default.Save();
1169 if (iDisplay.IsOpen())
1171 OpenDisplayConnection();
1180 private void maskedTextBoxTimerInterval_TextChanged(object sender, EventArgs e)
1182 if (maskedTextBoxTimerInterval.Text != "")
1184 int interval = Convert.ToInt32(maskedTextBoxTimerInterval.Text);
1188 timer.Interval = interval;
1189 cds.TimerInterval = timer.Interval;
1190 Properties.Settings.Default.Save();
1195 private void buttonPowerOn_Click(object sender, EventArgs e)
1200 private void buttonPowerOff_Click(object sender, EventArgs e)
1202 iDisplay.PowerOff();
1205 private void buttonShowClock_Click(object sender, EventArgs e)
1207 iDisplay.ShowClock();
1210 private void buttonHideClock_Click(object sender, EventArgs e)
1212 iDisplay.HideClock();
1217 /// A UI thread copy of a client relevant data.
1218 /// Keeping this copy in the UI thread helps us deal with threading issues.
1220 public class ClientData
1222 public ClientData(string aSessionId, ICallback aCallback)
1224 SessionId = aSessionId;
1226 Texts = new List<TextField>();
1227 Layout = new TableLayout(1, 2); //Default to one column and two rows
1228 Callback = aCallback;
1231 public string SessionId { get; set; }
1232 public string Name { get; set; }
1233 public List<TextField> Texts { get; set; }
1234 public TableLayout Layout { get; set; }
1235 public ICallback Callback { get; set; }