diff --git a/GUI/MainForm.Designer.cs b/GUI/MainForm.Designer.cs index a78fc9f..f5c05b8 100644 --- a/GUI/MainForm.Designer.cs +++ b/GUI/MainForm.Designer.cs @@ -102,10 +102,6 @@ namespace OpenHardwareMonitor.GUI { this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.splitContainer = new System.Windows.Forms.SplitContainer(); this.plotPanel = new OpenHardwareMonitor.GUI.PlotPanel(); - this.notifyContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); - this.hideShowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator(); - this.exitToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem(); this.sensorContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.saveFileDialog = new System.Windows.Forms.SaveFileDialog(); this.timer = new System.Windows.Forms.Timer(this.components); @@ -113,7 +109,6 @@ namespace OpenHardwareMonitor.GUI { this.splitContainer.Panel1.SuspendLayout(); this.splitContainer.Panel2.SuspendLayout(); this.splitContainer.SuspendLayout(); - this.notifyContextMenuStrip.SuspendLayout(); this.SuspendLayout(); // // treeView @@ -269,7 +264,7 @@ namespace OpenHardwareMonitor.GUI { this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; this.exitToolStripMenuItem.Size = new System.Drawing.Size(145, 22); this.exitToolStripMenuItem.Text = "Exit"; - this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); + this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitClick); // // viewToolStripMenuItem // @@ -393,9 +388,9 @@ namespace OpenHardwareMonitor.GUI { this.startupMenuItem.Text = "Run On Windows Startup"; this.startupMenuItem.CheckedChanged += new System.EventHandler(this.runOnWindowsStartupToolStripMenuItem_CheckedChanged); // - // toolStripMenuItem3 + // separatorMenuItem // - this.separatorMenuItem.Name = "toolStripMenuItem3"; + this.separatorMenuItem.Name = "separatorMenuItem"; this.separatorMenuItem.Size = new System.Drawing.Size(204, 6); // // temperatureUnitsToolStripMenuItem @@ -410,14 +405,14 @@ namespace OpenHardwareMonitor.GUI { // celciusToolStripMenuItem // this.celciusToolStripMenuItem.Name = "celciusToolStripMenuItem"; - this.celciusToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.celciusToolStripMenuItem.Size = new System.Drawing.Size(130, 22); this.celciusToolStripMenuItem.Text = "Celcius"; this.celciusToolStripMenuItem.Click += new System.EventHandler(this.celciusToolStripMenuItem_Click); // // fahrenheitToolStripMenuItem // this.fahrenheitToolStripMenuItem.Name = "fahrenheitToolStripMenuItem"; - this.fahrenheitToolStripMenuItem.Size = new System.Drawing.Size(152, 22); + this.fahrenheitToolStripMenuItem.Size = new System.Drawing.Size(130, 22); this.fahrenheitToolStripMenuItem.Text = "Fahrenheit"; this.fahrenheitToolStripMenuItem.Click += new System.EventHandler(this.fahrenheitToolStripMenuItem_Click); // @@ -478,38 +473,10 @@ namespace OpenHardwareMonitor.GUI { this.plotPanel.Size = new System.Drawing.Size(410, 171); this.plotPanel.TabIndex = 0; // - // notifyContextMenuStrip - // - this.notifyContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.hideShowToolStripMenuItem, - this.toolStripMenuItem2, - this.exitToolStripMenuItem1}); - this.notifyContextMenuStrip.Name = "notifyContextMenuStrip"; - this.notifyContextMenuStrip.Size = new System.Drawing.Size(134, 54); - // - // hideShowToolStripMenuItem - // - this.hideShowToolStripMenuItem.Name = "hideShowToolStripMenuItem"; - this.hideShowToolStripMenuItem.Size = new System.Drawing.Size(133, 22); - this.hideShowToolStripMenuItem.Text = "Hide/Show"; - this.hideShowToolStripMenuItem.Click += new System.EventHandler(this.hideShowClick); - // - // toolStripMenuItem2 - // - this.toolStripMenuItem2.Name = "toolStripMenuItem2"; - this.toolStripMenuItem2.Size = new System.Drawing.Size(130, 6); - // - // exitToolStripMenuItem1 - // - this.exitToolStripMenuItem1.Name = "exitToolStripMenuItem1"; - this.exitToolStripMenuItem1.Size = new System.Drawing.Size(133, 22); - this.exitToolStripMenuItem1.Text = "Exit"; - this.exitToolStripMenuItem1.Click += new System.EventHandler(this.exitToolStripMenuItem_Click); - // // sensorContextMenuStrip // this.sensorContextMenuStrip.Name = "sensorContextMenuStrip"; - this.sensorContextMenuStrip.Size = new System.Drawing.Size(61, 4); + this.sensorContextMenuStrip.Size = new System.Drawing.Size(153, 26); // // saveFileDialog // @@ -542,7 +509,6 @@ namespace OpenHardwareMonitor.GUI { this.splitContainer.Panel1.ResumeLayout(false); this.splitContainer.Panel2.ResumeLayout(false); this.splitContainer.ResumeLayout(false); - this.notifyContextMenuStrip.ResumeLayout(false); this.ResumeLayout(false); this.PerformLayout(); @@ -575,10 +541,6 @@ namespace OpenHardwareMonitor.GUI { private System.Windows.Forms.ToolStripMenuItem saveReportToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem optionsToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem hddMenuItem; - private System.Windows.Forms.ContextMenuStrip notifyContextMenuStrip; - private System.Windows.Forms.ToolStripMenuItem hideShowToolStripMenuItem; - private System.Windows.Forms.ToolStripSeparator toolStripMenuItem2; - private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem1; private System.Windows.Forms.ToolStripMenuItem minTrayMenuItem; private System.Windows.Forms.ToolStripSeparator separatorMenuItem; private System.Windows.Forms.ContextMenuStrip sensorContextMenuStrip; diff --git a/GUI/MainForm.cs b/GUI/MainForm.cs index 668591c..64f2545 100644 --- a/GUI/MainForm.cs +++ b/GUI/MainForm.cs @@ -57,8 +57,7 @@ namespace OpenHardwareMonitor.GUI { private IDictionary sensorPlotColors = new Dictionary(); private Color[] plotColorPalette; - private SensorSystemTray sensorSystemTray; - private NotifyIcon notifyIcon; + private SystemTray systemTray; private StartupManager startupManager = new StartupManager(); private UpdateVisitor updateVisitor = new UpdateVisitor(); @@ -68,21 +67,13 @@ namespace OpenHardwareMonitor.GUI { treeView.Font = SystemFonts.MessageBoxFont; plotPanel.Font = SystemFonts.MessageBoxFont; - nodeCheckBox.IsVisibleValueNeeded += - new EventHandler( - nodeCheckBox_IsVisibleValueNeeded); - nodeCheckBox.CheckStateChanged += - new EventHandler(UpdatePlotSelection); - nodeTextBoxText.DrawText += - new EventHandler(nodeTextBoxText_DrawText); - nodeTextBoxValue.DrawText += - new EventHandler(nodeTextBoxText_DrawText); - nodeTextBoxMin.DrawText += - new EventHandler(nodeTextBoxText_DrawText); - nodeTextBoxMax.DrawText += - new EventHandler(nodeTextBoxText_DrawText); - nodeTextBoxLimit.DrawText += - new EventHandler(nodeTextBoxLimit_DrawText); + nodeCheckBox.IsVisibleValueNeeded += nodeCheckBox_IsVisibleValueNeeded; + nodeCheckBox.CheckStateChanged += UpdatePlotSelection; + nodeTextBoxText.DrawText += nodeTextBoxText_DrawText; + nodeTextBoxValue.DrawText += nodeTextBoxText_DrawText; + nodeTextBoxMin.DrawText += nodeTextBoxText_DrawText; + nodeTextBoxMax.DrawText += nodeTextBoxText_DrawText; + nodeTextBoxLimit.DrawText += nodeTextBoxLimit_DrawText; if (Utilities.Config.Contains("mainForm.Location.X")) { int x = Utilities.Config.Get("mainForm.Location.X", Location.X); @@ -107,15 +98,11 @@ namespace OpenHardwareMonitor.GUI { root.Image = Utilities.EmbeddedResources.GetImage("computer.png"); treeModel.Nodes.Add(root); - treeView.Model = treeModel; - - notifyIcon = new NotifyIcon(); - notifyIcon.ContextMenuStrip = this.notifyContextMenuStrip; - notifyIcon.Icon = EmbeddedResources.GetIcon("smallicon.ico"); - notifyIcon.Text = "Open Hardware Monitor"; - notifyIcon.DoubleClick += new EventHandler(this.hideShowClick); + treeView.Model = treeModel; - sensorSystemTray = new SensorSystemTray(computer); + systemTray = new SystemTray(computer); + systemTray.HideShowCommand += hideShowClick; + systemTray.ExitCommand += exitClick; computer.HardwareAdded += new HardwareEventHandler(HardwareAdded); computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved); @@ -257,7 +244,7 @@ namespace OpenHardwareMonitor.GUI { plotMenuItem.Checked; } - private void exitToolStripMenuItem_Click(object sender, EventArgs e) { + private void exitClick(object sender, EventArgs e) { Close(); } @@ -265,7 +252,7 @@ namespace OpenHardwareMonitor.GUI { computer.Accept(updateVisitor); treeView.Invalidate(); plotPanel.Invalidate(); - sensorSystemTray.Redraw(); + systemTray.Redraw(); } private void SaveConfiguration() { @@ -299,8 +286,7 @@ namespace OpenHardwareMonitor.GUI { SaveConfiguration(); timer.Enabled = false; - sensorSystemTray.Dispose(); - notifyIcon.Dispose(); + systemTray.Dispose(); computer.Close(); } @@ -347,16 +333,16 @@ namespace OpenHardwareMonitor.GUI { }; sensorContextMenuStrip.Items.Add(item); } - if (sensorSystemTray.Contains(node.Sensor)) { + if (systemTray.Contains(node.Sensor)) { ToolStripMenuItem item = new ToolStripMenuItem("Remove From Tray"); item.Click += delegate(object obj, EventArgs args) { - sensorSystemTray.Remove(node.Sensor); + systemTray.Remove(node.Sensor); }; sensorContextMenuStrip.Items.Add(item); } else { ToolStripMenuItem item = new ToolStripMenuItem("Add To Tray"); item.Click += delegate(object obj, EventArgs args) { - sensorSystemTray.Add(node.Sensor, true); + systemTray.Add(node.Sensor, true); }; sensorContextMenuStrip.Items.Add(item); } @@ -411,7 +397,7 @@ namespace OpenHardwareMonitor.GUI { if (sensor == null) return; - sensorSystemTray.Remove(sensor); + systemTray.Remove(sensor); } private void ShowParameterForm(ISensor sensor) { @@ -437,7 +423,7 @@ namespace OpenHardwareMonitor.GUI { } private void minTrayMenuItem_CheckedChanged(object sender, EventArgs e) { - notifyIcon.Visible = minTrayMenuItem.Checked; + systemTray.IsMainIconEnabled = minTrayMenuItem.Checked; } private void hiddenSensorsMenuItem_CheckedChanged(object sender, diff --git a/GUI/MainForm.resx b/GUI/MainForm.resx index 1b67307..4eb4497 100644 --- a/GUI/MainForm.resx +++ b/GUI/MainForm.resx @@ -120,17 +120,14 @@ 17, 17 - + 125, 17 - - 307, 17 - - 493, 17 + 311, 17 - 622, 17 + 440, 17 55 diff --git a/GUI/SensorNotifyIcon.cs b/GUI/SensorNotifyIcon.cs index 1d90978..90640b2 100644 --- a/GUI/SensorNotifyIcon.cs +++ b/GUI/SensorNotifyIcon.cs @@ -61,7 +61,7 @@ namespace OpenHardwareMonitor.GUI { private Pen pen; private Font font; - public SensorNotifyIcon(SensorSystemTray sensorSystemTray, ISensor sensor, + public SensorNotifyIcon(SystemTray sensorSystemTray, ISensor sensor, bool balloonTip) { this.sensor = sensor; @@ -78,7 +78,13 @@ namespace OpenHardwareMonitor.GUI { this.font = SystemFonts.MessageBoxFont; ContextMenuStrip contextMenuStrip = new ContextMenuStrip(); - ToolStripMenuItem removeItem = new ToolStripMenuItem("Remove"); + ToolStripMenuItem hideShowItem = new ToolStripMenuItem("Hide/Show"); + hideShowItem.Click += delegate(object obj, EventArgs args) { + sensorSystemTray.SendHideShowCommand(); + }; + contextMenuStrip.Items.Add(hideShowItem); + contextMenuStrip.Items.Add(new ToolStripSeparator()); + ToolStripMenuItem removeItem = new ToolStripMenuItem("Remove Sensor"); removeItem.Click += delegate(object obj, EventArgs args) { sensorSystemTray.Remove(this.sensor); }; @@ -94,7 +100,16 @@ namespace OpenHardwareMonitor.GUI { } }; contextMenuStrip.Items.Add(colorItem); + contextMenuStrip.Items.Add(new ToolStripSeparator()); + ToolStripMenuItem exitItem = new ToolStripMenuItem("Exit"); + exitItem.Click += delegate(object obj, EventArgs args) { + sensorSystemTray.SendExitCommand(); + }; + contextMenuStrip.Items.Add(exitItem); this.notifyIcon.ContextMenuStrip = contextMenuStrip; + this.notifyIcon.DoubleClick += delegate(object obj, EventArgs args) { + sensorSystemTray.SendHideShowCommand(); + }; this.bitmap = new Bitmap(16, 16, PixelFormat.Format32bppArgb); this.graphics = Graphics.FromImage(this.bitmap); diff --git a/GUI/SensorSystemTray.cs b/GUI/SystemTray.cs similarity index 68% rename from GUI/SensorSystemTray.cs rename to GUI/SystemTray.cs index 59260cf..79603d5 100644 --- a/GUI/SensorSystemTray.cs +++ b/GUI/SystemTray.cs @@ -44,14 +44,36 @@ using OpenHardwareMonitor.Hardware; using OpenHardwareMonitor.Utilities; namespace OpenHardwareMonitor.GUI { - public class SensorSystemTray : IDisposable { + public class SystemTray : IDisposable { private IComputer computer; private List list = new List(); + private bool mainIconEnabled = false; + private NotifyIcon mainIcon; - public SensorSystemTray(IComputer computer) { + public SystemTray(IComputer computer) { this.computer = computer; computer.HardwareAdded += new HardwareEventHandler(HardwareAdded); computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved); + + this.mainIcon = new NotifyIcon(); + + ContextMenuStrip contextMenuStrip = new ContextMenuStrip(); + ToolStripMenuItem hideShowItem = new ToolStripMenuItem("Hide/Show"); + hideShowItem.Click += delegate(object obj, EventArgs args) { + SendHideShowCommand(); + }; + contextMenuStrip.Items.Add(hideShowItem); + contextMenuStrip.Items.Add(new ToolStripSeparator()); + ToolStripMenuItem exitItem = new ToolStripMenuItem("Exit"); + exitItem.Click += delegate(object obj, EventArgs args) { + SendExitCommand(); + }; + contextMenuStrip.Items.Add(exitItem); + this.mainIcon.ContextMenuStrip = contextMenuStrip; + this.mainIcon.DoubleClick += delegate(object obj, EventArgs args) { + SendHideShowCommand(); + }; + this.mainIcon.Icon = EmbeddedResources.GetIcon("smallicon.ico"); } private void HardwareRemoved(IHardware hardware) { @@ -86,6 +108,7 @@ namespace OpenHardwareMonitor.GUI { public void Dispose() { foreach (SensorNotifyIcon icon in list) icon.Dispose(); + mainIcon.Dispose(); } public void Redraw() { @@ -105,6 +128,7 @@ namespace OpenHardwareMonitor.GUI { return; } else { list.Add(new SensorNotifyIcon(this, sensor, balloonTip)); + UpdateMainIconVisibilty(); Config.Set(new Identifier(sensor.Identifier, "tray").ToString(), true); } } @@ -126,9 +150,41 @@ namespace OpenHardwareMonitor.GUI { instance = icon; if (instance != null) { list.Remove(instance); - instance.Dispose(); + UpdateMainIconVisibilty(); + instance.Dispose(); } } + public event EventHandler HideShowCommand; + + public void SendHideShowCommand() { + if (HideShowCommand != null) + HideShowCommand(this, null); + } + + public event EventHandler ExitCommand; + + public void SendExitCommand() { + if (ExitCommand != null) + ExitCommand(this, null); + } + + private void UpdateMainIconVisibilty() { + if (mainIconEnabled) { + mainIcon.Visible = list.Count == 0; + } else { + mainIcon.Visible = false; + } + } + + public bool IsMainIconEnabled { + get { return mainIconEnabled; } + set { + if (mainIconEnabled != value) { + mainIconEnabled = value; + UpdateMainIconVisibilty(); + } + } + } } } diff --git a/Hardware/Mainboard/Mainboard.cs b/Hardware/Mainboard/Mainboard.cs index 12849d8..0bc5972 100644 --- a/Hardware/Mainboard/Mainboard.cs +++ b/Hardware/Mainboard/Mainboard.cs @@ -76,7 +76,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard { superIOHardware[i] = new SuperIOHardware(superIO[i], smbios.Board != null ? smbios.Board.Manufacturer : Manufacturer.Unknown, smbios.Board != null ? smbios.Board.Model : - Model.Unknown); + Model.Unknown); } public string Name { diff --git a/Hardware/Mainboard/Model.cs b/Hardware/Mainboard/Model.cs index fe48c76..229e51b 100644 --- a/Hardware/Mainboard/Model.cs +++ b/Hardware/Mainboard/Model.cs @@ -39,7 +39,9 @@ namespace OpenHardwareMonitor.Hardware.Mainboard { public enum Model { // ASUS - P5W_DH_Deluxe, + Crosshair_III_Formula, + M2N_SLI_DELUXE, + P5W_DH_Deluxe, // DFI LP_BI_P45_T2RS_Elite, @@ -52,8 +54,10 @@ namespace OpenHardwareMonitor.Hardware.Mainboard { _965P_S3, EP45_DS3R, EP45_UD3R, + EX58_EXTREME, GA_MA785GMT_UD2H, P35_DS3, + P35_DS3L, X38_DS5, // Unknown diff --git a/Hardware/Mainboard/SMBIOS.cs b/Hardware/Mainboard/SMBIOS.cs index 6ada970..fe3e257 100644 --- a/Hardware/Mainboard/SMBIOS.cs +++ b/Hardware/Mainboard/SMBIOS.cs @@ -226,6 +226,10 @@ namespace OpenHardwareMonitor.Hardware.Mainboard { } switch (productName) { + case "Crosshair III Formula": + model = Model.Crosshair_III_Formula; break; + case "M2N-SLI DELUXE": + model = Model.M2N_SLI_DELUXE; break; case "P5W DH Deluxe": model = Model.P5W_DH_Deluxe; break; case "LP BI P45-T2RS Elite": @@ -240,10 +244,14 @@ namespace OpenHardwareMonitor.Hardware.Mainboard { model = Model.EP45_DS3R; break; case "EP45-UD3R": model = Model.EP45_UD3R; break; + case "EX58-EXTREME": + model = Model.EX58_EXTREME; break; case "GA-MA785GMT-UD2H": model = Model.GA_MA785GMT_UD2H; break; case "P35-DS3": model = Model.P35_DS3; break; + case "P35-DS3L": + model = Model.P35_DS3L; break; case "X38-DS5": model = Model.X38_DS5; break; default: diff --git a/Hardware/Mainboard/SuperIOHardware.cs b/Hardware/Mainboard/SuperIOHardware.cs index 5835bd3..3f215f1 100644 --- a/Hardware/Mainboard/SuperIOHardware.cs +++ b/Hardware/Mainboard/SuperIOHardware.cs @@ -90,6 +90,44 @@ namespace OpenHardwareMonitor.Hardware.Mainboard { case Chip.IT8720F: case Chip.IT8726F: switch (manufacturer) { + case Manufacturer.ASUS: + switch (model) { + case Model.Crosshair_III_Formula: + v.Add(new Voltage("VBat", 8)); + t.Add(new Temperature("CPU", 0)); + for (int i = 0; i < superIO.Fans.Length; i++) + f.Add(new Fan("Fan #" + (i + 1), i)); + break; + case Model.M2N_SLI_DELUXE: + v.Add(new Voltage("CPU VCore", 0)); + v.Add(new Voltage("+3.3V", 1)); + v.Add(new Voltage("+5V", 3, 6.8f, 10, 0)); + v.Add(new Voltage("+12V", 4, 30, 10, 0)); + v.Add(new Voltage("+5VSB", 7, 6.8f, 10, 0)); + v.Add(new Voltage("VBat", 8)); + t.Add(new Temperature("CPU", 0)); + t.Add(new Temperature("Motherboard", 1)); + f.Add(new Fan("CPU Fan", 0)); + f.Add(new Fan("Chassis Fan #1", 1)); + f.Add(new Fan("Power Fan", 2)); + break; + default: + v.Add(new Voltage("CPU VCore", 0)); + v.Add(new Voltage("Voltage #2", 1, true)); + v.Add(new Voltage("Voltage #3", 2, true)); + v.Add(new Voltage("Voltage #4", 3, true)); + v.Add(new Voltage("Voltage #5", 4, true)); + v.Add(new Voltage("Voltage #6", 5, true)); + v.Add(new Voltage("Voltage #7", 6, true)); + v.Add(new Voltage("Voltage #8", 7, true)); + v.Add(new Voltage("VBat", 8)); + for (int i = 0; i < superIO.Temperatures.Length; i++) + t.Add(new Temperature("Temperature #" + (i + 1), i)); + for (int i = 0; i < superIO.Fans.Length; i++) + f.Add(new Fan("Fan #" + (i + 1), i)); + break; + } + break; case Manufacturer.DFI: switch (model) { case Model.LP_BI_P45_T2RS_Elite: @@ -160,7 +198,7 @@ namespace OpenHardwareMonitor.Hardware.Mainboard { break; case Model.EP45_DS3R: case Model.EP45_UD3R: - case Model.X38_DS5: + case Model.X38_DS5: v.Add(new Voltage("CPU VCore", 0)); v.Add(new Voltage("DRAM", 1)); v.Add(new Voltage("+3.3V", 2)); @@ -174,7 +212,21 @@ namespace OpenHardwareMonitor.Hardware.Mainboard { f.Add(new Fan("Power Fan", 2)); f.Add(new Fan("System Fan #1", 3)); break; + case Model.EX58_EXTREME: + v.Add(new Voltage("CPU VCore", 0)); + v.Add(new Voltage("DRAM", 1)); + v.Add(new Voltage("+5V", 3, 6.8f, 10, 0)); + v.Add(new Voltage("VBat", 8)); + t.Add(new Temperature("System", 0)); + t.Add(new Temperature("CPU", 1)); + t.Add(new Temperature("MCH", 2)); + f.Add(new Fan("CPU Fan", 0)); + f.Add(new Fan("System Fan #2", 1)); + f.Add(new Fan("Power Fan", 2)); + f.Add(new Fan("System Fan #1", 3)); + break; case Model.P35_DS3: + case Model.P35_DS3L: v.Add(new Voltage("CPU VCore", 0)); v.Add(new Voltage("DRAM", 1)); v.Add(new Voltage("+3.3V", 2)); diff --git a/OpenHardwareMonitor.csproj b/OpenHardwareMonitor.csproj index 05701ef..f22388a 100644 --- a/OpenHardwareMonitor.csproj +++ b/OpenHardwareMonitor.csproj @@ -74,7 +74,7 @@ ParameterForm.cs - +