SharpDisplay: Migrating to new robust client scheme.
1.1 --- a/GUI/SharpDisplay.cs Mon Sep 22 21:59:11 2014 +0200
1.2 +++ b/GUI/SharpDisplay.cs Thu Jan 01 23:35:49 2015 +0100
1.3 @@ -25,19 +25,19 @@
1.4
1.5 namespace OpenHardwareMonitor.GUI
1.6 {
1.7 - public class SharpDisplay : ICallback, IDisposable
1.8 + public class SharpDisplay : IDisposable
1.9 {
1.10 private IComputer computer;
1.11 private PersistentSettings settings;
1.12 private UnitManager unitManager;
1.13 private List<SensorSharpDisplay> iSensors = new List<SensorSharpDisplay>();
1.14 - private global::SharpDisplay.Client iClient;
1.15 - TextField iTextFieldTop;
1.16 - TextField iTextFieldBottom;
1.17 - TextField iTextFieldTopRight;
1.18 - TextField iTextFieldBottomRight;
1.19 + private global::SharpDisplay.DisplayClient iClient;
1.20 + DataField iTextFieldTop;
1.21 + DataField iTextFieldBottom;
1.22 + DataField iTextFieldTopRight;
1.23 + DataField iTextFieldBottomRight;
1.24
1.25 - TextField[] iTextFields;
1.26 + DataField[] iTextFields;
1.27
1.28 private int iNextSensorToDisplay = 0;
1.29 private int iTickCounter = 0;
1.30 @@ -53,32 +53,18 @@
1.31
1.32 //Connect our client
1.33 //Instance context is then managed by our client class
1.34 - iClient = new global::SharpDisplay.Client(this);
1.35 + iClient = new global::SharpDisplay.DisplayClient();
1.36 //
1.37 - iTextFieldTop = new TextField(0);
1.38 - iTextFieldBottom = new TextField(1);
1.39 - iTextFieldTopRight = new TextField(2, "", ContentAlignment.MiddleRight);
1.40 - iTextFieldBottomRight = new TextField(3, "", ContentAlignment.MiddleRight);
1.41 -
1.42 - iTextFields = new TextField[] { iTextFieldTop, iTextFieldBottom };
1.43 -
1.44 + iTextFieldTop = new DataField(0);
1.45 + iTextFieldBottom = new DataField(1);
1.46 + iTextFieldTopRight = new DataField(2, "", ContentAlignment.MiddleRight);
1.47 + iTextFieldBottomRight = new DataField(3, "", ContentAlignment.MiddleRight);
1.48 + //
1.49 + iClient.Open();
1.50 + iClient.SetName("Open Hardware Monitor");
1.51 + CreateFields();
1.52 }
1.53
1.54 - //From ICallback
1.55 - public void OnConnected()
1.56 - {
1.57 - //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
1.58 - //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
1.59 - //MessageBox.Show("OnConnected()", "Client");
1.60 - }
1.61 -
1.62 - //From ICallback
1.63 - public void OnCloseOrder()
1.64 - {
1.65 - iClient.Close();
1.66 - }
1.67 -
1.68 -
1.69 private void HardwareRemoved(IHardware hardware)
1.70 {
1.71 hardware.SensorAdded -= new SensorEventHandler(SensorAdded);
1.72 @@ -123,6 +109,27 @@
1.73
1.74 }
1.75
1.76 + private void CreateFields()
1.77 + {
1.78 + if (iPacked)
1.79 + {
1.80 + //We just switched to packed mode
1.81 + //Make sure our layout is proper
1.82 + TableLayout layout = new TableLayout(2, 2);
1.83 + iClient.SetLayout(layout);
1.84 + iTextFields = new DataField[] { iTextFieldTop, iTextFieldBottom, iTextFieldTopRight, iTextFieldBottomRight };
1.85 + iClient.CreateFields(iTextFields);
1.86 + }
1.87 + else
1.88 + {
1.89 + //Non packed mode
1.90 + TableLayout layout = new TableLayout(1, 2);
1.91 + iClient.SetLayout(layout);
1.92 + iTextFields = new DataField[] { iTextFieldTop, iTextFieldBottom };
1.93 + iClient.CreateFields(iTextFields);
1.94 + }
1.95 + }
1.96 +
1.97 public void Redraw(bool aPacked, bool aDisplayTime)
1.98 {
1.99 const int KNumberOfTickBeforeSwitch = 4;
1.100 @@ -141,19 +148,8 @@
1.101 //Remember mode
1.102 iPacked = aPacked;
1.103
1.104 - if (iPacked)
1.105 - {
1.106 - //We just switched to packed mode
1.107 - //Make sure our layout is proper
1.108 - TableLayout layout = new TableLayout(2, 2);
1.109 - iClient.SetLayout(layout);
1.110 - }
1.111 - else
1.112 - {
1.113 - //Non packed mode
1.114 - TableLayout layout = new TableLayout(1, 2);
1.115 - iClient.SetLayout(layout);
1.116 - }
1.117 + CreateFields();
1.118 +
1.119 }
1.120 }
1.121
1.122 @@ -169,7 +165,7 @@
1.123 //First slot is taken by time display
1.124 count++;
1.125 iTextFieldTop.Text = time;
1.126 - iClient.SetText(iTextFieldTop);
1.127 + iClient.SetField(iTextFieldTop);
1.128 }
1.129
1.130 if (aPacked)
1.131 @@ -180,22 +176,22 @@
1.132 if (count == 1)
1.133 {
1.134 iTextFieldTop.Text = packedText;
1.135 - iClient.SetText(iTextFieldTop);
1.136 + iClient.SetField(iTextFieldTop);
1.137 }
1.138 else if (count == 2)
1.139 {
1.140 iTextFieldBottom.Text = packedText;
1.141 - iClient.SetText(iTextFieldBottom);
1.142 + iClient.SetField(iTextFieldBottom);
1.143 }
1.144 else if (count == 3)
1.145 {
1.146 iTextFieldTopRight.Text = packedText;
1.147 - iClient.SetText(iTextFieldTopRight);
1.148 + iClient.SetField(iTextFieldTopRight);
1.149 }
1.150 else if (count == 4)
1.151 {
1.152 iTextFieldBottomRight.Text = packedText;
1.153 - iClient.SetText(iTextFieldBottomRight);
1.154 + iClient.SetField(iTextFieldBottomRight);
1.155 }
1.156 }
1.157 }
1.158 @@ -345,7 +341,7 @@
1.159 //iServer.SendMessage("set-vfd-text:" + aUpperLine + "\n" + aLowerLine);
1.160 iTextFieldTop.Text = aUpperLine;
1.161 iTextFieldBottom.Text = aLowerLine;
1.162 - iClient.SetTexts(iTextFields);
1.163 + iClient.SetFields(iTextFields);
1.164
1.165 }
1.166
2.1 --- a/GUI/SharpDisplayClient.cs Mon Sep 22 21:59:11 2014 +0200
2.2 +++ b/GUI/SharpDisplayClient.cs Thu Jan 01 23:35:49 2015 +0100
2.3 @@ -1,207 +1,64 @@
2.4 -/*
2.5 -
2.6 - This Source Code Form is subject to the terms of the Mozilla Public
2.7 - License, v. 2.0. If a copy of the MPL was not distributed with this
2.8 - file, You can obtain one at http://mozilla.org/MPL/2.0/.
2.9 -
2.10 - Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
2.11 -
2.12 -*/
2.13 -
2.14 +
2.15 using System;
2.16 using System.Collections.Generic;
2.17 -using System.Drawing;
2.18 +using System.Linq;
2.19 using System.Text;
2.20 -using System.Diagnostics;
2.21 +using System.Threading.Tasks;
2.22 using System.Windows.Forms;
2.23 -using System.Windows;
2.24 -using OpenHardwareMonitor.Hardware;
2.25 -using OpenHardwareMonitor.Utilities;
2.26 -using System.Runtime.InteropServices;
2.27 -using UacHelpers;
2.28 -//
2.29 +using SharpDisplay;
2.30 using System.ServiceModel;
2.31 -using System.Runtime.Serialization;
2.32 -using SharpDisplay;
2.33 +using System.ServiceModel.Channels;
2.34 +
2.35
2.36 namespace SharpDisplay
2.37 {
2.38 -
2.39 -
2.40 -
2.41 - /// <summary>
2.42 - /// For client to specify a specific layout.
2.43 - /// </summary>
2.44 - [DataContract]
2.45 - public class TableLayout
2.46 - {
2.47 - public TableLayout()
2.48 - {
2.49 - Columns = new List<ColumnStyle>();
2.50 - Rows = new List<RowStyle>();
2.51 - Cells = new List<DataField>();
2.52 - }
2.53 -
2.54 - public TableLayout(int aColumnCount, int aRowCount)
2.55 - {
2.56 - Columns = new List<ColumnStyle>();
2.57 - Rows = new List<RowStyle>();
2.58 -
2.59 - for (int i = 0; i < aColumnCount; i++)
2.60 - {
2.61 - Columns.Add(new ColumnStyle(SizeType.Percent, 100 / aColumnCount));
2.62 - }
2.63 -
2.64 - for (int i = 0; i < aRowCount; i++)
2.65 - {
2.66 - Rows.Add(new RowStyle(SizeType.Percent, 100 / aRowCount));
2.67 - }
2.68 - }
2.69 -
2.70 - [DataMember]
2.71 - public List<DataField> Cells { get; set; }
2.72 -
2.73 - [DataMember]
2.74 - public List<ColumnStyle> Columns { get; set; }
2.75 -
2.76 - [DataMember]
2.77 - public List<RowStyle> Rows { get; set; }
2.78 -
2.79 - }
2.80 -
2.81 /// <summary>
2.82 ///
2.83 /// </summary>
2.84 - [DataContract]
2.85 - public class DataField
2.86 + [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
2.87 + public class Callback : ICallback, IDisposable
2.88 {
2.89 - [DataMember]
2.90 - public int Column { get; set; }
2.91 + private DisplayClient DisplayClient { get; set; }
2.92
2.93 - [DataMember]
2.94 - public int Row { get; set; }
2.95 + public Callback(DisplayClient aClient)
2.96 + {
2.97 + DisplayClient = aClient;
2.98 + }
2.99
2.100 - [DataMember]
2.101 - public int ColumnSpan { get; set; }
2.102 + public void OnConnected()
2.103 + {
2.104 + //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
2.105 + //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
2.106
2.107 - [DataMember]
2.108 - public int RowSpan { get; set; }
2.109 + MessageBox.Show("OnConnected()", "Client");
2.110 + }
2.111
2.112 +
2.113 + public void OnCloseOrder()
2.114 + {
2.115 + DisplayClient.Close();
2.116 + //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
2.117 + //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
2.118 +
2.119 + //MessageBox.Show("OnServerClosing()", "Client");
2.120 + //MainForm.CloseConnectionThreadSafe();
2.121 + //MainForm.CloseThreadSafe();
2.122 + }
2.123 +
2.124 + //From IDisposable
2.125 + public void Dispose()
2.126 + {
2.127 +
2.128 + }
2.129 }
2.130
2.131
2.132 /// <summary>
2.133 - /// TextField can be send to our server to be displayed on the screen.
2.134 - /// </summary>
2.135 - [DataContract]
2.136 - public class TextField : DataField
2.137 - {
2.138 - public TextField()
2.139 - {
2.140 - Index = 0;
2.141 - Text = "";
2.142 - Alignment = ContentAlignment.MiddleLeft;
2.143 - }
2.144 -
2.145 - public TextField(int aIndex, string aText = "", ContentAlignment aAlignment = ContentAlignment.MiddleLeft)
2.146 - {
2.147 - Index = aIndex;
2.148 - Text = aText;
2.149 - Alignment = aAlignment;
2.150 - }
2.151 -
2.152 - [DataMember]
2.153 - public int Index { get; set; }
2.154 -
2.155 - [DataMember]
2.156 - public string Text { get; set; }
2.157 -
2.158 - [DataMember]
2.159 - public ContentAlignment Alignment { get; set; }
2.160 - }
2.161 -
2.162 - /// <summary>
2.163 - /// Define our SharpDisplay service.
2.164 - /// Clients and servers must implement it to communicate with one another.
2.165 - /// Through this service clients can send requests to a server.
2.166 - /// Through this service a server session can receive requests from a client.
2.167 - /// </summary>
2.168 - [ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
2.169 - public interface IService
2.170 - {
2.171 - /// <summary>
2.172 - /// Set the name of this client.
2.173 - /// Name is a convenient way to recognize your client.
2.174 - /// Naming you client is not mandatory.
2.175 - /// In the absence of a name the session ID is often used instead.
2.176 - /// </summary>
2.177 - /// <param name="aClientName"></param>
2.178 - [OperationContract(IsOneWay = true)]
2.179 - void SetName(string aClientName);
2.180 -
2.181 -
2.182 - /// <summary>
2.183 - /// </summary>
2.184 - /// <param name="aLayout"></param>
2.185 - [OperationContract(IsOneWay = true)]
2.186 - void SetLayout(TableLayout aLayout);
2.187 -
2.188 - /// <summary>
2.189 - /// Put the given text in the given field on your display.
2.190 - /// Fields are often just lines of text.
2.191 - /// </summary>
2.192 - /// <param name="aTextFieldIndex"></param>
2.193 - [OperationContract(IsOneWay = true)]
2.194 - void SetText(TextField aTextField);
2.195 -
2.196 - /// <summary>
2.197 - /// Allows a client to set multiple text fields at once.
2.198 - /// </summary>
2.199 - /// <param name="aTexts"></param>
2.200 - [OperationContract(IsOneWay = true)]
2.201 - void SetTexts(System.Collections.Generic.IList<TextField> aTextFields);
2.202 -
2.203 - /// <summary>
2.204 - /// Provides the number of clients currently connected
2.205 - /// </summary>
2.206 - /// <returns></returns>
2.207 - [OperationContract()]
2.208 - int ClientCount();
2.209 -
2.210 - }
2.211 -
2.212 - /// <summary>
2.213 - /// SharDisplay callback provides a means for a server to notify its clients.
2.214 - /// </summary>
2.215 - public interface ICallback
2.216 - {
2.217 - [OperationContract(IsOneWay = true)]
2.218 - void OnConnected();
2.219 -
2.220 - /// <summary>
2.221 - /// Tell our client to close its connection.
2.222 - /// Notably sent when the server is shutting down.
2.223 - /// </summary>
2.224 - [OperationContract(IsOneWay = true)]
2.225 - void OnCloseOrder();
2.226 - }
2.227 -
2.228 -
2.229 -
2.230 -}
2.231 -
2.232 -
2.233 -
2.234 -namespace SharpDisplay
2.235 -{
2.236 -
2.237 - /// <summary>
2.238 ///
2.239 /// </summary>
2.240 [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
2.241 public class Client : DuplexClientBase<IService>
2.242 {
2.243 - public string Name { get; set; }
2.244 public string SessionId { get { return InnerChannel.SessionId; } }
2.245
2.246 public Client(ICallback aCallback)
2.247 @@ -210,7 +67,6 @@
2.248
2.249 public void SetName(string aClientName)
2.250 {
2.251 - Name = aClientName;
2.252 Channel.SetName(aClientName);
2.253 }
2.254
2.255 @@ -219,14 +75,14 @@
2.256 Channel.SetLayout(aLayout);
2.257 }
2.258
2.259 - public void SetText(TextField aTextField)
2.260 + public void SetField(DataField aField)
2.261 {
2.262 - Channel.SetText(aTextField);
2.263 + Channel.SetField(aField);
2.264 }
2.265
2.266 - public void SetTexts(System.Collections.Generic.IList<TextField> aTextFields)
2.267 + public void SetFields(System.Collections.Generic.IList<DataField> aFields)
2.268 {
2.269 - Channel.SetTexts(aTextFields);
2.270 + Channel.SetFields(aFields);
2.271 }
2.272
2.273 public int ClientCount()
2.274 @@ -236,10 +92,200 @@
2.275
2.276 public bool IsReady()
2.277 {
2.278 - return State == CommunicationState.Opened;
2.279 + return State == CommunicationState.Opened || State == CommunicationState.Created;
2.280 }
2.281 + }
2.282 +
2.283 +
2.284 + /// <summary>
2.285 + /// Handle connection with our Sharp Display Server.
2.286 + /// If the connection is faulted it will attempt to restart it.
2.287 + /// </summary>
2.288 + public class DisplayClient
2.289 + {
2.290 + private Client iClient;
2.291 + private Callback iCallback;
2.292 + private bool resetingConnection = false;
2.293 +
2.294 + //private MainForm MainForm { get; set; }
2.295 + public string SessionId { get { return iClient.SessionId; } }
2.296 + public string Name { get; private set; }
2.297 + private TableLayout Layout { get; set; }
2.298 + private System.Collections.Generic.IList<DataField> Fields { get; set; }
2.299 +
2.300 +
2.301 + public DisplayClient(/*MainForm aMainForm*/)
2.302 + {
2.303 + //MainForm = aMainForm;
2.304 + Name = "";
2.305 + Fields = new DataField[]{};
2.306 + }
2.307 +
2.308 + /// <summary>
2.309 + /// Initialize our server connection.
2.310 + /// </summary>
2.311 + public void Open()
2.312 + {
2.313 + iCallback = new Callback(this);
2.314 + iClient = new Client(iCallback);
2.315 + }
2.316 +
2.317 + /// <summary>
2.318 + /// Terminate our server connection.
2.319 + /// </summary>
2.320 + public void Close()
2.321 + {
2.322 + iClient.Close();
2.323 + iClient = null;
2.324 + iCallback.Dispose();
2.325 + iCallback = null;
2.326 + }
2.327 +
2.328 + /// <summary>
2.329 + /// Tells whether a server connection is available.
2.330 + /// </summary>
2.331 + /// <returns>True if a server connection is available. False otherwise.</returns>
2.332 + public bool IsReady()
2.333 + {
2.334 + return (iClient != null && iCallback != null && iClient.IsReady());
2.335 + }
2.336 +
2.337 + /// <summary>
2.338 + /// Check if our server connection is available and attempt reset it if it isn't.
2.339 + /// This is notably dealing with timed out connections.
2.340 + /// </summary>
2.341 + public void CheckConnection()
2.342 + {
2.343 + if (!IsReady() && !resetingConnection)
2.344 + {
2.345 + //Try to reconnect
2.346 + Open();
2.347 +
2.348 + //Avoid stack overflow in case of persisting failure
2.349 + resetingConnection = true;
2.350 +
2.351 + try
2.352 + {
2.353 + //On reconnect there is a bunch of properties we need to reset
2.354 + if (Name != "")
2.355 + {
2.356 + iClient.SetName(Name);
2.357 + }
2.358 +
2.359 + SetLayout(Layout);
2.360 + iClient.SetFields(Fields);
2.361 + }
2.362 + finally
2.363 + {
2.364 + //Make sure our this state does not get out of sync
2.365 + resetingConnection = true;
2.366 + }
2.367 + }
2.368 + }
2.369 +
2.370 + public void SetName(string aClientName)
2.371 + {
2.372 + Name = aClientName;
2.373 + CheckConnection();
2.374 + iClient.SetName(aClientName);
2.375 + }
2.376 +
2.377 +
2.378 + public void SetLayout(TableLayout aLayout)
2.379 + {
2.380 + Layout = aLayout;
2.381 + CheckConnection();
2.382 + iClient.SetLayout(aLayout);
2.383 + }
2.384 +
2.385 + /// <summary>
2.386 + /// Set the specified field.
2.387 + /// </summary>
2.388 + /// <param name="aField"></param>
2.389 + /// <returns>True if the specified field was set client side. False means you need to redefine all your fields using CreateFields.</returns>
2.390 + public bool SetField(DataField aField)
2.391 + {
2.392 + int i = 0;
2.393 + bool fieldFound = false;
2.394 + foreach (DataField field in Fields)
2.395 + {
2.396 + if (field.Index == aField.Index)
2.397 + {
2.398 + //Update our field then
2.399 + Fields[i] = aField;
2.400 + fieldFound = true;
2.401 + break;
2.402 + }
2.403 + i++;
2.404 + }
2.405 +
2.406 + if (!fieldFound)
2.407 + {
2.408 + //Field not found, make to use SetFields with all your fields at least once after setting your layout.
2.409 + return false;
2.410 + }
2.411 +
2.412 + CheckConnection();
2.413 + iClient.SetField(aField);
2.414 + return true;
2.415 + }
2.416 +
2.417 + /// <summary>
2.418 + /// Use this function when updating existing fields.
2.419 + /// </summary>
2.420 + /// <param name="aFields"></param>
2.421 + public bool SetFields(System.Collections.Generic.IList<DataField> aFields)
2.422 + {
2.423 + int fieldFoundCount = 0;
2.424 + foreach (DataField fieldUpdate in aFields)
2.425 + {
2.426 + int i = 0;
2.427 + foreach (DataField existingField in Fields)
2.428 + {
2.429 + if (existingField.Index == fieldUpdate.Index)
2.430 + {
2.431 + //Update our field then
2.432 + Fields[i] = fieldUpdate;
2.433 + fieldFoundCount++;
2.434 + //Move on to the next field
2.435 + break;
2.436 + }
2.437 + i++;
2.438 + }
2.439 + }
2.440 +
2.441 + //
2.442 + if (fieldFoundCount!=aFields.Count)
2.443 + {
2.444 + //Field not found, make sure to use SetFields with all your fields at least once after setting your layout.
2.445 + return false;
2.446 + }
2.447 +
2.448 + CheckConnection();
2.449 + iClient.SetFields(aFields);
2.450 + return true;
2.451 + }
2.452 +
2.453 + /// <summary>
2.454 + /// Use this function when creating your fields.
2.455 + /// </summary>
2.456 + /// <param name="aFields"></param>
2.457 + public void CreateFields(System.Collections.Generic.IList<DataField> aFields)
2.458 + {
2.459 + Fields = aFields;
2.460 + CheckConnection();
2.461 + iClient.SetFields(aFields);
2.462 + }
2.463 +
2.464 + public int ClientCount()
2.465 + {
2.466 + CheckConnection();
2.467 + return iClient.ClientCount();
2.468 + }
2.469 +
2.470 +
2.471
2.472 }
2.473
2.474
2.475 -}
2.476 \ No newline at end of file
2.477 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/GUI/SharpDisplayInterface.cs Thu Jan 01 23:35:49 2015 +0100
3.3 @@ -0,0 +1,204 @@
3.4 +//
3.5 +// Define a public API for both SharpDisplay client and server to use.
3.6 +//
3.7 +
3.8 +using System;
3.9 +using System.Collections.Generic;
3.10 +using System.Linq;
3.11 +using System.Text;
3.12 +using System.Threading.Tasks;
3.13 +using System.ServiceModel;
3.14 +using System.Collections;
3.15 +using System.Drawing;
3.16 +using System.Runtime.Serialization;
3.17 +using System.Windows.Forms;
3.18 +
3.19 +
3.20 +namespace SharpDisplay
3.21 +{
3.22 + /// <summary>
3.23 + /// For client to specify a specific layout.
3.24 + /// </summary>
3.25 + [DataContract]
3.26 + public class TableLayout
3.27 + {
3.28 + public TableLayout()
3.29 + {
3.30 + Columns = new List<ColumnStyle>();
3.31 + Rows = new List<RowStyle>();
3.32 + Cells = new List<DataField>();
3.33 + }
3.34 +
3.35 + public TableLayout(int aColumnCount, int aRowCount)
3.36 + {
3.37 + Columns = new List<ColumnStyle>();
3.38 + Rows = new List<RowStyle>();
3.39 +
3.40 + for (int i = 0; i < aColumnCount; i++)
3.41 + {
3.42 + Columns.Add(new ColumnStyle(SizeType.Percent, 100 / aColumnCount));
3.43 + }
3.44 +
3.45 + for (int i = 0; i < aRowCount; i++)
3.46 + {
3.47 + Rows.Add(new RowStyle(SizeType.Percent, 100 / aRowCount));
3.48 + }
3.49 + }
3.50 +
3.51 + [DataMember]
3.52 + public List<DataField> Cells { get; set; }
3.53 +
3.54 + [DataMember]
3.55 + public List<ColumnStyle> Columns { get; set; }
3.56 +
3.57 + [DataMember]
3.58 + public List<RowStyle> Rows { get; set; }
3.59 + }
3.60 +
3.61 + /// <summary>
3.62 + ///
3.63 + /// </summary>
3.64 + [DataContract]
3.65 + public class DataField
3.66 + {
3.67 + public DataField()
3.68 + {
3.69 + Index = 0;
3.70 + ColumnSpan = 1;
3.71 + RowSpan = 1;
3.72 + //Text
3.73 + Text = "";
3.74 + Alignment = ContentAlignment.MiddleLeft;
3.75 + //Bitmap
3.76 + Bitmap = null;
3.77 + }
3.78 +
3.79 + //Text constructor
3.80 + public DataField(int aIndex, string aText = "", ContentAlignment aAlignment = ContentAlignment.MiddleLeft)
3.81 + {
3.82 + ColumnSpan = 1;
3.83 + RowSpan = 1;
3.84 + Index = aIndex;
3.85 + Text = aText;
3.86 + Alignment = aAlignment;
3.87 + //
3.88 + Bitmap = null;
3.89 + }
3.90 +
3.91 + //Bitmap constructor
3.92 + public DataField(int aIndex, Bitmap aBitmap)
3.93 + {
3.94 + ColumnSpan = 1;
3.95 + RowSpan = 1;
3.96 + Index = aIndex;
3.97 + Bitmap = aBitmap;
3.98 + //Text
3.99 + Text = "";
3.100 + Alignment = ContentAlignment.MiddleLeft;
3.101 + }
3.102 +
3.103 +
3.104 + //Generic layout properties
3.105 + [DataMember]
3.106 + public int Index { get; set; }
3.107 +
3.108 + [DataMember]
3.109 + public int Column { get; set; }
3.110 +
3.111 + [DataMember]
3.112 + public int Row { get; set; }
3.113 +
3.114 + [DataMember]
3.115 + public int ColumnSpan { get; set; }
3.116 +
3.117 + [DataMember]
3.118 + public int RowSpan { get; set; }
3.119 +
3.120 + //Text properties
3.121 + [DataMember]
3.122 + public string Text { get; set; }
3.123 +
3.124 + [DataMember]
3.125 + public ContentAlignment Alignment { get; set; }
3.126 +
3.127 + //Bitmap properties
3.128 + [DataMember]
3.129 + public Bitmap Bitmap { get; set; }
3.130 +
3.131 + //
3.132 + public bool IsBitmap { get { return Bitmap != null; } }
3.133 + //
3.134 + public bool IsText { get { return Bitmap == null; } }
3.135 + //
3.136 + public bool IsSameLayout(DataField aField)
3.137 + {
3.138 + return (aField.ColumnSpan == ColumnSpan && aField.RowSpan == RowSpan);
3.139 + }
3.140 + }
3.141 +
3.142 + /// <summary>
3.143 + /// Define our SharpDisplay service.
3.144 + /// Clients and servers must implement it to communicate with one another.
3.145 + /// Through this service clients can send requests to a server.
3.146 + /// Through this service a server session can receive requests from a client.
3.147 + /// </summary>
3.148 + [ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
3.149 + public interface IService
3.150 + {
3.151 + /// <summary>
3.152 + /// Set the name of this client.
3.153 + /// Name is a convenient way to recognize your client.
3.154 + /// Naming you client is not mandatory.
3.155 + /// In the absence of a name the session ID is often used instead.
3.156 + /// </summary>
3.157 + /// <param name="aClientName"></param>
3.158 + [OperationContract(IsOneWay = true)]
3.159 + void SetName(string aClientName);
3.160 +
3.161 + /// <summary>
3.162 + /// </summary>
3.163 + /// <param name="aLayout"></param>
3.164 + [OperationContract(IsOneWay = true)]
3.165 + void SetLayout(TableLayout aLayout);
3.166 +
3.167 + /// <summary>
3.168 + /// Set the given field on your display.
3.169 + /// Fields are often just lines of text or bitmaps.
3.170 + /// </summary>
3.171 + /// <param name="aTextFieldIndex"></param>
3.172 + [OperationContract(IsOneWay = true)]
3.173 + void SetField(DataField aField);
3.174 +
3.175 + /// <summary>
3.176 + /// Allows a client to set multiple fields at once.
3.177 + /// </summary>
3.178 + /// <param name="aFields"></param>
3.179 + [OperationContract(IsOneWay = true)]
3.180 + void SetFields(System.Collections.Generic.IList<DataField> aFields);
3.181 +
3.182 + /// <summary>
3.183 + /// Provides the number of clients currently connected
3.184 + /// </summary>
3.185 + /// <returns></returns>
3.186 + [OperationContract()]
3.187 + int ClientCount();
3.188 +
3.189 + }
3.190 +
3.191 + /// <summary>
3.192 + /// SharDisplay callback provides a means for a server to notify its clients.
3.193 + /// </summary>
3.194 + public interface ICallback
3.195 + {
3.196 + [OperationContract(IsOneWay = true)]
3.197 + void OnConnected();
3.198 +
3.199 + /// <summary>
3.200 + /// Tell our client to close its connection.
3.201 + /// Notably sent when the server is shutting down.
3.202 + /// </summary>
3.203 + [OperationContract(IsOneWay = true)]
3.204 + void OnCloseOrder();
3.205 + }
3.206 +
3.207 +}
4.1 --- a/OpenHardwareMonitor.csproj Mon Sep 22 21:59:11 2014 +0200
4.2 +++ b/OpenHardwareMonitor.csproj Thu Jan 01 23:35:49 2015 +0100
4.3 @@ -117,6 +117,7 @@
4.4 <Compile Include="GUI\SensorSharpDisplay.cs" />
4.5 <Compile Include="GUI\SharpDisplay.cs" />
4.6 <Compile Include="GUI\SharpDisplayClient.cs" />
4.7 + <Compile Include="GUI\SharpDisplayInterface.cs" />
4.8 <Compile Include="GUI\ShowDesktop.cs" />
4.9 <Compile Include="GUI\SoundGraphDisplay.cs" />
4.10 <Compile Include="GUI\SoundGraphServer.cs" />