SharpDisplay: Migrating to new robust client scheme.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/.editorconfig Thu Jan 01 23:35:49 2015 +0100
1.3 @@ -0,0 +1,12 @@
1.4 +; Top-most EditorConfig file
1.5 +root = true
1.6 +
1.7 +; Windows-style newlines
1.8 +[*]
1.9 +end_of_line = crlf
1.10 +
1.11 +; 4-column tab indentation
1.12 +[*.cs]
1.13 +indent_style = tab
1.14 +indent_size = 4
1.15 +
2.1 --- a/GUI/SharpDisplay.cs Mon Sep 22 21:59:11 2014 +0200
2.2 +++ b/GUI/SharpDisplay.cs Thu Jan 01 23:35:49 2015 +0100
2.3 @@ -25,19 +25,19 @@
2.4
2.5 namespace OpenHardwareMonitor.GUI
2.6 {
2.7 - public class SharpDisplay : ICallback, IDisposable
2.8 + public class SharpDisplay : IDisposable
2.9 {
2.10 private IComputer computer;
2.11 private PersistentSettings settings;
2.12 private UnitManager unitManager;
2.13 private List<SensorSharpDisplay> iSensors = new List<SensorSharpDisplay>();
2.14 - private global::SharpDisplay.Client iClient;
2.15 - TextField iTextFieldTop;
2.16 - TextField iTextFieldBottom;
2.17 - TextField iTextFieldTopRight;
2.18 - TextField iTextFieldBottomRight;
2.19 + private global::SharpDisplay.DisplayClient iClient;
2.20 + DataField iTextFieldTop;
2.21 + DataField iTextFieldBottom;
2.22 + DataField iTextFieldTopRight;
2.23 + DataField iTextFieldBottomRight;
2.24
2.25 - TextField[] iTextFields;
2.26 + DataField[] iTextFields;
2.27
2.28 private int iNextSensorToDisplay = 0;
2.29 private int iTickCounter = 0;
2.30 @@ -53,32 +53,18 @@
2.31
2.32 //Connect our client
2.33 //Instance context is then managed by our client class
2.34 - iClient = new global::SharpDisplay.Client(this);
2.35 + iClient = new global::SharpDisplay.DisplayClient();
2.36 //
2.37 - iTextFieldTop = new TextField(0);
2.38 - iTextFieldBottom = new TextField(1);
2.39 - iTextFieldTopRight = new TextField(2, "", ContentAlignment.MiddleRight);
2.40 - iTextFieldBottomRight = new TextField(3, "", ContentAlignment.MiddleRight);
2.41 -
2.42 - iTextFields = new TextField[] { iTextFieldTop, iTextFieldBottom };
2.43 -
2.44 + iTextFieldTop = new DataField(0);
2.45 + iTextFieldBottom = new DataField(1);
2.46 + iTextFieldTopRight = new DataField(2, "", ContentAlignment.MiddleRight);
2.47 + iTextFieldBottomRight = new DataField(3, "", ContentAlignment.MiddleRight);
2.48 + //
2.49 + iClient.Open();
2.50 + iClient.SetName("Open Hardware Monitor");
2.51 + CreateFields();
2.52 }
2.53
2.54 - //From ICallback
2.55 - public void OnConnected()
2.56 - {
2.57 - //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
2.58 - //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
2.59 - //MessageBox.Show("OnConnected()", "Client");
2.60 - }
2.61 -
2.62 - //From ICallback
2.63 - public void OnCloseOrder()
2.64 - {
2.65 - iClient.Close();
2.66 - }
2.67 -
2.68 -
2.69 private void HardwareRemoved(IHardware hardware)
2.70 {
2.71 hardware.SensorAdded -= new SensorEventHandler(SensorAdded);
2.72 @@ -123,6 +109,27 @@
2.73
2.74 }
2.75
2.76 + private void CreateFields()
2.77 + {
2.78 + if (iPacked)
2.79 + {
2.80 + //We just switched to packed mode
2.81 + //Make sure our layout is proper
2.82 + TableLayout layout = new TableLayout(2, 2);
2.83 + iClient.SetLayout(layout);
2.84 + iTextFields = new DataField[] { iTextFieldTop, iTextFieldBottom, iTextFieldTopRight, iTextFieldBottomRight };
2.85 + iClient.CreateFields(iTextFields);
2.86 + }
2.87 + else
2.88 + {
2.89 + //Non packed mode
2.90 + TableLayout layout = new TableLayout(1, 2);
2.91 + iClient.SetLayout(layout);
2.92 + iTextFields = new DataField[] { iTextFieldTop, iTextFieldBottom };
2.93 + iClient.CreateFields(iTextFields);
2.94 + }
2.95 + }
2.96 +
2.97 public void Redraw(bool aPacked, bool aDisplayTime)
2.98 {
2.99 const int KNumberOfTickBeforeSwitch = 4;
2.100 @@ -141,19 +148,8 @@
2.101 //Remember mode
2.102 iPacked = aPacked;
2.103
2.104 - if (iPacked)
2.105 - {
2.106 - //We just switched to packed mode
2.107 - //Make sure our layout is proper
2.108 - TableLayout layout = new TableLayout(2, 2);
2.109 - iClient.SetLayout(layout);
2.110 - }
2.111 - else
2.112 - {
2.113 - //Non packed mode
2.114 - TableLayout layout = new TableLayout(1, 2);
2.115 - iClient.SetLayout(layout);
2.116 - }
2.117 + CreateFields();
2.118 +
2.119 }
2.120 }
2.121
2.122 @@ -169,7 +165,7 @@
2.123 //First slot is taken by time display
2.124 count++;
2.125 iTextFieldTop.Text = time;
2.126 - iClient.SetText(iTextFieldTop);
2.127 + iClient.SetField(iTextFieldTop);
2.128 }
2.129
2.130 if (aPacked)
2.131 @@ -180,22 +176,22 @@
2.132 if (count == 1)
2.133 {
2.134 iTextFieldTop.Text = packedText;
2.135 - iClient.SetText(iTextFieldTop);
2.136 + iClient.SetField(iTextFieldTop);
2.137 }
2.138 else if (count == 2)
2.139 {
2.140 iTextFieldBottom.Text = packedText;
2.141 - iClient.SetText(iTextFieldBottom);
2.142 + iClient.SetField(iTextFieldBottom);
2.143 }
2.144 else if (count == 3)
2.145 {
2.146 iTextFieldTopRight.Text = packedText;
2.147 - iClient.SetText(iTextFieldTopRight);
2.148 + iClient.SetField(iTextFieldTopRight);
2.149 }
2.150 else if (count == 4)
2.151 {
2.152 iTextFieldBottomRight.Text = packedText;
2.153 - iClient.SetText(iTextFieldBottomRight);
2.154 + iClient.SetField(iTextFieldBottomRight);
2.155 }
2.156 }
2.157 }
2.158 @@ -345,7 +341,7 @@
2.159 //iServer.SendMessage("set-vfd-text:" + aUpperLine + "\n" + aLowerLine);
2.160 iTextFieldTop.Text = aUpperLine;
2.161 iTextFieldBottom.Text = aLowerLine;
2.162 - iClient.SetTexts(iTextFields);
2.163 + iClient.SetFields(iTextFields);
2.164
2.165 }
2.166
3.1 --- a/GUI/SharpDisplayClient.cs Mon Sep 22 21:59:11 2014 +0200
3.2 +++ b/GUI/SharpDisplayClient.cs Thu Jan 01 23:35:49 2015 +0100
3.3 @@ -1,207 +1,64 @@
3.4 -/*
3.5 -
3.6 - This Source Code Form is subject to the terms of the Mozilla Public
3.7 - License, v. 2.0. If a copy of the MPL was not distributed with this
3.8 - file, You can obtain one at http://mozilla.org/MPL/2.0/.
3.9 -
3.10 - Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
3.11 -
3.12 -*/
3.13 -
3.14 +
3.15 using System;
3.16 using System.Collections.Generic;
3.17 -using System.Drawing;
3.18 +using System.Linq;
3.19 using System.Text;
3.20 -using System.Diagnostics;
3.21 +using System.Threading.Tasks;
3.22 using System.Windows.Forms;
3.23 -using System.Windows;
3.24 -using OpenHardwareMonitor.Hardware;
3.25 -using OpenHardwareMonitor.Utilities;
3.26 -using System.Runtime.InteropServices;
3.27 -using UacHelpers;
3.28 -//
3.29 +using SharpDisplay;
3.30 using System.ServiceModel;
3.31 -using System.Runtime.Serialization;
3.32 -using SharpDisplay;
3.33 +using System.ServiceModel.Channels;
3.34 +
3.35
3.36 namespace SharpDisplay
3.37 {
3.38 -
3.39 -
3.40 -
3.41 - /// <summary>
3.42 - /// For client to specify a specific layout.
3.43 - /// </summary>
3.44 - [DataContract]
3.45 - public class TableLayout
3.46 - {
3.47 - public TableLayout()
3.48 - {
3.49 - Columns = new List<ColumnStyle>();
3.50 - Rows = new List<RowStyle>();
3.51 - Cells = new List<DataField>();
3.52 - }
3.53 -
3.54 - public TableLayout(int aColumnCount, int aRowCount)
3.55 - {
3.56 - Columns = new List<ColumnStyle>();
3.57 - Rows = new List<RowStyle>();
3.58 -
3.59 - for (int i = 0; i < aColumnCount; i++)
3.60 - {
3.61 - Columns.Add(new ColumnStyle(SizeType.Percent, 100 / aColumnCount));
3.62 - }
3.63 -
3.64 - for (int i = 0; i < aRowCount; i++)
3.65 - {
3.66 - Rows.Add(new RowStyle(SizeType.Percent, 100 / aRowCount));
3.67 - }
3.68 - }
3.69 -
3.70 - [DataMember]
3.71 - public List<DataField> Cells { get; set; }
3.72 -
3.73 - [DataMember]
3.74 - public List<ColumnStyle> Columns { get; set; }
3.75 -
3.76 - [DataMember]
3.77 - public List<RowStyle> Rows { get; set; }
3.78 -
3.79 - }
3.80 -
3.81 /// <summary>
3.82 ///
3.83 /// </summary>
3.84 - [DataContract]
3.85 - public class DataField
3.86 + [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
3.87 + public class Callback : ICallback, IDisposable
3.88 {
3.89 - [DataMember]
3.90 - public int Column { get; set; }
3.91 + private DisplayClient DisplayClient { get; set; }
3.92
3.93 - [DataMember]
3.94 - public int Row { get; set; }
3.95 + public Callback(DisplayClient aClient)
3.96 + {
3.97 + DisplayClient = aClient;
3.98 + }
3.99
3.100 - [DataMember]
3.101 - public int ColumnSpan { get; set; }
3.102 + public void OnConnected()
3.103 + {
3.104 + //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
3.105 + //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
3.106
3.107 - [DataMember]
3.108 - public int RowSpan { get; set; }
3.109 + MessageBox.Show("OnConnected()", "Client");
3.110 + }
3.111
3.112 +
3.113 + public void OnCloseOrder()
3.114 + {
3.115 + DisplayClient.Close();
3.116 + //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
3.117 + //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
3.118 +
3.119 + //MessageBox.Show("OnServerClosing()", "Client");
3.120 + //MainForm.CloseConnectionThreadSafe();
3.121 + //MainForm.CloseThreadSafe();
3.122 + }
3.123 +
3.124 + //From IDisposable
3.125 + public void Dispose()
3.126 + {
3.127 +
3.128 + }
3.129 }
3.130
3.131
3.132 /// <summary>
3.133 - /// TextField can be send to our server to be displayed on the screen.
3.134 - /// </summary>
3.135 - [DataContract]
3.136 - public class TextField : DataField
3.137 - {
3.138 - public TextField()
3.139 - {
3.140 - Index = 0;
3.141 - Text = "";
3.142 - Alignment = ContentAlignment.MiddleLeft;
3.143 - }
3.144 -
3.145 - public TextField(int aIndex, string aText = "", ContentAlignment aAlignment = ContentAlignment.MiddleLeft)
3.146 - {
3.147 - Index = aIndex;
3.148 - Text = aText;
3.149 - Alignment = aAlignment;
3.150 - }
3.151 -
3.152 - [DataMember]
3.153 - public int Index { get; set; }
3.154 -
3.155 - [DataMember]
3.156 - public string Text { get; set; }
3.157 -
3.158 - [DataMember]
3.159 - public ContentAlignment Alignment { get; set; }
3.160 - }
3.161 -
3.162 - /// <summary>
3.163 - /// Define our SharpDisplay service.
3.164 - /// Clients and servers must implement it to communicate with one another.
3.165 - /// Through this service clients can send requests to a server.
3.166 - /// Through this service a server session can receive requests from a client.
3.167 - /// </summary>
3.168 - [ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
3.169 - public interface IService
3.170 - {
3.171 - /// <summary>
3.172 - /// Set the name of this client.
3.173 - /// Name is a convenient way to recognize your client.
3.174 - /// Naming you client is not mandatory.
3.175 - /// In the absence of a name the session ID is often used instead.
3.176 - /// </summary>
3.177 - /// <param name="aClientName"></param>
3.178 - [OperationContract(IsOneWay = true)]
3.179 - void SetName(string aClientName);
3.180 -
3.181 -
3.182 - /// <summary>
3.183 - /// </summary>
3.184 - /// <param name="aLayout"></param>
3.185 - [OperationContract(IsOneWay = true)]
3.186 - void SetLayout(TableLayout aLayout);
3.187 -
3.188 - /// <summary>
3.189 - /// Put the given text in the given field on your display.
3.190 - /// Fields are often just lines of text.
3.191 - /// </summary>
3.192 - /// <param name="aTextFieldIndex"></param>
3.193 - [OperationContract(IsOneWay = true)]
3.194 - void SetText(TextField aTextField);
3.195 -
3.196 - /// <summary>
3.197 - /// Allows a client to set multiple text fields at once.
3.198 - /// </summary>
3.199 - /// <param name="aTexts"></param>
3.200 - [OperationContract(IsOneWay = true)]
3.201 - void SetTexts(System.Collections.Generic.IList<TextField> aTextFields);
3.202 -
3.203 - /// <summary>
3.204 - /// Provides the number of clients currently connected
3.205 - /// </summary>
3.206 - /// <returns></returns>
3.207 - [OperationContract()]
3.208 - int ClientCount();
3.209 -
3.210 - }
3.211 -
3.212 - /// <summary>
3.213 - /// SharDisplay callback provides a means for a server to notify its clients.
3.214 - /// </summary>
3.215 - public interface ICallback
3.216 - {
3.217 - [OperationContract(IsOneWay = true)]
3.218 - void OnConnected();
3.219 -
3.220 - /// <summary>
3.221 - /// Tell our client to close its connection.
3.222 - /// Notably sent when the server is shutting down.
3.223 - /// </summary>
3.224 - [OperationContract(IsOneWay = true)]
3.225 - void OnCloseOrder();
3.226 - }
3.227 -
3.228 -
3.229 -
3.230 -}
3.231 -
3.232 -
3.233 -
3.234 -namespace SharpDisplay
3.235 -{
3.236 -
3.237 - /// <summary>
3.238 ///
3.239 /// </summary>
3.240 [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
3.241 public class Client : DuplexClientBase<IService>
3.242 {
3.243 - public string Name { get; set; }
3.244 public string SessionId { get { return InnerChannel.SessionId; } }
3.245
3.246 public Client(ICallback aCallback)
3.247 @@ -210,7 +67,6 @@
3.248
3.249 public void SetName(string aClientName)
3.250 {
3.251 - Name = aClientName;
3.252 Channel.SetName(aClientName);
3.253 }
3.254
3.255 @@ -219,14 +75,14 @@
3.256 Channel.SetLayout(aLayout);
3.257 }
3.258
3.259 - public void SetText(TextField aTextField)
3.260 + public void SetField(DataField aField)
3.261 {
3.262 - Channel.SetText(aTextField);
3.263 + Channel.SetField(aField);
3.264 }
3.265
3.266 - public void SetTexts(System.Collections.Generic.IList<TextField> aTextFields)
3.267 + public void SetFields(System.Collections.Generic.IList<DataField> aFields)
3.268 {
3.269 - Channel.SetTexts(aTextFields);
3.270 + Channel.SetFields(aFields);
3.271 }
3.272
3.273 public int ClientCount()
3.274 @@ -236,10 +92,200 @@
3.275
3.276 public bool IsReady()
3.277 {
3.278 - return State == CommunicationState.Opened;
3.279 + return State == CommunicationState.Opened || State == CommunicationState.Created;
3.280 }
3.281 + }
3.282 +
3.283 +
3.284 + /// <summary>
3.285 + /// Handle connection with our Sharp Display Server.
3.286 + /// If the connection is faulted it will attempt to restart it.
3.287 + /// </summary>
3.288 + public class DisplayClient
3.289 + {
3.290 + private Client iClient;
3.291 + private Callback iCallback;
3.292 + private bool resetingConnection = false;
3.293 +
3.294 + //private MainForm MainForm { get; set; }
3.295 + public string SessionId { get { return iClient.SessionId; } }
3.296 + public string Name { get; private set; }
3.297 + private TableLayout Layout { get; set; }
3.298 + private System.Collections.Generic.IList<DataField> Fields { get; set; }
3.299 +
3.300 +
3.301 + public DisplayClient(/*MainForm aMainForm*/)
3.302 + {
3.303 + //MainForm = aMainForm;
3.304 + Name = "";
3.305 + Fields = new DataField[]{};
3.306 + }
3.307 +
3.308 + /// <summary>
3.309 + /// Initialize our server connection.
3.310 + /// </summary>
3.311 + public void Open()
3.312 + {
3.313 + iCallback = new Callback(this);
3.314 + iClient = new Client(iCallback);
3.315 + }
3.316 +
3.317 + /// <summary>
3.318 + /// Terminate our server connection.
3.319 + /// </summary>
3.320 + public void Close()
3.321 + {
3.322 + iClient.Close();
3.323 + iClient = null;
3.324 + iCallback.Dispose();
3.325 + iCallback = null;
3.326 + }
3.327 +
3.328 + /// <summary>
3.329 + /// Tells whether a server connection is available.
3.330 + /// </summary>
3.331 + /// <returns>True if a server connection is available. False otherwise.</returns>
3.332 + public bool IsReady()
3.333 + {
3.334 + return (iClient != null && iCallback != null && iClient.IsReady());
3.335 + }
3.336 +
3.337 + /// <summary>
3.338 + /// Check if our server connection is available and attempt reset it if it isn't.
3.339 + /// This is notably dealing with timed out connections.
3.340 + /// </summary>
3.341 + public void CheckConnection()
3.342 + {
3.343 + if (!IsReady() && !resetingConnection)
3.344 + {
3.345 + //Try to reconnect
3.346 + Open();
3.347 +
3.348 + //Avoid stack overflow in case of persisting failure
3.349 + resetingConnection = true;
3.350 +
3.351 + try
3.352 + {
3.353 + //On reconnect there is a bunch of properties we need to reset
3.354 + if (Name != "")
3.355 + {
3.356 + iClient.SetName(Name);
3.357 + }
3.358 +
3.359 + SetLayout(Layout);
3.360 + iClient.SetFields(Fields);
3.361 + }
3.362 + finally
3.363 + {
3.364 + //Make sure our this state does not get out of sync
3.365 + resetingConnection = true;
3.366 + }
3.367 + }
3.368 + }
3.369 +
3.370 + public void SetName(string aClientName)
3.371 + {
3.372 + Name = aClientName;
3.373 + CheckConnection();
3.374 + iClient.SetName(aClientName);
3.375 + }
3.376 +
3.377 +
3.378 + public void SetLayout(TableLayout aLayout)
3.379 + {
3.380 + Layout = aLayout;
3.381 + CheckConnection();
3.382 + iClient.SetLayout(aLayout);
3.383 + }
3.384 +
3.385 + /// <summary>
3.386 + /// Set the specified field.
3.387 + /// </summary>
3.388 + /// <param name="aField"></param>
3.389 + /// <returns>True if the specified field was set client side. False means you need to redefine all your fields using CreateFields.</returns>
3.390 + public bool SetField(DataField aField)
3.391 + {
3.392 + int i = 0;
3.393 + bool fieldFound = false;
3.394 + foreach (DataField field in Fields)
3.395 + {
3.396 + if (field.Index == aField.Index)
3.397 + {
3.398 + //Update our field then
3.399 + Fields[i] = aField;
3.400 + fieldFound = true;
3.401 + break;
3.402 + }
3.403 + i++;
3.404 + }
3.405 +
3.406 + if (!fieldFound)
3.407 + {
3.408 + //Field not found, make to use SetFields with all your fields at least once after setting your layout.
3.409 + return false;
3.410 + }
3.411 +
3.412 + CheckConnection();
3.413 + iClient.SetField(aField);
3.414 + return true;
3.415 + }
3.416 +
3.417 + /// <summary>
3.418 + /// Use this function when updating existing fields.
3.419 + /// </summary>
3.420 + /// <param name="aFields"></param>
3.421 + public bool SetFields(System.Collections.Generic.IList<DataField> aFields)
3.422 + {
3.423 + int fieldFoundCount = 0;
3.424 + foreach (DataField fieldUpdate in aFields)
3.425 + {
3.426 + int i = 0;
3.427 + foreach (DataField existingField in Fields)
3.428 + {
3.429 + if (existingField.Index == fieldUpdate.Index)
3.430 + {
3.431 + //Update our field then
3.432 + Fields[i] = fieldUpdate;
3.433 + fieldFoundCount++;
3.434 + //Move on to the next field
3.435 + break;
3.436 + }
3.437 + i++;
3.438 + }
3.439 + }
3.440 +
3.441 + //
3.442 + if (fieldFoundCount!=aFields.Count)
3.443 + {
3.444 + //Field not found, make sure to use SetFields with all your fields at least once after setting your layout.
3.445 + return false;
3.446 + }
3.447 +
3.448 + CheckConnection();
3.449 + iClient.SetFields(aFields);
3.450 + return true;
3.451 + }
3.452 +
3.453 + /// <summary>
3.454 + /// Use this function when creating your fields.
3.455 + /// </summary>
3.456 + /// <param name="aFields"></param>
3.457 + public void CreateFields(System.Collections.Generic.IList<DataField> aFields)
3.458 + {
3.459 + Fields = aFields;
3.460 + CheckConnection();
3.461 + iClient.SetFields(aFields);
3.462 + }
3.463 +
3.464 + public int ClientCount()
3.465 + {
3.466 + CheckConnection();
3.467 + return iClient.ClientCount();
3.468 + }
3.469 +
3.470 +
3.471
3.472 }
3.473
3.474
3.475 -}
3.476 \ No newline at end of file
3.477 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/GUI/SharpDisplayInterface.cs Thu Jan 01 23:35:49 2015 +0100
4.3 @@ -0,0 +1,204 @@
4.4 +//
4.5 +// Define a public API for both SharpDisplay client and server to use.
4.6 +//
4.7 +
4.8 +using System;
4.9 +using System.Collections.Generic;
4.10 +using System.Linq;
4.11 +using System.Text;
4.12 +using System.Threading.Tasks;
4.13 +using System.ServiceModel;
4.14 +using System.Collections;
4.15 +using System.Drawing;
4.16 +using System.Runtime.Serialization;
4.17 +using System.Windows.Forms;
4.18 +
4.19 +
4.20 +namespace SharpDisplay
4.21 +{
4.22 + /// <summary>
4.23 + /// For client to specify a specific layout.
4.24 + /// </summary>
4.25 + [DataContract]
4.26 + public class TableLayout
4.27 + {
4.28 + public TableLayout()
4.29 + {
4.30 + Columns = new List<ColumnStyle>();
4.31 + Rows = new List<RowStyle>();
4.32 + Cells = new List<DataField>();
4.33 + }
4.34 +
4.35 + public TableLayout(int aColumnCount, int aRowCount)
4.36 + {
4.37 + Columns = new List<ColumnStyle>();
4.38 + Rows = new List<RowStyle>();
4.39 +
4.40 + for (int i = 0; i < aColumnCount; i++)
4.41 + {
4.42 + Columns.Add(new ColumnStyle(SizeType.Percent, 100 / aColumnCount));
4.43 + }
4.44 +
4.45 + for (int i = 0; i < aRowCount; i++)
4.46 + {
4.47 + Rows.Add(new RowStyle(SizeType.Percent, 100 / aRowCount));
4.48 + }
4.49 + }
4.50 +
4.51 + [DataMember]
4.52 + public List<DataField> Cells { get; set; }
4.53 +
4.54 + [DataMember]
4.55 + public List<ColumnStyle> Columns { get; set; }
4.56 +
4.57 + [DataMember]
4.58 + public List<RowStyle> Rows { get; set; }
4.59 + }
4.60 +
4.61 + /// <summary>
4.62 + ///
4.63 + /// </summary>
4.64 + [DataContract]
4.65 + public class DataField
4.66 + {
4.67 + public DataField()
4.68 + {
4.69 + Index = 0;
4.70 + ColumnSpan = 1;
4.71 + RowSpan = 1;
4.72 + //Text
4.73 + Text = "";
4.74 + Alignment = ContentAlignment.MiddleLeft;
4.75 + //Bitmap
4.76 + Bitmap = null;
4.77 + }
4.78 +
4.79 + //Text constructor
4.80 + public DataField(int aIndex, string aText = "", ContentAlignment aAlignment = ContentAlignment.MiddleLeft)
4.81 + {
4.82 + ColumnSpan = 1;
4.83 + RowSpan = 1;
4.84 + Index = aIndex;
4.85 + Text = aText;
4.86 + Alignment = aAlignment;
4.87 + //
4.88 + Bitmap = null;
4.89 + }
4.90 +
4.91 + //Bitmap constructor
4.92 + public DataField(int aIndex, Bitmap aBitmap)
4.93 + {
4.94 + ColumnSpan = 1;
4.95 + RowSpan = 1;
4.96 + Index = aIndex;
4.97 + Bitmap = aBitmap;
4.98 + //Text
4.99 + Text = "";
4.100 + Alignment = ContentAlignment.MiddleLeft;
4.101 + }
4.102 +
4.103 +
4.104 + //Generic layout properties
4.105 + [DataMember]
4.106 + public int Index { get; set; }
4.107 +
4.108 + [DataMember]
4.109 + public int Column { get; set; }
4.110 +
4.111 + [DataMember]
4.112 + public int Row { get; set; }
4.113 +
4.114 + [DataMember]
4.115 + public int ColumnSpan { get; set; }
4.116 +
4.117 + [DataMember]
4.118 + public int RowSpan { get; set; }
4.119 +
4.120 + //Text properties
4.121 + [DataMember]
4.122 + public string Text { get; set; }
4.123 +
4.124 + [DataMember]
4.125 + public ContentAlignment Alignment { get; set; }
4.126 +
4.127 + //Bitmap properties
4.128 + [DataMember]
4.129 + public Bitmap Bitmap { get; set; }
4.130 +
4.131 + //
4.132 + public bool IsBitmap { get { return Bitmap != null; } }
4.133 + //
4.134 + public bool IsText { get { return Bitmap == null; } }
4.135 + //
4.136 + public bool IsSameLayout(DataField aField)
4.137 + {
4.138 + return (aField.ColumnSpan == ColumnSpan && aField.RowSpan == RowSpan);
4.139 + }
4.140 + }
4.141 +
4.142 + /// <summary>
4.143 + /// Define our SharpDisplay service.
4.144 + /// Clients and servers must implement it to communicate with one another.
4.145 + /// Through this service clients can send requests to a server.
4.146 + /// Through this service a server session can receive requests from a client.
4.147 + /// </summary>
4.148 + [ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
4.149 + public interface IService
4.150 + {
4.151 + /// <summary>
4.152 + /// Set the name of this client.
4.153 + /// Name is a convenient way to recognize your client.
4.154 + /// Naming you client is not mandatory.
4.155 + /// In the absence of a name the session ID is often used instead.
4.156 + /// </summary>
4.157 + /// <param name="aClientName"></param>
4.158 + [OperationContract(IsOneWay = true)]
4.159 + void SetName(string aClientName);
4.160 +
4.161 + /// <summary>
4.162 + /// </summary>
4.163 + /// <param name="aLayout"></param>
4.164 + [OperationContract(IsOneWay = true)]
4.165 + void SetLayout(TableLayout aLayout);
4.166 +
4.167 + /// <summary>
4.168 + /// Set the given field on your display.
4.169 + /// Fields are often just lines of text or bitmaps.
4.170 + /// </summary>
4.171 + /// <param name="aTextFieldIndex"></param>
4.172 + [OperationContract(IsOneWay = true)]
4.173 + void SetField(DataField aField);
4.174 +
4.175 + /// <summary>
4.176 + /// Allows a client to set multiple fields at once.
4.177 + /// </summary>
4.178 + /// <param name="aFields"></param>
4.179 + [OperationContract(IsOneWay = true)]
4.180 + void SetFields(System.Collections.Generic.IList<DataField> aFields);
4.181 +
4.182 + /// <summary>
4.183 + /// Provides the number of clients currently connected
4.184 + /// </summary>
4.185 + /// <returns></returns>
4.186 + [OperationContract()]
4.187 + int ClientCount();
4.188 +
4.189 + }
4.190 +
4.191 + /// <summary>
4.192 + /// SharDisplay callback provides a means for a server to notify its clients.
4.193 + /// </summary>
4.194 + public interface ICallback
4.195 + {
4.196 + [OperationContract(IsOneWay = true)]
4.197 + void OnConnected();
4.198 +
4.199 + /// <summary>
4.200 + /// Tell our client to close its connection.
4.201 + /// Notably sent when the server is shutting down.
4.202 + /// </summary>
4.203 + [OperationContract(IsOneWay = true)]
4.204 + void OnCloseOrder();
4.205 + }
4.206 +
4.207 +}
5.1 --- a/OpenHardwareMonitor.csproj Mon Sep 22 21:59:11 2014 +0200
5.2 +++ b/OpenHardwareMonitor.csproj Thu Jan 01 23:35:49 2015 +0100
5.3 @@ -129,6 +129,7 @@
5.4 <Compile Include="GUI\SensorSharpDisplay.cs" />
5.5 <Compile Include="GUI\SharpDisplay.cs" />
5.6 <Compile Include="GUI\SharpDisplayClient.cs" />
5.7 + <Compile Include="GUI\SharpDisplayInterface.cs" />
5.8 <Compile Include="GUI\ShowDesktop.cs" />
5.9 <Compile Include="GUI\SoundGraphDisplay.cs" />
5.10 <Compile Include="GUI\SoundGraphServer.cs" />