GUI/SharpDisplayClient.cs
branchMiniDisplay
changeset 447 af40a92d480d
parent 446 0cb7b9f6a6f8
     1.1 --- a/GUI/SharpDisplayClient.cs	Mon Sep 22 21:59:11 2014 +0200
     1.2 +++ b/GUI/SharpDisplayClient.cs	Thu Jan 01 23:35:49 2015 +0100
     1.3 @@ -1,207 +1,64 @@
     1.4 -/*
     1.5 - 
     1.6 -  This Source Code Form is subject to the terms of the Mozilla Public
     1.7 -  License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 -  file, You can obtain one at http://mozilla.org/MPL/2.0/.
     1.9 - 
    1.10 -  Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
    1.11 -	
    1.12 -*/
    1.13 -
    1.14 +
    1.15  using System;
    1.16  using System.Collections.Generic;
    1.17 -using System.Drawing;
    1.18 +using System.Linq;
    1.19  using System.Text;
    1.20 -using System.Diagnostics;
    1.21 +using System.Threading.Tasks;
    1.22  using System.Windows.Forms;
    1.23 -using System.Windows;
    1.24 -using OpenHardwareMonitor.Hardware;
    1.25 -using OpenHardwareMonitor.Utilities;
    1.26 -using System.Runtime.InteropServices;
    1.27 -using UacHelpers;
    1.28 -//
    1.29 +using SharpDisplay;
    1.30  using System.ServiceModel;
    1.31 -using System.Runtime.Serialization;
    1.32 -using SharpDisplay;
    1.33 +using System.ServiceModel.Channels;
    1.34 +
    1.35  
    1.36  namespace SharpDisplay
    1.37  {
    1.38 -
    1.39 -
    1.40 -
    1.41 -    /// <summary>
    1.42 -    /// For client to specify a specific layout.
    1.43 -    /// </summary>
    1.44 -    [DataContract]
    1.45 -    public class TableLayout
    1.46 -    {
    1.47 -        public TableLayout()
    1.48 -        {
    1.49 -            Columns = new List<ColumnStyle>();
    1.50 -            Rows = new List<RowStyle>();
    1.51 -            Cells = new List<DataField>();
    1.52 -        }
    1.53 -
    1.54 -        public TableLayout(int aColumnCount, int aRowCount)
    1.55 -        {
    1.56 -            Columns = new List<ColumnStyle>();
    1.57 -            Rows = new List<RowStyle>();
    1.58 -
    1.59 -            for (int i = 0; i < aColumnCount; i++)
    1.60 -            {
    1.61 -                Columns.Add(new ColumnStyle(SizeType.Percent, 100 / aColumnCount));
    1.62 -            }
    1.63 -
    1.64 -            for (int i = 0; i < aRowCount; i++)
    1.65 -            {
    1.66 -                Rows.Add(new RowStyle(SizeType.Percent, 100 / aRowCount));
    1.67 -            }
    1.68 -        }
    1.69 -
    1.70 -        [DataMember]
    1.71 -        public List<DataField> Cells { get; set; }
    1.72 -
    1.73 -        [DataMember]
    1.74 -        public List<ColumnStyle> Columns { get; set; }
    1.75 -
    1.76 -        [DataMember]
    1.77 -        public List<RowStyle> Rows { get; set; }
    1.78 -
    1.79 -    }
    1.80 -
    1.81      /// <summary>
    1.82      ///
    1.83      /// </summary>
    1.84 -    [DataContract]
    1.85 -    public class DataField
    1.86 +    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    1.87 +    public class Callback : ICallback, IDisposable
    1.88      {
    1.89 -        [DataMember]
    1.90 -        public int Column { get; set; }
    1.91 +		private DisplayClient DisplayClient { get; set; }
    1.92  
    1.93 -        [DataMember]
    1.94 -        public int Row { get; set; }
    1.95 +		public Callback(DisplayClient aClient)
    1.96 +        {
    1.97 +            DisplayClient = aClient;
    1.98 +        }
    1.99  
   1.100 -        [DataMember]
   1.101 -        public int ColumnSpan { get; set; }
   1.102 +        public void OnConnected()
   1.103 +        {
   1.104 +            //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
   1.105 +            //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
   1.106  
   1.107 -        [DataMember]
   1.108 -        public int RowSpan { get; set; }
   1.109 +            MessageBox.Show("OnConnected()", "Client");
   1.110 +        }
   1.111  
   1.112 +
   1.113 +        public void OnCloseOrder()
   1.114 +        {
   1.115 +			DisplayClient.Close();
   1.116 +            //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
   1.117 +            //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
   1.118 +
   1.119 +            //MessageBox.Show("OnServerClosing()", "Client");
   1.120 +            //MainForm.CloseConnectionThreadSafe();
   1.121 +            //MainForm.CloseThreadSafe();
   1.122 +        }
   1.123 +
   1.124 +        //From IDisposable
   1.125 +        public void Dispose()
   1.126 +        {
   1.127 +
   1.128 +        }
   1.129      }
   1.130  
   1.131  
   1.132      /// <summary>
   1.133 -    /// TextField can be send to our server to be displayed on the screen.
   1.134 -    /// </summary>
   1.135 -    [DataContract]
   1.136 -    public class TextField : DataField
   1.137 -    {
   1.138 -        public TextField()
   1.139 -        {
   1.140 -            Index = 0;
   1.141 -            Text = "";
   1.142 -            Alignment = ContentAlignment.MiddleLeft;
   1.143 -        }
   1.144 -
   1.145 -        public TextField(int aIndex, string aText = "", ContentAlignment aAlignment = ContentAlignment.MiddleLeft)
   1.146 -        {
   1.147 -            Index = aIndex;
   1.148 -            Text = aText;
   1.149 -            Alignment = aAlignment;
   1.150 -        }
   1.151 -
   1.152 -        [DataMember]
   1.153 -        public int Index { get; set; }
   1.154 -
   1.155 -        [DataMember]
   1.156 -        public string Text { get; set; }
   1.157 -
   1.158 -        [DataMember]
   1.159 -        public ContentAlignment Alignment { get; set; }
   1.160 -    }
   1.161 -
   1.162 -    /// <summary>
   1.163 -    /// Define our SharpDisplay service.
   1.164 -    /// Clients and servers must implement it to communicate with one another.
   1.165 -    /// Through this service clients can send requests to a server.
   1.166 -    /// Through this service a server session can receive requests from a client.
   1.167 -    /// </summary>
   1.168 -    [ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
   1.169 -    public interface IService
   1.170 -    {
   1.171 -        /// <summary>
   1.172 -        /// Set the name of this client.
   1.173 -        /// Name is a convenient way to recognize your client.
   1.174 -        /// Naming you client is not mandatory.
   1.175 -        /// In the absence of a name the session ID is often used instead.
   1.176 -        /// </summary>
   1.177 -        /// <param name="aClientName"></param>
   1.178 -        [OperationContract(IsOneWay = true)]
   1.179 -        void SetName(string aClientName);
   1.180 -
   1.181 -
   1.182 -        /// <summary>
   1.183 -        /// </summary>
   1.184 -        /// <param name="aLayout"></param>
   1.185 -        [OperationContract(IsOneWay = true)]
   1.186 -        void SetLayout(TableLayout aLayout);
   1.187 -
   1.188 -        /// <summary>
   1.189 -        /// Put the given text in the given field on your display.
   1.190 -        /// Fields are often just lines of text.
   1.191 -        /// </summary>
   1.192 -        /// <param name="aTextFieldIndex"></param>
   1.193 -        [OperationContract(IsOneWay = true)]
   1.194 -        void SetText(TextField aTextField);
   1.195 -
   1.196 -        /// <summary>
   1.197 -        /// Allows a client to set multiple text fields at once.
   1.198 -        /// </summary>
   1.199 -        /// <param name="aTexts"></param>
   1.200 -        [OperationContract(IsOneWay = true)]
   1.201 -        void SetTexts(System.Collections.Generic.IList<TextField> aTextFields);
   1.202 -
   1.203 -        /// <summary>
   1.204 -        /// Provides the number of clients currently connected
   1.205 -        /// </summary>
   1.206 -        /// <returns></returns>
   1.207 -        [OperationContract()]
   1.208 -        int ClientCount();
   1.209 -
   1.210 -    }
   1.211 -
   1.212 -    /// <summary>
   1.213 -    /// SharDisplay callback provides a means for a server to notify its clients.
   1.214 -    /// </summary>
   1.215 -    public interface ICallback
   1.216 -    {
   1.217 -        [OperationContract(IsOneWay = true)]
   1.218 -        void OnConnected();
   1.219 -
   1.220 -        /// <summary>
   1.221 -        /// Tell our client to close its connection.
   1.222 -        /// Notably sent when the server is shutting down.
   1.223 -        /// </summary>
   1.224 -        [OperationContract(IsOneWay = true)]
   1.225 -        void OnCloseOrder();
   1.226 -    }
   1.227 -
   1.228 -
   1.229 -
   1.230 -}
   1.231 -
   1.232 -
   1.233 -
   1.234 -namespace SharpDisplay
   1.235 -{
   1.236 -
   1.237 -    /// <summary>
   1.238      ///
   1.239      /// </summary>
   1.240      [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
   1.241      public class Client : DuplexClientBase<IService>
   1.242      {
   1.243 -        public string Name { get; set; }
   1.244          public string SessionId { get { return InnerChannel.SessionId; } }
   1.245  
   1.246          public Client(ICallback aCallback)
   1.247 @@ -210,7 +67,6 @@
   1.248  
   1.249          public void SetName(string aClientName)
   1.250          {
   1.251 -            Name = aClientName;
   1.252              Channel.SetName(aClientName);
   1.253          }
   1.254  
   1.255 @@ -219,14 +75,14 @@
   1.256              Channel.SetLayout(aLayout);
   1.257          }
   1.258  
   1.259 -        public void SetText(TextField aTextField)
   1.260 +        public void SetField(DataField aField)
   1.261          {
   1.262 -            Channel.SetText(aTextField);
   1.263 +            Channel.SetField(aField);
   1.264          }
   1.265  
   1.266 -        public void SetTexts(System.Collections.Generic.IList<TextField> aTextFields)
   1.267 +        public void SetFields(System.Collections.Generic.IList<DataField> aFields)
   1.268          {
   1.269 -            Channel.SetTexts(aTextFields);
   1.270 +            Channel.SetFields(aFields);
   1.271          }
   1.272  
   1.273          public int ClientCount()
   1.274 @@ -236,10 +92,200 @@
   1.275  
   1.276          public bool IsReady()
   1.277          {
   1.278 -            return State == CommunicationState.Opened;
   1.279 +            return State == CommunicationState.Opened || State == CommunicationState.Created;
   1.280          }
   1.281 +    }
   1.282 +
   1.283 +
   1.284 +    /// <summary>
   1.285 +    /// Handle connection with our Sharp Display Server.
   1.286 +    /// If the connection is faulted it will attempt to restart it.
   1.287 +    /// </summary>
   1.288 +    public class DisplayClient
   1.289 +    {
   1.290 +        private Client iClient;
   1.291 +        private Callback iCallback;
   1.292 +        private bool resetingConnection = false;
   1.293 +
   1.294 +        //private MainForm MainForm { get; set; }
   1.295 +        public string SessionId { get { return iClient.SessionId; } }
   1.296 +        public string Name { get; private set; }
   1.297 +        private TableLayout Layout { get; set; }
   1.298 +        private System.Collections.Generic.IList<DataField> Fields { get; set; }
   1.299 +
   1.300 +
   1.301 +        public DisplayClient(/*MainForm aMainForm*/)
   1.302 +        {
   1.303 +            //MainForm = aMainForm;
   1.304 +            Name = "";
   1.305 +            Fields = new DataField[]{};
   1.306 +        }
   1.307 +
   1.308 +        /// <summary>
   1.309 +        /// Initialize our server connection.
   1.310 +        /// </summary>
   1.311 +        public void Open()
   1.312 +        {
   1.313 +            iCallback = new Callback(this);
   1.314 +            iClient = new Client(iCallback);
   1.315 +        }
   1.316 +
   1.317 +        /// <summary>
   1.318 +        /// Terminate our server connection.
   1.319 +        /// </summary>
   1.320 +        public void Close()
   1.321 +        {
   1.322 +            iClient.Close();
   1.323 +            iClient = null;
   1.324 +            iCallback.Dispose();
   1.325 +            iCallback = null;
   1.326 +        }
   1.327 +
   1.328 +        /// <summary>
   1.329 +        /// Tells whether a server connection is available.
   1.330 +        /// </summary>
   1.331 +        /// <returns>True if a server connection is available. False otherwise.</returns>
   1.332 +        public bool IsReady()
   1.333 +        {
   1.334 +            return (iClient != null && iCallback != null && iClient.IsReady());
   1.335 +        }
   1.336 +
   1.337 +        /// <summary>
   1.338 +        /// Check if our server connection is available and attempt reset it if it isn't.
   1.339 +        /// This is notably dealing with timed out connections.
   1.340 +        /// </summary>
   1.341 +        public void CheckConnection()
   1.342 +        {
   1.343 +            if (!IsReady() && !resetingConnection)
   1.344 +            {
   1.345 +                //Try to reconnect
   1.346 +                Open();
   1.347 +
   1.348 +                //Avoid stack overflow in case of persisting failure
   1.349 +                resetingConnection = true;
   1.350 +
   1.351 +                try
   1.352 +                {
   1.353 +                    //On reconnect there is a bunch of properties we need to reset
   1.354 +                    if (Name != "")
   1.355 +                    {
   1.356 +                        iClient.SetName(Name);
   1.357 +                    }
   1.358 +
   1.359 +                    SetLayout(Layout);
   1.360 +                    iClient.SetFields(Fields);
   1.361 +                }
   1.362 +                finally
   1.363 +                {
   1.364 +                    //Make sure our this state does not get out of sync
   1.365 +                    resetingConnection = true;
   1.366 +                }
   1.367 +            }
   1.368 +        }
   1.369 +
   1.370 +        public void SetName(string aClientName)
   1.371 +        {
   1.372 +            Name = aClientName;
   1.373 +            CheckConnection();
   1.374 +            iClient.SetName(aClientName);
   1.375 +        }
   1.376 +
   1.377 +
   1.378 +        public void SetLayout(TableLayout aLayout)
   1.379 +        {
   1.380 +            Layout = aLayout;
   1.381 +            CheckConnection();
   1.382 +            iClient.SetLayout(aLayout);
   1.383 +        }
   1.384 +
   1.385 +        /// <summary>
   1.386 +        /// Set the specified field.
   1.387 +        /// </summary>
   1.388 +        /// <param name="aField"></param>
   1.389 +        /// <returns>True if the specified field was set client side. False means you need to redefine all your fields using CreateFields.</returns>
   1.390 +        public bool SetField(DataField aField)
   1.391 +        {
   1.392 +            int i = 0;
   1.393 +            bool fieldFound = false;
   1.394 +            foreach (DataField field in Fields)
   1.395 +            {
   1.396 +                if (field.Index == aField.Index)
   1.397 +                {
   1.398 +                    //Update our field then
   1.399 +                    Fields[i] = aField;
   1.400 +                    fieldFound = true;
   1.401 +                    break;
   1.402 +                }
   1.403 +                i++;
   1.404 +            }
   1.405 +
   1.406 +            if (!fieldFound)
   1.407 +            {
   1.408 +                //Field not found, make to use SetFields with all your fields at least once after setting your layout.
   1.409 +                return false;
   1.410 +            }
   1.411 +
   1.412 +            CheckConnection();
   1.413 +            iClient.SetField(aField);
   1.414 +            return true;
   1.415 +        }
   1.416 +
   1.417 +        /// <summary>
   1.418 +        /// Use this function when updating existing fields.
   1.419 +        /// </summary>
   1.420 +        /// <param name="aFields"></param>
   1.421 +        public bool SetFields(System.Collections.Generic.IList<DataField> aFields)
   1.422 +        {
   1.423 +            int fieldFoundCount = 0;
   1.424 +            foreach (DataField fieldUpdate in aFields)
   1.425 +            {
   1.426 +                int i = 0;
   1.427 +                foreach (DataField existingField in Fields)
   1.428 +                {
   1.429 +                    if (existingField.Index == fieldUpdate.Index)
   1.430 +                    {
   1.431 +                        //Update our field then
   1.432 +                        Fields[i] = fieldUpdate;
   1.433 +                        fieldFoundCount++;
   1.434 +                        //Move on to the next field
   1.435 +                        break;
   1.436 +                    }
   1.437 +                    i++;
   1.438 +                }
   1.439 +            }
   1.440 +
   1.441 +            //
   1.442 +            if (fieldFoundCount!=aFields.Count)
   1.443 +            {
   1.444 +                //Field not found, make sure to use SetFields with all your fields at least once after setting your layout.
   1.445 +                return false;
   1.446 +            }
   1.447 +
   1.448 +            CheckConnection();
   1.449 +            iClient.SetFields(aFields);
   1.450 +            return true;
   1.451 +        }
   1.452 +
   1.453 +        /// <summary>
   1.454 +        /// Use this function when creating your fields.
   1.455 +        /// </summary>
   1.456 +        /// <param name="aFields"></param>
   1.457 +        public void CreateFields(System.Collections.Generic.IList<DataField> aFields)
   1.458 +        {
   1.459 +            Fields = aFields;
   1.460 +            CheckConnection();
   1.461 +            iClient.SetFields(aFields);
   1.462 +        }
   1.463 +
   1.464 +        public int ClientCount()
   1.465 +        {
   1.466 +            CheckConnection();
   1.467 +            return iClient.ClientCount();
   1.468 +        }
   1.469 +
   1.470 +
   1.471  
   1.472      }
   1.473  
   1.474  
   1.475 -}
   1.476 \ No newline at end of file
   1.477 +}