sl@0: using System;
sl@0: using System.Collections.Generic;
sl@0: using System.ComponentModel;
sl@0: using System.Data;
sl@0: using System.Drawing;
sl@0: using System.Linq;
sl@0: using System.Text;
sl@0: using System.Threading.Tasks;
sl@0: using System.Windows.Forms;
sl@14: using System.IO;
sl@0: using CodeProject.Dialog;
sl@14: using System.Drawing.Imaging;
sl@17: using System.ServiceModel;
sl@25: using System.Threading;
sl@31: using System.Diagnostics;
sl@25: //
sl@25: using SharpDisplayClient;
sl@55: using SharpDisplay;
sl@0:
sl@0: namespace SharpDisplayManager
sl@0: {
sl@0: public partial class MainForm : Form
sl@0: {
sl@2: DateTime LastTickTime;
sl@3: Display iDisplay;
sl@14: System.Drawing.Bitmap iBmp;
sl@14: bool iCreateBitmap; //Workaround render to bitmap issues when minimized
sl@17: ServiceHost iServiceHost;
sl@21: ///
sl@21: /// Our collection of clients
sl@21: ///
sl@33: public Dictionary iClients;
sl@29: public bool iClosing;
sl@2:
sl@0: public MainForm()
sl@0: {
sl@2: LastTickTime = DateTime.Now;
sl@3: iDisplay = new Display();
sl@33: iClients = new Dictionary();
sl@2:
sl@0: InitializeComponent();
sl@7: UpdateStatus();
sl@14: //We have a bug when drawing minimized and reusing our bitmap
sl@14: iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14: iCreateBitmap = false;
sl@57: //
sl@57: //this.tableLayoutPanel.CellPaint += new TableLayoutCellPaintEventHandler(tableLayoutPanel_CellPaint);
sl@0: }
sl@0:
sl@13: private void MainForm_Load(object sender, EventArgs e)
sl@13: {
sl@17: StartServer();
sl@17:
sl@13: if (Properties.Settings.Default.DisplayConnectOnStartup)
sl@13: {
sl@46: OpenDisplayConnection();
sl@13: }
sl@13: }
sl@13:
sl@57: //Testing that stuff
sl@57: private void tableLayoutPanel_CellPaint(object sender, TableLayoutCellPaintEventArgs e)
sl@57: {
sl@57: var panel = sender as TableLayoutPanel;
sl@57: //e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
sl@57: var rectangle = e.CellBounds;
sl@57: using (var pen = new Pen(Color.Black, 1))
sl@57: {
sl@57: pen.Alignment = System.Drawing.Drawing2D.PenAlignment.Center;
sl@57: pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
sl@57:
sl@57: if (e.Row == (panel.RowCount - 1))
sl@57: {
sl@57: rectangle.Height -= 1;
sl@57: }
sl@57:
sl@57: if (e.Column == (panel.ColumnCount - 1))
sl@57: {
sl@57: rectangle.Width -= 1;
sl@57: }
sl@57:
sl@57: e.Graphics.DrawRectangle(pen, rectangle);
sl@57: }
sl@57: }
sl@57:
sl@13:
sl@0: private void buttonFont_Click(object sender, EventArgs e)
sl@0: {
sl@0: //fontDialog.ShowColor = true;
sl@0: //fontDialog.ShowApply = true;
sl@0: fontDialog.ShowEffects = true;
sl@11: fontDialog.Font = marqueeLabelTop.Font;
sl@28:
sl@28: fontDialog.FixedPitchOnly = checkBoxFixedPitchFontOnly.Checked;
sl@28:
sl@0: //fontDialog.ShowHelp = true;
sl@0:
sl@0: //fontDlg.MaxSize = 40;
sl@0: //fontDlg.MinSize = 22;
sl@0:
sl@0: //fontDialog.Parent = this;
sl@0: //fontDialog.StartPosition = FormStartPosition.CenterParent;
sl@0:
sl@0: //DlgBox.ShowDialog(fontDialog);
sl@0:
sl@0: //if (fontDialog.ShowDialog(this) != DialogResult.Cancel)
sl@0: if (DlgBox.ShowDialog(fontDialog) != DialogResult.Cancel)
sl@0: {
sl@0:
sl@4: //MsgBox.Show("MessageBox MsgBox", "MsgBox caption");
sl@0:
sl@0: //MessageBox.Show("Ok");
sl@4: marqueeLabelTop.Font = fontDialog.Font;
sl@4: marqueeLabelBottom.Font = fontDialog.Font;
sl@48: cds.Font = fontDialog.Font;
sl@8: Properties.Settings.Default.Save();
sl@36: //
sl@37: CheckFontHeight();
sl@37: }
sl@37: }
sl@36:
sl@37: ///
sl@38: ///
sl@37: ///
sl@37: void CheckFontHeight()
sl@37: {
sl@54: //Show font height and width
sl@54: labelFontHeight.Text = "Font height: " + cds.Font.Height;
sl@54: float charWidth = IsFixedWidth(cds.Font);
sl@54: if (charWidth == 0.0f)
sl@54: {
sl@54: labelFontWidth.Visible = false;
sl@54: }
sl@54: else
sl@54: {
sl@54: labelFontWidth.Visible = true;
sl@54: labelFontWidth.Text = "Font width: " + charWidth;
sl@54: }
sl@54:
sl@54: //Now check font height and show a warning if needed.
sl@37: if (marqueeLabelBottom.Font.Height > marqueeLabelBottom.Height)
sl@37: {
sl@37: labelWarning.Text = "WARNING: Selected font is too height by " + (marqueeLabelBottom.Font.Height - marqueeLabelBottom.Height) + " pixels!";
sl@37: labelWarning.Visible = true;
sl@0: }
sl@37: else
sl@37: {
sl@37: labelWarning.Visible = false;
sl@37: }
sl@37:
sl@0: }
sl@0:
sl@0: private void buttonCapture_Click(object sender, EventArgs e)
sl@0: {
sl@0: System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height);
sl@0: tableLayoutPanel.DrawToBitmap(bmp, tableLayoutPanel.ClientRectangle);
sl@14: //Bitmap bmpToSave = new Bitmap(bmp);
sl@14: bmp.Save("D:\\capture.png");
sl@14:
sl@17: marqueeLabelTop.Text = "Sweet";
sl@17:
sl@14: /*
sl@14: string outputFileName = "d:\\capture.png";
sl@14: using (MemoryStream memory = new MemoryStream())
sl@14: {
sl@14: using (FileStream fs = new FileStream(outputFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite))
sl@14: {
sl@14: bmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
sl@14: byte[] bytes = memory.ToArray();
sl@14: fs.Write(bytes, 0, bytes.Length);
sl@14: }
sl@14: }
sl@14: */
sl@14:
sl@0: }
sl@2:
sl@12: private void CheckForRequestResults()
sl@12: {
sl@12: if (iDisplay.IsRequestPending())
sl@12: {
sl@12: switch (iDisplay.AttemptRequestCompletion())
sl@12: {
sl@51: case Display.TMiniDisplayRequest.EMiniDisplayRequestFirmwareRevision:
sl@51: toolStripStatusLabelConnect.Text += " v" + iDisplay.FirmwareRevision();
sl@51: //Issue next request then
sl@51: iDisplay.RequestPowerSupplyStatus();
sl@51: break;
sl@51:
sl@12: case Display.TMiniDisplayRequest.EMiniDisplayRequestPowerSupplyStatus:
sl@12: if (iDisplay.PowerSupplyStatus())
sl@12: {
sl@12: toolStripStatusLabelPower.Text = "ON";
sl@12: }
sl@12: else
sl@12: {
sl@12: toolStripStatusLabelPower.Text = "OFF";
sl@12: }
sl@12: //Issue next request then
sl@12: iDisplay.RequestDeviceId();
sl@12: break;
sl@12:
sl@12: case Display.TMiniDisplayRequest.EMiniDisplayRequestDeviceId:
sl@12: toolStripStatusLabelConnect.Text += " - " + iDisplay.DeviceId();
sl@12: //No more request to issue
sl@12: break;
sl@12: }
sl@12: }
sl@12: }
sl@12:
sl@16:
sl@57: public delegate uint ColorProcessingDelegate(uint aPixel);
sl@57:
sl@57: public static uint ColorUntouched(uint aPixel)
sl@57: {
sl@57: return aPixel;
sl@57: }
sl@57:
sl@57: public static uint ColorInversed(uint aPixel)
sl@57: {
sl@57: return ~aPixel;
sl@57: }
sl@57:
sl@16: public delegate int CoordinateTranslationDelegate(System.Drawing.Bitmap aBmp, int aInt);
sl@16:
sl@16: public static int ScreenReversedX(System.Drawing.Bitmap aBmp, int aX)
sl@16: {
sl@16: return aBmp.Width - aX - 1;
sl@16: }
sl@16:
sl@16: public int ScreenReversedY(System.Drawing.Bitmap aBmp, int aY)
sl@16: {
sl@16: return iBmp.Height - aY - 1;
sl@16: }
sl@16:
sl@16: public int ScreenX(System.Drawing.Bitmap aBmp, int aX)
sl@16: {
sl@16: return aX;
sl@16: }
sl@16:
sl@16: public int ScreenY(System.Drawing.Bitmap aBmp, int aY)
sl@16: {
sl@16: return aY;
sl@16: }
sl@16:
sl@16:
sl@16: //This is our timer tick responsible to perform our render
sl@2: private void timer_Tick(object sender, EventArgs e)
sl@14: {
sl@2: //Update our animations
sl@2: DateTime NewTickTime = DateTime.Now;
sl@2:
sl@2: marqueeLabelTop.UpdateAnimation(LastTickTime, NewTickTime);
sl@2: marqueeLabelBottom.UpdateAnimation(LastTickTime, NewTickTime);
sl@2:
sl@4: //Update our display
sl@4: if (iDisplay.IsOpen())
sl@4: {
sl@12: CheckForRequestResults();
sl@12:
sl@22: //Draw to bitmap
sl@14: if (iCreateBitmap)
sl@14: {
sl@14: iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14: }
sl@14: tableLayoutPanel.DrawToBitmap(iBmp, tableLayoutPanel.ClientRectangle);
sl@14: //iBmp.Save("D:\\capture.png");
sl@16:
sl@57:
sl@57: //Select our pixel processing routine
sl@57: ColorProcessingDelegate colorFx;
sl@57:
sl@57: if (cds.InverseColors)
sl@57: {
sl@57: colorFx = ColorInversed;
sl@57: }
sl@57: else
sl@57: {
sl@57: colorFx = ColorUntouched;
sl@57: }
sl@57:
sl@16: //Select proper coordinate translation functions
sl@16: //We used delegate/function pointer to support reverse screen without doing an extra test on each pixels
sl@16: CoordinateTranslationDelegate screenX;
sl@16: CoordinateTranslationDelegate screenY;
sl@16:
sl@48: if (cds.ReverseScreen)
sl@16: {
sl@16: screenX = ScreenReversedX;
sl@16: screenY = ScreenReversedY;
sl@16: }
sl@16: else
sl@16: {
sl@16: screenX = ScreenX;
sl@16: screenY = ScreenY;
sl@16: }
sl@22:
sl@7: //Send it to our display
sl@14: for (int i = 0; i < iBmp.Width; i++)
sl@4: {
sl@14: for (int j = 0; j < iBmp.Height; j++)
sl@4: {
sl@4: unchecked
sl@4: {
sl@14: uint color = (uint)iBmp.GetPixel(i, j).ToArgb();
sl@57: //Apply color effects
sl@57: color = colorFx(color);
sl@14: //For some reason when the app is minimized in the task bar only the alpha of our color is set.
sl@14: //Thus that strange test for rendering to work both when the app is in the task bar and when it isn't.
sl@57: //iDisplay.SetPixel(screenX(iBmp, i), screenY(iBmp, j), Convert.ToInt32(!(color != 0xFF000000)));
sl@57: iDisplay.SetPixel(screenX(iBmp, i), screenY(iBmp, j), color);
sl@4: }
sl@4: }
sl@4: }
sl@4:
sl@4: iDisplay.SwapBuffers();
sl@4:
sl@4: }
sl@8:
sl@8: //Compute instant FPS
sl@47: toolStripStatusLabelFps.Text = (1.0/NewTickTime.Subtract(LastTickTime).TotalSeconds).ToString("F0") + " / " + (1000/timer.Interval).ToString() + " FPS";
sl@8:
sl@8: LastTickTime = NewTickTime;
sl@8:
sl@2: }
sl@3:
sl@46: private void OpenDisplayConnection()
sl@3: {
sl@46: CloseDisplayConnection();
sl@46:
sl@48: if (iDisplay.Open((Display.TMiniDisplayType)cds.DisplayType))
sl@3: {
sl@7: UpdateStatus();
sl@51: iDisplay.RequestFirmwareRevision();
sl@3: }
sl@7: else
sl@7: {
sl@7: UpdateStatus();
sl@7: toolStripStatusLabelConnect.Text = "Connection error";
sl@7: }
sl@46: }
sl@7:
sl@46: private void CloseDisplayConnection()
sl@46: {
sl@46: iDisplay.Close();
sl@46: UpdateStatus();
sl@46: }
sl@46:
sl@46: private void buttonOpen_Click(object sender, EventArgs e)
sl@46: {
sl@46: OpenDisplayConnection();
sl@3: }
sl@3:
sl@3: private void buttonClose_Click(object sender, EventArgs e)
sl@3: {
sl@46: CloseDisplayConnection();
sl@3: }
sl@3:
sl@3: private void buttonClear_Click(object sender, EventArgs e)
sl@3: {
sl@3: iDisplay.Clear();
sl@3: iDisplay.SwapBuffers();
sl@3: }
sl@3:
sl@3: private void buttonFill_Click(object sender, EventArgs e)
sl@3: {
sl@3: iDisplay.Fill();
sl@3: iDisplay.SwapBuffers();
sl@3: }
sl@3:
sl@3: private void trackBarBrightness_Scroll(object sender, EventArgs e)
sl@3: {
sl@48: cds.Brightness = trackBarBrightness.Value;
sl@9: Properties.Settings.Default.Save();
sl@3: iDisplay.SetBrightness(trackBarBrightness.Value);
sl@9:
sl@3: }
sl@7:
sl@48:
sl@48: ///
sl@48: /// CDS stands for Current Display Settings
sl@48: ///
sl@50: private DisplaySettings cds
sl@48: {
sl@48: get
sl@48: {
sl@50: DisplaysSettings settings = Properties.Settings.Default.DisplaySettings;
sl@51: if (settings == null)
sl@51: {
sl@51: settings = new DisplaysSettings();
sl@51: settings.Init();
sl@51: Properties.Settings.Default.DisplaySettings = settings;
sl@51: }
sl@48:
sl@48: //Make sure all our settings have been created
sl@48: while (settings.Displays.Count <= Properties.Settings.Default.CurrentDisplayIndex)
sl@48: {
sl@50: settings.Displays.Add(new DisplaySettings());
sl@48: }
sl@48:
sl@50: DisplaySettings displaySettings = settings.Displays[Properties.Settings.Default.CurrentDisplayIndex];
sl@48: return displaySettings;
sl@48: }
sl@48: }
sl@48:
sl@54: ///
sl@54: /// Check if the given font has a fixed character pitch.
sl@54: ///
sl@54: ///
sl@54: /// 0.0f if this is not a monospace font, otherwise returns the character width.
sl@54: public float IsFixedWidth(Font ft)
sl@54: {
sl@54: Graphics g = CreateGraphics();
sl@54: char[] charSizes = new char[] { 'i', 'a', 'Z', '%', '#', 'a', 'B', 'l', 'm', ',', '.' };
sl@54: float charWidth = g.MeasureString("I", ft, Int32.MaxValue, StringFormat.GenericTypographic).Width;
sl@54:
sl@54: bool fixedWidth = true;
sl@54:
sl@54: foreach (char c in charSizes)
sl@54: if (g.MeasureString(c.ToString(), ft, Int32.MaxValue, StringFormat.GenericTypographic).Width != charWidth)
sl@54: fixedWidth = false;
sl@54:
sl@54: if (fixedWidth)
sl@54: {
sl@54: return charWidth;
sl@54: }
sl@54:
sl@54: return 0.0f;
sl@54: }
sl@54:
sl@7: private void UpdateStatus()
sl@7: {
sl@48: //Synchronize UI with settings
sl@48: //Load settings
sl@54:
sl@54: checkBoxShowBorders.Checked = cds.ShowBorders;
sl@54: tableLayoutPanel.CellBorderStyle = (cds.ShowBorders ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
sl@48: marqueeLabelTop.Font = cds.Font;
sl@48: marqueeLabelBottom.Font = cds.Font;
sl@54: CheckFontHeight();
sl@48: checkBoxConnectOnStartup.Checked = Properties.Settings.Default.DisplayConnectOnStartup;
sl@48: checkBoxReverseScreen.Checked = cds.ReverseScreen;
sl@57: checkBoxInverseColors.Checked = cds.InverseColors;
sl@48: comboBoxDisplayType.SelectedIndex = cds.DisplayType;
sl@48: timer.Interval = cds.TimerInterval;
sl@48: maskedTextBoxTimerInterval.Text = cds.TimerInterval.ToString();
sl@48:
sl@48:
sl@7: if (iDisplay.IsOpen())
sl@7: {
sl@48: //Only setup brightness if display is open
sl@48: trackBarBrightness.Minimum = iDisplay.MinBrightness();
sl@48: trackBarBrightness.Maximum = iDisplay.MaxBrightness();
sl@48: trackBarBrightness.Value = cds.Brightness;
sl@48: trackBarBrightness.LargeChange = Math.Max(1, (iDisplay.MaxBrightness() - iDisplay.MinBrightness()) / 5);
sl@48: trackBarBrightness.SmallChange = 1;
sl@48: iDisplay.SetBrightness(cds.Brightness);
sl@48: //
sl@7: buttonFill.Enabled = true;
sl@7: buttonClear.Enabled = true;
sl@7: buttonOpen.Enabled = false;
sl@7: buttonClose.Enabled = true;
sl@7: trackBarBrightness.Enabled = true;
sl@10: toolStripStatusLabelConnect.Text = "Connected - " + iDisplay.Vendor() + " - " + iDisplay.Product();
sl@10: //+ " - " + iDisplay.SerialNumber();
sl@52:
sl@52: if (iDisplay.SupportPowerOnOff())
sl@52: {
sl@52: buttonPowerOn.Enabled = true;
sl@52: buttonPowerOff.Enabled = true;
sl@52: }
sl@52: else
sl@52: {
sl@52: buttonPowerOn.Enabled = false;
sl@52: buttonPowerOff.Enabled = false;
sl@52: }
sl@53:
sl@53: if (iDisplay.SupportClock())
sl@53: {
sl@53: buttonShowClock.Enabled = true;
sl@53: buttonHideClock.Enabled = true;
sl@53: }
sl@53: else
sl@53: {
sl@53: buttonShowClock.Enabled = false;
sl@53: buttonHideClock.Enabled = false;
sl@53: }
sl@7: }
sl@7: else
sl@7: {
sl@7: buttonFill.Enabled = false;
sl@7: buttonClear.Enabled = false;
sl@7: buttonOpen.Enabled = true;
sl@7: buttonClose.Enabled = false;
sl@7: trackBarBrightness.Enabled = false;
sl@52: buttonPowerOn.Enabled = false;
sl@52: buttonPowerOff.Enabled = false;
sl@53: buttonShowClock.Enabled = false;
sl@53: buttonHideClock.Enabled = false;
sl@9: toolStripStatusLabelConnect.Text = "Disconnected";
sl@48: toolStripStatusLabelPower.Text = "N/A";
sl@7: }
sl@7: }
sl@9:
sl@13:
sl@13:
sl@9: private void checkBoxShowBorders_CheckedChanged(object sender, EventArgs e)
sl@9: {
sl@16: //Save our show borders setting
sl@13: tableLayoutPanel.CellBorderStyle = (checkBoxShowBorders.Checked ? TableLayoutPanelCellBorderStyle.Single : TableLayoutPanelCellBorderStyle.None);
sl@48: cds.ShowBorders = checkBoxShowBorders.Checked;
sl@9: Properties.Settings.Default.Save();
sl@57: CheckFontHeight();
sl@9: }
sl@13:
sl@13: private void checkBoxConnectOnStartup_CheckedChanged(object sender, EventArgs e)
sl@13: {
sl@16: //Save our connect on startup setting
sl@13: Properties.Settings.Default.DisplayConnectOnStartup = checkBoxConnectOnStartup.Checked;
sl@13: Properties.Settings.Default.Save();
sl@13: }
sl@13:
sl@16: private void checkBoxReverseScreen_CheckedChanged(object sender, EventArgs e)
sl@16: {
sl@16: //Save our reverse screen setting
sl@48: cds.ReverseScreen = checkBoxReverseScreen.Checked;
sl@16: Properties.Settings.Default.Save();
sl@16: }
sl@16:
sl@57: private void checkBoxInverseColors_CheckedChanged(object sender, EventArgs e)
sl@57: {
sl@57: //Save our inverse colors setting
sl@57: cds.InverseColors = checkBoxInverseColors.Checked;
sl@57: Properties.Settings.Default.Save();
sl@57: }
sl@57:
sl@14: private void MainForm_Resize(object sender, EventArgs e)
sl@14: {
sl@14: if (WindowState == FormWindowState.Minimized)
sl@14: {
sl@14: // Do some stuff
sl@14: //iBmp = new System.Drawing.Bitmap(tableLayoutPanel.Width, tableLayoutPanel.Height, PixelFormat.Format32bppArgb);
sl@14: iCreateBitmap = true;
sl@14: }
sl@14: }
sl@14:
sl@17: private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
sl@17: {
sl@17: StopServer();
sl@32: e.Cancel = iClosing;
sl@17: }
sl@17:
sl@17: public void StartServer()
sl@17: {
sl@17: iServiceHost = new ServiceHost
sl@17: (
sl@55: typeof(Session),
sl@20: new Uri[] { new Uri("net.tcp://localhost:8001/") }
sl@17: );
sl@17:
sl@55: iServiceHost.AddServiceEndpoint(typeof(IService), new NetTcpBinding(SecurityMode.None, true), "DisplayService");
sl@17: iServiceHost.Open();
sl@17: }
sl@17:
sl@17: public void StopServer()
sl@17: {
sl@32: if (iClients.Count > 0 && !iClosing)
sl@29: {
sl@29: //Tell our clients
sl@32: iClosing = true;
sl@29: BroadcastCloseEvent();
sl@29: }
sl@32: else if (iClosing)
sl@32: {
sl@32: if (MessageBox.Show("Force exit?", "Waiting for clients...", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
sl@32: {
sl@32: iClosing = false; //We make sure we force close if asked twice
sl@32: }
sl@32: }
sl@32: else
sl@36: {
sl@32: //We removed that as it often lags for some reason
sl@32: //iServiceHost.Close();
sl@32: }
sl@17: }
sl@17:
sl@21: public void BroadcastCloseEvent()
sl@21: {
sl@31: Trace.TraceInformation("BroadcastCloseEvent - start");
sl@31:
sl@21: var inactiveClients = new List();
sl@21: foreach (var client in iClients)
sl@21: {
sl@21: //if (client.Key != eventData.ClientName)
sl@21: {
sl@21: try
sl@21: {
sl@31: Trace.TraceInformation("BroadcastCloseEvent - " + client.Key);
sl@33: client.Value.Callback.OnCloseOrder(/*eventData*/);
sl@21: }
sl@21: catch (Exception ex)
sl@21: {
sl@21: inactiveClients.Add(client.Key);
sl@21: }
sl@21: }
sl@21: }
sl@21:
sl@21: if (inactiveClients.Count > 0)
sl@21: {
sl@21: foreach (var client in inactiveClients)
sl@21: {
sl@21: iClients.Remove(client);
sl@30: Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(client, false)[0]);
sl@21: }
sl@21: }
sl@21: }
sl@21:
sl@25: private void buttonStartClient_Click(object sender, EventArgs e)
sl@25: {
sl@25: Thread clientThread = new Thread(SharpDisplayClient.Program.Main);
sl@25: clientThread.Start();
sl@36: BringToFront();
sl@25: }
sl@25:
sl@27: private void buttonSuspend_Click(object sender, EventArgs e)
sl@27: {
sl@52: LastTickTime = DateTime.Now; //Reset timer to prevent jump
sl@27: timer.Enabled = !timer.Enabled;
sl@27: if (!timer.Enabled)
sl@27: {
sl@52: buttonSuspend.Text = "Run";
sl@27: }
sl@27: else
sl@27: {
sl@27: buttonSuspend.Text = "Pause";
sl@27: }
sl@27: }
sl@27:
sl@29: private void buttonCloseClients_Click(object sender, EventArgs e)
sl@29: {
sl@29: BroadcastCloseEvent();
sl@29: }
sl@29:
sl@30: private void treeViewClients_AfterSelect(object sender, TreeViewEventArgs e)
sl@30: {
sl@21:
sl@30: }
sl@30:
sl@36: //Delegates are used for our thread safe method
sl@55: public delegate void AddClientDelegate(string aSessionId, ICallback aCallback);
sl@30: public delegate void RemoveClientDelegate(string aSessionId);
sl@43: public delegate void SetTextDelegate(string SessionId, TextField aTextField);
sl@43: public delegate void SetTextsDelegate(string SessionId, System.Collections.Generic.IList aTextFields);
sl@32: public delegate void SetClientNameDelegate(string aSessionId, string aName);
sl@30:
sl@36:
sl@30: ///
sl@36: ///
sl@30: ///
sl@30: ///
sl@30: ///
sl@55: public void AddClientThreadSafe(string aSessionId, ICallback aCallback)
sl@30: {
sl@33: if (this.InvokeRequired)
sl@30: {
sl@30: //Not in the proper thread, invoke ourselves
sl@30: AddClientDelegate d = new AddClientDelegate(AddClientThreadSafe);
sl@30: this.Invoke(d, new object[] { aSessionId, aCallback });
sl@30: }
sl@30: else
sl@30: {
sl@30: //We are in the proper thread
sl@30: //Add this session to our collection of clients
sl@33: ClientData newClient = new ClientData(aSessionId, aCallback);
sl@33: Program.iMainForm.iClients.Add(aSessionId, newClient);
sl@30: //Add this session to our UI
sl@33: UpdateClientTreeViewNode(newClient);
sl@30: }
sl@30: }
sl@30:
sl@30: ///
sl@36: ///
sl@30: ///
sl@30: ///
sl@30: public void RemoveClientThreadSafe(string aSessionId)
sl@30: {
sl@33: if (this.InvokeRequired)
sl@30: {
sl@30: //Not in the proper thread, invoke ourselves
sl@30: RemoveClientDelegate d = new RemoveClientDelegate(RemoveClientThreadSafe);
sl@30: this.Invoke(d, new object[] { aSessionId });
sl@30: }
sl@30: else
sl@30: {
sl@30: //We are in the proper thread
sl@33: //Remove this session from both client collection and UI tree view
sl@30: if (Program.iMainForm.iClients.Keys.Contains(aSessionId))
sl@30: {
sl@30: Program.iMainForm.iClients.Remove(aSessionId);
sl@30: Program.iMainForm.treeViewClients.Nodes.Remove(Program.iMainForm.treeViewClients.Nodes.Find(aSessionId, false)[0]);
sl@32: }
sl@32:
sl@32: if (iClosing && iClients.Count == 0)
sl@32: {
sl@32: //We were closing our form
sl@32: //All clients are now closed
sl@32: //Just resume our close operation
sl@32: iClosing = false;
sl@32: Close();
sl@32: }
sl@30: }
sl@30: }
sl@30:
sl@30: ///
sl@36: ///
sl@30: ///
sl@30: ///
sl@30: ///
sl@43: public void SetTextThreadSafe(string aSessionId, TextField aTextField)
sl@30: {
sl@33: if (this.InvokeRequired)
sl@30: {
sl@30: //Not in the proper thread, invoke ourselves
sl@30: SetTextDelegate d = new SetTextDelegate(SetTextThreadSafe);
sl@43: this.Invoke(d, new object[] { aSessionId, aTextField });
sl@30: }
sl@30: else
sl@30: {
sl@34: ClientData client = iClients[aSessionId];
sl@34: if (client != null)
sl@30: {
sl@34: //Make sure all our texts are in place
sl@43: while (client.Texts.Count < (aTextField.Index + 1))
sl@34: {
sl@43: //Add a text field with proper index
sl@43: client.Texts.Add(new TextField(client.Texts.Count));
sl@34: }
sl@43: client.Texts[aTextField.Index] = aTextField;
sl@34:
sl@34: //We are in the proper thread
sl@34: //Only support two lines for now
sl@43: if (aTextField.Index == 0)
sl@34: {
sl@43: marqueeLabelTop.Text = aTextField.Text;
sl@43: marqueeLabelTop.TextAlign = aTextField.Alignment;
sl@34: }
sl@43: else if (aTextField.Index == 1)
sl@34: {
sl@43: marqueeLabelBottom.Text = aTextField.Text;
sl@43: marqueeLabelBottom.TextAlign = aTextField.Alignment;
sl@34: }
sl@34:
sl@34:
sl@34: UpdateClientTreeViewNode(client);
sl@30: }
sl@30: }
sl@30: }
sl@30:
sl@30: ///
sl@36: ///
sl@30: ///
sl@30: ///
sl@43: public void SetTextsThreadSafe(string aSessionId, System.Collections.Generic.IList aTextFields)
sl@30: {
sl@33: if (this.InvokeRequired)
sl@30: {
sl@30: //Not in the proper thread, invoke ourselves
sl@30: SetTextsDelegate d = new SetTextsDelegate(SetTextsThreadSafe);
sl@43: this.Invoke(d, new object[] { aSessionId, aTextFields });
sl@30: }
sl@30: else
sl@30: {
sl@43: //We are in the proper thread
sl@34: ClientData client = iClients[aSessionId];
sl@34: if (client != null)
sl@30: {
sl@43: //Populate our client with the given text fields
sl@34: int j = 0;
sl@43: foreach (TextField textField in aTextFields)
sl@30: {
sl@34: if (client.Texts.Count < (j + 1))
sl@34: {
sl@43: client.Texts.Add(textField);
sl@34: }
sl@34: else
sl@34: {
sl@43: client.Texts[j] = textField;
sl@34: }
sl@34: j++;
sl@54: }
sl@34: //Only support two lines for now
sl@43: for (int i = 0; i < aTextFields.Count; i++)
sl@30: {
sl@43: if (aTextFields[i].Index == 0)
sl@34: {
sl@43: marqueeLabelTop.Text = aTextFields[i].Text;
sl@43: marqueeLabelTop.TextAlign = aTextFields[i].Alignment;
sl@34: }
sl@43: else if (aTextFields[i].Index == 1)
sl@34: {
sl@43: marqueeLabelBottom.Text = aTextFields[i].Text;
sl@43: marqueeLabelBottom.TextAlign = aTextFields[i].Alignment;
sl@34: }
sl@30: }
sl@34:
sl@34:
sl@34: UpdateClientTreeViewNode(client);
sl@30: }
sl@30: }
sl@32: }
sl@30:
sl@32:
sl@32: ///
sl@36: ///
sl@32: ///
sl@32: ///
sl@32: ///
sl@32: public void SetClientNameThreadSafe(string aSessionId, string aName)
sl@32: {
sl@32: if (this.InvokeRequired)
sl@32: {
sl@32: //Not in the proper thread, invoke ourselves
sl@32: SetClientNameDelegate d = new SetClientNameDelegate(SetClientNameThreadSafe);
sl@32: this.Invoke(d, new object[] { aSessionId, aName });
sl@32: }
sl@32: else
sl@32: {
sl@32: //We are in the proper thread
sl@33: //Get our client
sl@33: ClientData client = iClients[aSessionId];
sl@33: if (client != null)
sl@32: {
sl@33: //Set its name
sl@33: client.Name = aName;
sl@33: //Update our tree-view
sl@33: UpdateClientTreeViewNode(client);
sl@33: }
sl@33: }
sl@33: }
sl@33:
sl@33: ///
sl@36: ///
sl@33: ///
sl@33: ///
sl@33: private void UpdateClientTreeViewNode(ClientData aClient)
sl@33: {
sl@33: if (aClient == null)
sl@33: {
sl@33: return;
sl@33: }
sl@33:
sl@33: TreeNode node = null;
sl@33: //Check that our client node already exists
sl@33: //Get our client root node using its key which is our session ID
sl@33: TreeNode[] nodes = treeViewClients.Nodes.Find(aClient.SessionId, false);
sl@33: if (nodes.Count()>0)
sl@33: {
sl@33: //We already have a node for that client
sl@33: node = nodes[0];
sl@33: //Clear children as we are going to recreate them below
sl@33: node.Nodes.Clear();
sl@33: }
sl@33: else
sl@33: {
sl@33: //Client node does not exists create a new one
sl@33: treeViewClients.Nodes.Add(aClient.SessionId, aClient.SessionId);
sl@33: node = treeViewClients.Nodes.Find(aClient.SessionId, false)[0];
sl@33: }
sl@33:
sl@33: if (node != null)
sl@33: {
sl@33: //Change its name
sl@33: if (aClient.Name != "")
sl@33: {
sl@33: //We have a name, us it as text for our root node
sl@33: node.Text = aClient.Name;
sl@32: //Add a child with SessionId
sl@33: node.Nodes.Add(new TreeNode(aClient.SessionId));
sl@33: }
sl@33: else
sl@33: {
sl@33: //No name, use session ID instead
sl@33: node.Text = aClient.SessionId;
sl@33: }
sl@36:
sl@33: if (aClient.Texts.Count > 0)
sl@33: {
sl@33: //Create root node for our texts
sl@33: TreeNode textsRoot = new TreeNode("Text");
sl@33: node.Nodes.Add(textsRoot);
sl@33: //For each text add a new entry
sl@43: foreach (TextField field in aClient.Texts)
sl@33: {
sl@43: textsRoot.Nodes.Add(new TreeNode(field.Text));
sl@33: }
sl@32: }
sl@34:
sl@34: node.ExpandAll();
sl@32: }
sl@30: }
sl@17:
sl@38: private void buttonAddRow_Click(object sender, EventArgs e)
sl@38: {
sl@38: if (tableLayoutPanel.RowCount < 6)
sl@38: {
sl@38: tableLayoutPanel.RowCount++;
sl@38: CheckFontHeight();
sl@38: }
sl@38: }
sl@38:
sl@38: private void buttonRemoveRow_Click(object sender, EventArgs e)
sl@38: {
sl@38: if (tableLayoutPanel.RowCount > 1)
sl@38: {
sl@38: tableLayoutPanel.RowCount--;
sl@38: CheckFontHeight();
sl@38: }
sl@38: }
sl@38:
sl@38: private void buttonAddColumn_Click(object sender, EventArgs e)
sl@38: {
sl@38: if (tableLayoutPanel.ColumnCount < 8)
sl@38: {
sl@38: tableLayoutPanel.ColumnCount++;
sl@38: //CheckFontHeight();
sl@38: }
sl@38: }
sl@38:
sl@38: private void buttonRemoveColumn_Click(object sender, EventArgs e)
sl@38: {
sl@38: if (tableLayoutPanel.ColumnCount > 1)
sl@38: {
sl@38: tableLayoutPanel.ColumnCount--;
sl@38: //CheckFontHeight();
sl@38: }
sl@38: }
sl@38:
sl@41: private void buttonAlignLeft_Click(object sender, EventArgs e)
sl@41: {
sl@41: marqueeLabelTop.TextAlign = ContentAlignment.MiddleLeft;
sl@41: marqueeLabelBottom.TextAlign = ContentAlignment.MiddleLeft;
sl@41: }
sl@41:
sl@41: private void buttonAlignCenter_Click(object sender, EventArgs e)
sl@41: {
sl@41: marqueeLabelTop.TextAlign = ContentAlignment.MiddleCenter;
sl@41: marqueeLabelBottom.TextAlign = ContentAlignment.MiddleCenter;
sl@41: }
sl@41:
sl@41: private void buttonAlignRight_Click(object sender, EventArgs e)
sl@41: {
sl@41: marqueeLabelTop.TextAlign = ContentAlignment.MiddleRight;
sl@41: marqueeLabelBottom.TextAlign = ContentAlignment.MiddleRight;
sl@41: }
sl@36:
sl@46: private void comboBoxDisplayType_SelectedIndexChanged(object sender, EventArgs e)
sl@46: {
sl@48: Properties.Settings.Default.CurrentDisplayIndex = comboBoxDisplayType.SelectedIndex;
sl@48: cds.DisplayType = comboBoxDisplayType.SelectedIndex;
sl@46: Properties.Settings.Default.Save();
sl@51: if (iDisplay.IsOpen())
sl@51: {
sl@51: OpenDisplayConnection();
sl@51: }
sl@51: else
sl@51: {
sl@51: UpdateStatus();
sl@51: }
sl@46: }
sl@46:
sl@47:
sl@47: private void maskedTextBoxTimerInterval_TextChanged(object sender, EventArgs e)
sl@47: {
sl@47: if (maskedTextBoxTimerInterval.Text != "")
sl@47: {
sl@51: int interval = Convert.ToInt32(maskedTextBoxTimerInterval.Text);
sl@51:
sl@51: if (interval > 0)
sl@51: {
sl@51: timer.Interval = interval;
sl@51: cds.TimerInterval = timer.Interval;
sl@51: Properties.Settings.Default.Save();
sl@51: }
sl@47: }
sl@47: }
sl@47:
sl@52: private void buttonPowerOn_Click(object sender, EventArgs e)
sl@52: {
sl@52: iDisplay.PowerOn();
sl@52: }
sl@52:
sl@52: private void buttonPowerOff_Click(object sender, EventArgs e)
sl@52: {
sl@52: iDisplay.PowerOff();
sl@52: }
sl@52:
sl@53: private void buttonShowClock_Click(object sender, EventArgs e)
sl@53: {
sl@53: iDisplay.ShowClock();
sl@53: }
sl@53:
sl@53: private void buttonHideClock_Click(object sender, EventArgs e)
sl@53: {
sl@53: iDisplay.HideClock();
sl@53: }
sl@53:
sl@0: }
sl@34:
sl@34: ///
sl@34: /// A UI thread copy of a client relevant data.
sl@34: /// Keeping this copy in the UI thread helps us deal with threading issues.
sl@34: ///
sl@34: public class ClientData
sl@34: {
sl@55: public ClientData(string aSessionId, ICallback aCallback)
sl@34: {
sl@34: SessionId = aSessionId;
sl@34: Name = "";
sl@43: Texts = new List();
sl@34: Callback = aCallback;
sl@34: }
sl@34:
sl@34: public string SessionId { get; set; }
sl@34: public string Name { get; set; }
sl@43: public List Texts { get; set; }
sl@55: public ICallback Callback { get; set; }
sl@34: }
sl@0: }