Quick and dirty usage of our new SharpDisplay layout for packed mode.
1.1 --- a/GUI/SensorSharpDisplay.cs Sun Sep 21 21:55:36 2014 +0200
1.2 +++ b/GUI/SensorSharpDisplay.cs Mon Sep 22 21:59:11 2014 +0200
1.3 @@ -160,7 +160,7 @@
1.4 case SensorType.Load: format = "{0:F0}%"; break;
1.5 //iMON VFD escape sequence for Celsius
1.6 case SensorType.Temperature: format = "{0:F0}°C"; break;
1.7 - case SensorType.Fan: format = "{0:F0}*"; break; //RPM
1.8 + case SensorType.Fan: format = "{0:F0}R"; break; //RPM
1.9 case SensorType.Flow: format = "{0:F0}L/h"; break;
1.10 case SensorType.Control: format = "{0:F0}%"; break;
1.11 case SensorType.Level: format = "{0:F0}%"; break;
2.1 --- a/GUI/SharpDisplay.cs Sun Sep 21 21:55:36 2014 +0200
2.2 +++ b/GUI/SharpDisplay.cs Mon Sep 22 21:59:11 2014 +0200
2.3 @@ -30,15 +30,18 @@
2.4 private IComputer computer;
2.5 private PersistentSettings settings;
2.6 private UnitManager unitManager;
2.7 - private List<SensorSharpDisplay> list = new List<SensorSharpDisplay>();
2.8 + private List<SensorSharpDisplay> iSensors = new List<SensorSharpDisplay>();
2.9 private global::SharpDisplay.Client iClient;
2.10 TextField iTextFieldTop;
2.11 TextField iTextFieldBottom;
2.12 + TextField iTextFieldTopRight;
2.13 + TextField iTextFieldBottomRight;
2.14 +
2.15 TextField[] iTextFields;
2.16
2.17 private int iNextSensorToDisplay = 0;
2.18 private int iTickCounter = 0;
2.19 -
2.20 + bool iPacked = false;
2.21
2.22 public SharpDisplay(IComputer computer, PersistentSettings settings, UnitManager unitManager)
2.23 {
2.24 @@ -54,6 +57,9 @@
2.25 //
2.26 iTextFieldTop = new TextField(0);
2.27 iTextFieldBottom = new TextField(1);
2.28 + iTextFieldTopRight = new TextField(2, "", ContentAlignment.MiddleRight);
2.29 + iTextFieldBottomRight = new TextField(3, "", ContentAlignment.MiddleRight);
2.30 +
2.31 iTextFields = new TextField[] { iTextFieldTop, iTextFieldBottom };
2.32
2.33 }
2.34 @@ -108,7 +114,7 @@
2.35
2.36 public void Dispose()
2.37 {
2.38 - foreach (SensorSharpDisplay icon in list)
2.39 + foreach (SensorSharpDisplay icon in iSensors)
2.40 icon.Dispose();
2.41
2.42 Quit();
2.43 @@ -125,19 +131,45 @@
2.44 string packedSecondLine = "";
2.45 int count = 0;
2.46
2.47 - string time = DateTime.Now.ToShortTimeString();
2.48 + //string time = DateTime.Now.ToShortTimeString();
2.49 + string time = DateTime.Now.ToLongTimeString();
2.50 +
2.51 + if (iSensors.Count > 0)
2.52 + {
2.53 + if (iPacked != aPacked)
2.54 + {
2.55 + //Remember mode
2.56 + iPacked = aPacked;
2.57 +
2.58 + if (iPacked)
2.59 + {
2.60 + //We just switched to packed mode
2.61 + //Make sure our layout is proper
2.62 + TableLayout layout = new TableLayout(2, 2);
2.63 + iClient.SetLayout(layout);
2.64 + }
2.65 + else
2.66 + {
2.67 + //Non packed mode
2.68 + TableLayout layout = new TableLayout(1, 2);
2.69 + iClient.SetLayout(layout);
2.70 + }
2.71 + }
2.72 + }
2.73 +
2.74
2.75 //Update all sensors from our front view
2.76 - foreach (SensorSharpDisplay sensor in list)
2.77 + foreach (SensorSharpDisplay sensor in iSensors)
2.78 {
2.79 count++;
2.80 sensor.Update();
2.81
2.82 if (aDisplayTime && count == 1)
2.83 {
2.84 - //First slot is take by time display
2.85 + //First slot is taken by time display
2.86 count++;
2.87 - packedFirstLine = time + " ";
2.88 + iTextFieldTop.Text = time;
2.89 + iClient.SetText(iTextFieldTop);
2.90 }
2.91
2.92 if (aPacked)
2.93 @@ -147,39 +179,33 @@
2.94 packedText = sensor.iFirstLine.Substring(0, 3) + ":" + sensor.iSecondLine;
2.95 if (count == 1)
2.96 {
2.97 - packedFirstLine = packedText + " "; //Minimum one space to separate sensors on the same line
2.98 + iTextFieldTop.Text = packedText;
2.99 + iClient.SetText(iTextFieldTop);
2.100 }
2.101 else if (count == 2)
2.102 {
2.103 - //Add enough spaces to align to right hand side
2.104 - while (packedFirstLine.Length + packedText.Length < KMaxCharacterPerLine)
2.105 - {
2.106 - packedFirstLine += " ";
2.107 - }
2.108 - packedFirstLine += packedText;
2.109 + iTextFieldBottom.Text = packedText;
2.110 + iClient.SetText(iTextFieldBottom);
2.111 }
2.112 else if (count == 3)
2.113 {
2.114 - packedSecondLine = packedText + " "; //Minimum one space to separate sensors on the same line
2.115 + iTextFieldTopRight.Text = packedText;
2.116 + iClient.SetText(iTextFieldTopRight);
2.117 }
2.118 else if (count == 4)
2.119 {
2.120 - //Add enough spaces to align to right hand side
2.121 - while (packedSecondLine.Length + packedText.Length < KMaxCharacterPerLine)
2.122 - {
2.123 - packedSecondLine += " ";
2.124 - }
2.125 - packedSecondLine += packedText;
2.126 + iTextFieldBottomRight.Text = packedText;
2.127 + iClient.SetText(iTextFieldBottomRight);
2.128 }
2.129 }
2.130 - //SetText(sensor.iFirstLine, sensor.iSecondLine);
2.131 }
2.132
2.133 //Alternate between sensors
2.134 - if (list.Count > 0)
2.135 + if (iSensors.Count > 0)
2.136 {
2.137 if (aPacked)
2.138 {
2.139 + //Review that stuff cause as it is it's probably useless
2.140 //string packedLine = "";
2.141 iTickCounter++;
2.142 if (iTickCounter == KNumberOfTickBeforeSwitch) //Move to the next sensor only every so many tick
2.143 @@ -194,16 +220,10 @@
2.144 iNextSensorToDisplay = 1;
2.145 }
2.146 }
2.147 -
2.148 - //TODO: Do something like that to cycle lines if ever we want to
2.149 - //SetText(time, (iNextSensorToDisplay == 1 && packedSecondLine.Length > 0 ? packedSecondLine : packedFirstLine));
2.150 -
2.151 - //Display packed sensors on our FrontView display
2.152 - SetText(packedFirstLine, packedSecondLine);
2.153 }
2.154 else
2.155 {
2.156 - string secondLine = list[iNextSensorToDisplay].iSecondLine;
2.157 + string secondLine = iSensors[iNextSensorToDisplay].iSecondLine;
2.158 if (aDisplayTime)
2.159 {
2.160 //Add enough spaces
2.161 @@ -214,7 +234,7 @@
2.162 secondLine += time;
2.163 }
2.164 //Display current sensor on our FrontView display
2.165 - SetText(list[iNextSensorToDisplay].iFirstLine, secondLine);
2.166 + SetText(iSensors[iNextSensorToDisplay].iFirstLine, secondLine);
2.167 iTickCounter++;
2.168 if (iTickCounter == KNumberOfTickBeforeSwitch) //Move to the next sensor only every so many tick
2.169 {
2.170 @@ -224,7 +244,7 @@
2.171 }
2.172 }
2.173
2.174 - if (iNextSensorToDisplay == list.Count)
2.175 + if (iNextSensorToDisplay == iSensors.Count)
2.176 {
2.177 //Go back to first sensor
2.178 iNextSensorToDisplay = 0;
2.179 @@ -235,7 +255,7 @@
2.180
2.181 public bool Contains(ISensor sensor)
2.182 {
2.183 - foreach (SensorSharpDisplay icon in list)
2.184 + foreach (SensorSharpDisplay icon in iSensors)
2.185 if (icon.Sensor == sensor)
2.186 return true;
2.187 return false;
2.188 @@ -250,11 +270,11 @@
2.189 else
2.190 {
2.191 //SL:
2.192 - list.Add(new SensorSharpDisplay(this, sensor, balloonTip, settings, unitManager));
2.193 + iSensors.Add(new SensorSharpDisplay(this, sensor, balloonTip, settings, unitManager));
2.194 //UpdateMainIconVisibilty();
2.195 settings.SetValue(new Identifier(sensor.Identifier, "SharpDisplay").ToString(), true);
2.196 iNextSensorToDisplay = 0;
2.197 - if (list.Count == 1)
2.198 + if (iSensors.Count == 1)
2.199 {
2.200 //Just added first sensor in FrontView, unable FrontView plug-in mode
2.201 Init();
2.202 @@ -267,7 +287,7 @@
2.203 {
2.204 Remove(sensor, true);
2.205 iNextSensorToDisplay = 0;
2.206 - if (list.Count == 0)
2.207 + if (iSensors.Count == 0)
2.208 {
2.209 //No sensor to display in FrontView, just disable FrontView plug-in mode
2.210 Uninit();
2.211 @@ -283,12 +303,12 @@
2.212 new Identifier(sensor.Identifier, "SharpDisplay").ToString());
2.213 }
2.214 SensorSharpDisplay instance = null;
2.215 - foreach (SensorSharpDisplay icon in list)
2.216 + foreach (SensorSharpDisplay icon in iSensors)
2.217 if (icon.Sensor == sensor)
2.218 instance = icon;
2.219 if (instance != null)
2.220 {
2.221 - list.Remove(instance);
2.222 + iSensors.Remove(instance);
2.223 //UpdateMainIconVisibilty();
2.224 instance.Dispose();
2.225 }
3.1 --- a/GUI/SharpDisplayClient.cs Sun Sep 21 21:55:36 2014 +0200
3.2 +++ b/GUI/SharpDisplayClient.cs Mon Sep 22 21:59:11 2014 +0200
3.3 @@ -26,11 +26,75 @@
3.4
3.5 namespace SharpDisplay
3.6 {
3.7 - //That contract need to be in the same namespace than the original assembly
3.8 - //otherwise our parameter won't make to the server.
3.9 - //See: http://stackoverflow.com/questions/14956377/passing-an-object-using-datacontract-in-wcf/25455292#25455292
3.10 +
3.11 +
3.12 +
3.13 + /// <summary>
3.14 + /// For client to specify a specific layout.
3.15 + /// </summary>
3.16 [DataContract]
3.17 - public class TextField
3.18 + public class TableLayout
3.19 + {
3.20 + public TableLayout()
3.21 + {
3.22 + Columns = new List<ColumnStyle>();
3.23 + Rows = new List<RowStyle>();
3.24 + Cells = new List<DataField>();
3.25 + }
3.26 +
3.27 + public TableLayout(int aColumnCount, int aRowCount)
3.28 + {
3.29 + Columns = new List<ColumnStyle>();
3.30 + Rows = new List<RowStyle>();
3.31 +
3.32 + for (int i = 0; i < aColumnCount; i++)
3.33 + {
3.34 + Columns.Add(new ColumnStyle(SizeType.Percent, 100 / aColumnCount));
3.35 + }
3.36 +
3.37 + for (int i = 0; i < aRowCount; i++)
3.38 + {
3.39 + Rows.Add(new RowStyle(SizeType.Percent, 100 / aRowCount));
3.40 + }
3.41 + }
3.42 +
3.43 + [DataMember]
3.44 + public List<DataField> Cells { get; set; }
3.45 +
3.46 + [DataMember]
3.47 + public List<ColumnStyle> Columns { get; set; }
3.48 +
3.49 + [DataMember]
3.50 + public List<RowStyle> Rows { get; set; }
3.51 +
3.52 + }
3.53 +
3.54 + /// <summary>
3.55 + ///
3.56 + /// </summary>
3.57 + [DataContract]
3.58 + public class DataField
3.59 + {
3.60 + [DataMember]
3.61 + public int Column { get; set; }
3.62 +
3.63 + [DataMember]
3.64 + public int Row { get; set; }
3.65 +
3.66 + [DataMember]
3.67 + public int ColumnSpan { get; set; }
3.68 +
3.69 + [DataMember]
3.70 + public int RowSpan { get; set; }
3.71 +
3.72 + }
3.73 +
3.74 +
3.75 + /// <summary>
3.76 + /// TextField can be send to our server to be displayed on the screen.
3.77 + /// </summary>
3.78 + [DataContract]
3.79 + public class TextField : DataField
3.80 {
3.81 public TextField()
3.82 {
3.83 @@ -56,7 +120,12 @@
3.84 public ContentAlignment Alignment { get; set; }
3.85 }
3.86
3.87 -
3.88 + /// <summary>
3.89 + /// Define our SharpDisplay service.
3.90 + /// Clients and servers must implement it to communicate with one another.
3.91 + /// Through this service clients can send requests to a server.
3.92 + /// Through this service a server session can receive requests from a client.
3.93 + /// </summary>
3.94 [ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
3.95 public interface IService
3.96 {
3.97 @@ -70,6 +139,13 @@
3.98 [OperationContract(IsOneWay = true)]
3.99 void SetName(string aClientName);
3.100
3.101 +
3.102 + /// <summary>
3.103 + /// </summary>
3.104 + /// <param name="aLayout"></param>
3.105 + [OperationContract(IsOneWay = true)]
3.106 + void SetLayout(TableLayout aLayout);
3.107 +
3.108 /// <summary>
3.109 /// Put the given text in the given field on your display.
3.110 /// Fields are often just lines of text.
3.111 @@ -94,7 +170,9 @@
3.112
3.113 }
3.114
3.115 -
3.116 + /// <summary>
3.117 + /// SharDisplay callback provides a means for a server to notify its clients.
3.118 + /// </summary>
3.119 public interface ICallback
3.120 {
3.121 [OperationContract(IsOneWay = true)]
3.122 @@ -107,6 +185,9 @@
3.123 [OperationContract(IsOneWay = true)]
3.124 void OnCloseOrder();
3.125 }
3.126 +
3.127 +
3.128 +
3.129 }
3.130
3.131
3.132 @@ -133,6 +214,11 @@
3.133 Channel.SetName(aClientName);
3.134 }
3.135
3.136 + public void SetLayout(TableLayout aLayout)
3.137 + {
3.138 + Channel.SetLayout(aLayout);
3.139 + }
3.140 +
3.141 public void SetText(TextField aTextField)
3.142 {
3.143 Channel.SetText(aTextField);