From 6bb9184f9e61c3307309394b0ba8de9ddc6ff025 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 10:11:01 +0200 Subject: [PATCH 01/31] Pascal casing for public Settings members --- Hotkeys.cs | 30 ++++++++++----------- Main.cs | 32 +++++++++++----------- Settings.cs | 78 ++++++++++++++++++++++++++--------------------------- Tray.cs | 4 +-- 4 files changed, 72 insertions(+), 72 deletions(-) diff --git a/Hotkeys.cs b/Hotkeys.cs index 4b65a0f..3860f1b 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -66,8 +66,8 @@ protected override void WndProc(ref Message m) { if (CtrlAlt) Thread.Sleep(TimeSpan.FromSeconds(3)); - else if (_settings.delayCheckbox) - Thread.Sleep(TimeSpan.FromSeconds(_settings.delaySeconds)); + else if (_settings.DelayCheckbox) + Thread.Sleep(TimeSpan.FromSeconds(_settings.DelaySeconds)); try { Screenshot.CaptureWindow(ref info); @@ -88,26 +88,26 @@ protected override void WndProc(ref Message m) private ScreenshotTask GetParamteresFromUI() { var type = ScreenshotTask.BackgroundType.Transparent; - if (_settings.opaqueCheckbox && _settings.opaqueType == 0) + if (_settings.OpaqueCheckbox && _settings.OpaqueType == 0) type = ScreenshotTask.BackgroundType.Checkerboard; - else if (_settings.opaqueCheckbox && _settings.opaqueType == 1) + else if (_settings.OpaqueCheckbox && _settings.OpaqueType == 1) type = ScreenshotTask.BackgroundType.SolidColor; return new ScreenshotTask( WindowsApi.GetForegroundWindow(), - _settings.clipboardButton, - _settings.folderTextBox, - _settings.resizeCheckbox, - _settings.windowWidth, - _settings.windowHeight, + _settings.ClipboardButton, + _settings.FolderTextBox, + _settings.ResizeCheckbox, + _settings.WindowWidth, + _settings.WindowHeight, type, - Color.FromArgb(Convert.ToInt32("FF" + _settings.opaqueColorHexBox, 16)), - _settings.checkerValue, - _settings.aeroColorCheckbox, - Color.FromArgb(Convert.ToInt32("FF" + _settings.aeroColorHexBox, 16)), - _settings.mouseCheckbox, - _settings.clearTypeCheckbox); + Color.FromArgb(Convert.ToInt32("FF" + _settings.OpaqueColorHexBox, 16)), + _settings.CheckerValue, + _settings.AeroColorCheckbox, + Color.FromArgb(Convert.ToInt32("FF" + _settings.AeroColorHexBox, 16)), + _settings.MouseCheckbox, + _settings.ClearTypeCheckbox); } } } \ No newline at end of file diff --git a/Main.cs b/Main.cs index fb2a33d..47b09ab 100644 --- a/Main.cs +++ b/Main.cs @@ -37,22 +37,22 @@ public MainForm() Icon = new Icon(typeof(MainForm), "icon.ico"); InitializeComponent(); - folderTextBox.Text = _settings.folderTextBox; - clipboardButton.Checked = _settings.clipboardButton; - diskButton.Checked = _settings.diskButton; - resizeCheckbox.Checked = _settings.resizeCheckbox; - windowWidth.Value = _settings.windowWidth; - windowHeight.Value = _settings.windowHeight; - opaqueCheckbox.Checked = _settings.opaqueCheckbox; - opaqueType.SelectedIndex = _settings.opaqueType; - checkerValue.Value = _settings.checkerValue; - opaqueColorHexBox.Text = _settings.opaqueColorHexBox; - aeroColorCheckbox.Checked = _settings.aeroColorCheckbox; - aeroColorHexBox.Text = _settings.aeroColorHexBox; - mouseCheckbox.Checked = _settings.mouseCheckbox; - delayCheckbox.Checked = _settings.delayCheckbox; - delaySeconds.Value = _settings.delaySeconds; - clearTypeCheckbox.Checked = _settings.clearTypeCheckbox; + folderTextBox.Text = _settings.FolderTextBox; + clipboardButton.Checked = _settings.ClipboardButton; + diskButton.Checked = _settings.DiskButton; + resizeCheckbox.Checked = _settings.ResizeCheckbox; + windowWidth.Value = _settings.WindowWidth; + windowHeight.Value = _settings.WindowHeight; + opaqueCheckbox.Checked = _settings.OpaqueCheckbox; + opaqueType.SelectedIndex = _settings.OpaqueType; + checkerValue.Value = _settings.CheckerValue; + opaqueColorHexBox.Text = _settings.OpaqueColorHexBox; + aeroColorCheckbox.Checked = _settings.AeroColorCheckbox; + aeroColorHexBox.Text = _settings.AeroColorHexBox; + mouseCheckbox.Checked = _settings.MouseCheckbox; + delayCheckbox.Checked = _settings.DelayCheckbox; + delaySeconds.Value = _settings.DelaySeconds; + clearTypeCheckbox.Checked = _settings.ClearTypeCheckbox; if (!GlassAvailable()) { diff --git a/Settings.cs b/Settings.cs index db33354..0cfd4dd 100644 --- a/Settings.cs +++ b/Settings.cs @@ -23,23 +23,23 @@ namespace AeroShot { public class Settings { - public bool firstRun; - public int checkerValue = 8; - public string opaqueColorHexBox; - public string folderTextBox; - public bool opaqueCheckbox; - public byte opaqueType; - public bool aeroColorCheckbox; - public string aeroColorHexBox; - public bool resizeCheckbox; - public int windowHeight = 640; - public int windowWidth = 480; - public bool diskButton; - public bool clipboardButton; - public bool mouseCheckbox; - public bool delayCheckbox; - public byte delaySeconds = 3; - public bool clearTypeCheckbox; + public bool FirstRun; + public int CheckerValue = 8; + public string OpaqueColorHexBox; + public string FolderTextBox; + public bool OpaqueCheckbox; + public byte OpaqueType; + public bool AeroColorCheckbox; + public string AeroColorHexBox; + public bool ResizeCheckbox; + public int WindowHeight = 640; + public int WindowWidth = 480; + public bool DiskButton; + public bool ClipboardButton; + public bool MouseCheckbox; + public bool DelayCheckbox; + public byte DelaySeconds = 3; + public bool ClearTypeCheckbox; private readonly RegistryKey _registryKey; @@ -50,7 +50,7 @@ public Settings() if ((value = _registryKey.GetValue("FirstRun")) == null) { - firstRun = true; + FirstRun = true; } @@ -59,18 +59,18 @@ public Settings() { if (((string)value).Substring(0, 1) == "*") { - folderTextBox = ((string)value).Substring(1); - clipboardButton = true; + FolderTextBox = ((string)value).Substring(1); + ClipboardButton = true; } else { - folderTextBox = (string)value; - diskButton = true; + FolderTextBox = (string)value; + DiskButton = true; } } else { - folderTextBox = + FolderTextBox = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); } @@ -80,9 +80,9 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - resizeCheckbox = (b[0] & 1) == 1; - windowWidth = b[1] << 16 | b[2] << 8 | b[3]; - windowHeight = b[4] << 16 | b[5] << 8 | b[6]; + ResizeCheckbox = (b[0] & 1) == 1; + WindowWidth = b[1] << 16 | b[2] << 8 | b[3]; + WindowHeight = b[4] << 16 | b[5] << 8 | b[6]; } if ((value = _registryKey.GetValue("Opaque")) != null && @@ -91,22 +91,22 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - opaqueCheckbox = (b[0] & 1) == 1; + OpaqueCheckbox = (b[0] & 1) == 1; if ((b[0] & 2) == 2) - opaqueType = 0; + OpaqueType = 0; if ((b[0] & 4) == 4) - opaqueType = 1; + OpaqueType = 1; - checkerValue = b[1] + 2; + CheckerValue = b[1] + 2; var hex = new StringBuilder(6); hex.AppendFormat("{0:X2}", b[2]); hex.AppendFormat("{0:X2}", b[3]); hex.AppendFormat("{0:X2}", b[4]); - opaqueColorHexBox = hex.ToString(); + OpaqueColorHexBox = hex.ToString(); } else - opaqueType = 0; + OpaqueType = 0; if ((value = _registryKey.GetValue("AeroColor")) != null && value.GetType() == (typeof(long))) @@ -114,24 +114,24 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - aeroColorCheckbox = (b[0] & 1) == 1; + AeroColorCheckbox = (b[0] & 1) == 1; var hex = new StringBuilder(6); hex.AppendFormat("{0:X2}", b[1]); hex.AppendFormat("{0:X2}", b[2]); hex.AppendFormat("{0:X2}", b[3]); - aeroColorHexBox = hex.ToString(); + AeroColorHexBox = hex.ToString(); } else - opaqueType = 0; + OpaqueType = 0; if ((value = _registryKey.GetValue("CapturePointer")) != null && value.GetType() == (typeof(int))) - mouseCheckbox = ((int)value & 1) == 1; + MouseCheckbox = ((int)value & 1) == 1; if ((value = _registryKey.GetValue("ClearType")) != null && value.GetType() == (typeof(int))) - clearTypeCheckbox = ((int)value & 1) == 1; + ClearTypeCheckbox = ((int)value & 1) == 1; if ((value = _registryKey.GetValue("Delay")) != null && value.GetType() == (typeof(long))) @@ -139,8 +139,8 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - delayCheckbox = (b[0] & 1) == 1; - delaySeconds = b[1]; + DelayCheckbox = (b[0] & 1) == 1; + DelaySeconds = b[1]; } } } diff --git a/Tray.cs b/Tray.cs index ad876ee..7c0ca8f 100644 --- a/Tray.cs +++ b/Tray.cs @@ -57,9 +57,9 @@ protected override void OnLoad(EventArgs e) base.OnLoad(e); string saveLocation; - if (_settings.diskButton) + if (_settings.DiskButton) { - saveLocation = "\"" + _settings.folderTextBox + "\""; + saveLocation = "\"" + _settings.FolderTextBox + "\""; } else { From b05a1c4c77cd11b2f33bfc9d5cf4ff279b7174aa Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 10:12:46 +0200 Subject: [PATCH 02/31] Settings.FirstRun was never used --- Settings.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Settings.cs b/Settings.cs index 0cfd4dd..f0722b1 100644 --- a/Settings.cs +++ b/Settings.cs @@ -23,7 +23,6 @@ namespace AeroShot { public class Settings { - public bool FirstRun; public int CheckerValue = 8; public string OpaqueColorHexBox; public string FolderTextBox; @@ -48,12 +47,6 @@ public Settings() object value; _registryKey = Registry.CurrentUser.CreateSubKey(@"Software\AeroShot"); - if ((value = _registryKey.GetValue("FirstRun")) == null) - { - FirstRun = true; - } - - if ((value = _registryKey.GetValue("LastPath")) != null && value.GetType() == (typeof(string))) { From 5878d741f1f377c9d5afaff4e3c2a27e26d395f1 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 10:28:20 +0200 Subject: [PATCH 03/31] More logical Settings field names Settings fields were named after the controls like DiskButton when UseDisk is more logical. --- Hotkeys.cs | 26 ++++++++++++------------- Main.cs | 26 ++++++++++++------------- Settings.cs | 56 ++++++++++++++++++++++++++--------------------------- Tray.cs | 4 ++-- 4 files changed, 56 insertions(+), 56 deletions(-) diff --git a/Hotkeys.cs b/Hotkeys.cs index 3860f1b..6d20c09 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -66,8 +66,8 @@ protected override void WndProc(ref Message m) { if (CtrlAlt) Thread.Sleep(TimeSpan.FromSeconds(3)); - else if (_settings.DelayCheckbox) - Thread.Sleep(TimeSpan.FromSeconds(_settings.DelaySeconds)); + else if (_settings.DelayCapture) + Thread.Sleep(TimeSpan.FromSeconds(_settings.DelayCaptureSeconds)); try { Screenshot.CaptureWindow(ref info); @@ -88,26 +88,26 @@ protected override void WndProc(ref Message m) private ScreenshotTask GetParamteresFromUI() { var type = ScreenshotTask.BackgroundType.Transparent; - if (_settings.OpaqueCheckbox && _settings.OpaqueType == 0) + if (_settings.UseOpaqueBackground && _settings.OpaqueType == 0) type = ScreenshotTask.BackgroundType.Checkerboard; - else if (_settings.OpaqueCheckbox && _settings.OpaqueType == 1) + else if (_settings.UseOpaqueBackground && _settings.OpaqueType == 1) type = ScreenshotTask.BackgroundType.SolidColor; return new ScreenshotTask( WindowsApi.GetForegroundWindow(), - _settings.ClipboardButton, - _settings.FolderTextBox, - _settings.ResizeCheckbox, + _settings.UseClipboard, + _settings.FolderPath, + _settings.Resize, _settings.WindowWidth, _settings.WindowHeight, type, - Color.FromArgb(Convert.ToInt32("FF" + _settings.OpaqueColorHexBox, 16)), - _settings.CheckerValue, - _settings.AeroColorCheckbox, - Color.FromArgb(Convert.ToInt32("FF" + _settings.AeroColorHexBox, 16)), - _settings.MouseCheckbox, - _settings.ClearTypeCheckbox); + Color.FromArgb(Convert.ToInt32("FF" + _settings.OpaqueColorHex, 16)), + _settings.CheckerSize, + _settings.UseAeroColor, + Color.FromArgb(Convert.ToInt32("FF" + _settings.AeroColorHex, 16)), + _settings.CaputreMouse, + _settings.DisableClearType); } } } \ No newline at end of file diff --git a/Main.cs b/Main.cs index 47b09ab..da44cce 100644 --- a/Main.cs +++ b/Main.cs @@ -37,22 +37,22 @@ public MainForm() Icon = new Icon(typeof(MainForm), "icon.ico"); InitializeComponent(); - folderTextBox.Text = _settings.FolderTextBox; - clipboardButton.Checked = _settings.ClipboardButton; - diskButton.Checked = _settings.DiskButton; - resizeCheckbox.Checked = _settings.ResizeCheckbox; + folderTextBox.Text = _settings.FolderPath; + clipboardButton.Checked = _settings.UseClipboard; + diskButton.Checked = _settings.UseDisk; + resizeCheckbox.Checked = _settings.Resize; windowWidth.Value = _settings.WindowWidth; windowHeight.Value = _settings.WindowHeight; - opaqueCheckbox.Checked = _settings.OpaqueCheckbox; + opaqueCheckbox.Checked = _settings.UseOpaqueBackground; opaqueType.SelectedIndex = _settings.OpaqueType; - checkerValue.Value = _settings.CheckerValue; - opaqueColorHexBox.Text = _settings.OpaqueColorHexBox; - aeroColorCheckbox.Checked = _settings.AeroColorCheckbox; - aeroColorHexBox.Text = _settings.AeroColorHexBox; - mouseCheckbox.Checked = _settings.MouseCheckbox; - delayCheckbox.Checked = _settings.DelayCheckbox; - delaySeconds.Value = _settings.DelaySeconds; - clearTypeCheckbox.Checked = _settings.ClearTypeCheckbox; + checkerValue.Value = _settings.CheckerSize; + opaqueColorHexBox.Text = _settings.OpaqueColorHex; + aeroColorCheckbox.Checked = _settings.UseAeroColor; + aeroColorHexBox.Text = _settings.AeroColorHex; + mouseCheckbox.Checked = _settings.CaputreMouse; + delayCheckbox.Checked = _settings.DelayCapture; + delaySeconds.Value = _settings.DelayCaptureSeconds; + clearTypeCheckbox.Checked = _settings.DisableClearType; if (!GlassAvailable()) { diff --git a/Settings.cs b/Settings.cs index f0722b1..4d9d88e 100644 --- a/Settings.cs +++ b/Settings.cs @@ -23,22 +23,22 @@ namespace AeroShot { public class Settings { - public int CheckerValue = 8; - public string OpaqueColorHexBox; - public string FolderTextBox; - public bool OpaqueCheckbox; + public bool UseDisk; + public bool UseClipboard; + public string FolderPath; + public bool UseOpaqueBackground; public byte OpaqueType; - public bool AeroColorCheckbox; - public string AeroColorHexBox; - public bool ResizeCheckbox; + public string OpaqueColorHex; + public int CheckerSize = 8; + public bool UseAeroColor; + public string AeroColorHex; + public bool Resize; public int WindowHeight = 640; public int WindowWidth = 480; - public bool DiskButton; - public bool ClipboardButton; - public bool MouseCheckbox; - public bool DelayCheckbox; - public byte DelaySeconds = 3; - public bool ClearTypeCheckbox; + public bool CaputreMouse; + public bool DelayCapture; + public byte DelayCaptureSeconds = 3; + public bool DisableClearType; private readonly RegistryKey _registryKey; @@ -52,18 +52,18 @@ public Settings() { if (((string)value).Substring(0, 1) == "*") { - FolderTextBox = ((string)value).Substring(1); - ClipboardButton = true; + FolderPath = ((string)value).Substring(1); + UseClipboard = true; } else { - FolderTextBox = (string)value; - DiskButton = true; + FolderPath = (string)value; + UseDisk = true; } } else { - FolderTextBox = + FolderPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); } @@ -73,7 +73,7 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - ResizeCheckbox = (b[0] & 1) == 1; + Resize = (b[0] & 1) == 1; WindowWidth = b[1] << 16 | b[2] << 8 | b[3]; WindowHeight = b[4] << 16 | b[5] << 8 | b[6]; } @@ -84,19 +84,19 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - OpaqueCheckbox = (b[0] & 1) == 1; + UseOpaqueBackground = (b[0] & 1) == 1; if ((b[0] & 2) == 2) OpaqueType = 0; if ((b[0] & 4) == 4) OpaqueType = 1; - CheckerValue = b[1] + 2; + CheckerSize = b[1] + 2; var hex = new StringBuilder(6); hex.AppendFormat("{0:X2}", b[2]); hex.AppendFormat("{0:X2}", b[3]); hex.AppendFormat("{0:X2}", b[4]); - OpaqueColorHexBox = hex.ToString(); + OpaqueColorHex = hex.ToString(); } else OpaqueType = 0; @@ -107,24 +107,24 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - AeroColorCheckbox = (b[0] & 1) == 1; + UseAeroColor = (b[0] & 1) == 1; var hex = new StringBuilder(6); hex.AppendFormat("{0:X2}", b[1]); hex.AppendFormat("{0:X2}", b[2]); hex.AppendFormat("{0:X2}", b[3]); - AeroColorHexBox = hex.ToString(); + AeroColorHex = hex.ToString(); } else OpaqueType = 0; if ((value = _registryKey.GetValue("CapturePointer")) != null && value.GetType() == (typeof(int))) - MouseCheckbox = ((int)value & 1) == 1; + CaputreMouse = ((int)value & 1) == 1; if ((value = _registryKey.GetValue("ClearType")) != null && value.GetType() == (typeof(int))) - ClearTypeCheckbox = ((int)value & 1) == 1; + DisableClearType = ((int)value & 1) == 1; if ((value = _registryKey.GetValue("Delay")) != null && value.GetType() == (typeof(long))) @@ -132,8 +132,8 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - DelayCheckbox = (b[0] & 1) == 1; - DelaySeconds = b[1]; + DelayCapture = (b[0] & 1) == 1; + DelayCaptureSeconds = b[1]; } } } diff --git a/Tray.cs b/Tray.cs index 7c0ca8f..0e90a72 100644 --- a/Tray.cs +++ b/Tray.cs @@ -57,9 +57,9 @@ protected override void OnLoad(EventArgs e) base.OnLoad(e); string saveLocation; - if (_settings.DiskButton) + if (_settings.UseDisk) { - saveLocation = "\"" + _settings.FolderTextBox + "\""; + saveLocation = "\"" + _settings.FolderPath + "\""; } else { From 995a4adb0072feb369200d422e008053bdb5d069 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 10:28:54 +0200 Subject: [PATCH 04/31] Settings does note need to be public --- Settings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Settings.cs b/Settings.cs index 4d9d88e..8f5051a 100644 --- a/Settings.cs +++ b/Settings.cs @@ -21,7 +21,7 @@ You should have received a copy of the GNU General Public License namespace AeroShot { - public class Settings + sealed class Settings { public bool UseDisk; public bool UseClipboard; From b9ba6b258c206067eda64dd946db84ff7ca2678e Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 12:56:39 +0200 Subject: [PATCH 05/31] Stronger-typed color settings --- Hotkeys.cs | 5 ++--- Main.cs | 4 ++-- Settings.cs | 32 +++++++++++++++----------------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/Hotkeys.cs b/Hotkeys.cs index 6d20c09..af62ff1 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -16,7 +16,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ using System; -using System.Drawing; using System.Threading; using System.Windows.Forms; @@ -102,10 +101,10 @@ private ScreenshotTask GetParamteresFromUI() _settings.WindowWidth, _settings.WindowHeight, type, - Color.FromArgb(Convert.ToInt32("FF" + _settings.OpaqueColorHex, 16)), + _settings.OpaqueColor, _settings.CheckerSize, _settings.UseAeroColor, - Color.FromArgb(Convert.ToInt32("FF" + _settings.AeroColorHex, 16)), + _settings.AeroColor, _settings.CaputreMouse, _settings.DisableClearType); } diff --git a/Main.cs b/Main.cs index da44cce..2719ccb 100644 --- a/Main.cs +++ b/Main.cs @@ -46,9 +46,9 @@ public MainForm() opaqueCheckbox.Checked = _settings.UseOpaqueBackground; opaqueType.SelectedIndex = _settings.OpaqueType; checkerValue.Value = _settings.CheckerSize; - opaqueColorHexBox.Text = _settings.OpaqueColorHex; + opaqueColorHexBox.Text = HexColor.Encode(_settings.OpaqueColor); aeroColorCheckbox.Checked = _settings.UseAeroColor; - aeroColorHexBox.Text = _settings.AeroColorHex; + aeroColorHexBox.Text = HexColor.Encode(_settings.AeroColor); mouseCheckbox.Checked = _settings.CaputreMouse; delayCheckbox.Checked = _settings.DelayCapture; delaySeconds.Value = _settings.DelayCaptureSeconds; diff --git a/Settings.cs b/Settings.cs index 8f5051a..10a1377 100644 --- a/Settings.cs +++ b/Settings.cs @@ -16,22 +16,23 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ using System; -using System.Text; using Microsoft.Win32; namespace AeroShot { - sealed class Settings + using System.Drawing; + + sealed class Settings { public bool UseDisk; public bool UseClipboard; public string FolderPath; public bool UseOpaqueBackground; public byte OpaqueType; - public string OpaqueColorHex; + public Color OpaqueColor; public int CheckerSize = 8; public bool UseAeroColor; - public string AeroColorHex; + public Color AeroColor; public bool Resize; public int WindowHeight = 640; public int WindowWidth = 480; @@ -89,14 +90,8 @@ public Settings() OpaqueType = 0; if ((b[0] & 4) == 4) OpaqueType = 1; - CheckerSize = b[1] + 2; - - var hex = new StringBuilder(6); - hex.AppendFormat("{0:X2}", b[2]); - hex.AppendFormat("{0:X2}", b[3]); - hex.AppendFormat("{0:X2}", b[4]); - OpaqueColorHex = hex.ToString(); + OpaqueColor = Color.FromArgb(b[2], b[3], b[4]); } else OpaqueType = 0; @@ -108,12 +103,7 @@ public Settings() for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); UseAeroColor = (b[0] & 1) == 1; - - var hex = new StringBuilder(6); - hex.AppendFormat("{0:X2}", b[1]); - hex.AppendFormat("{0:X2}", b[2]); - hex.AppendFormat("{0:X2}", b[3]); - AeroColorHex = hex.ToString(); + AeroColor = Color.FromArgb(b[1], b[2], b[3]); } else OpaqueType = 0; @@ -137,4 +127,12 @@ public Settings() } } } + + static class HexColor + { + public static string Encode(Color color) + { + return color.IsEmpty ? null : ColorTranslator.ToHtml(color).Substring(1); + } + } } \ No newline at end of file From 3d8ec844a9242669a9ad96e2229cce67a16ebc15 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 13:24:16 +0200 Subject: [PATCH 06/31] Stronger-typed background settings --- Hotkeys.cs | 14 +++++--------- Main.cs | 8 +++++--- Screenshot.cs | 30 +++++++++++++++--------------- Settings.cs | 17 +++++++++-------- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/Hotkeys.cs b/Hotkeys.cs index af62ff1..7321580 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -86,13 +86,7 @@ protected override void WndProc(ref Message m) private ScreenshotTask GetParamteresFromUI() { - var type = ScreenshotTask.BackgroundType.Transparent; - if (_settings.UseOpaqueBackground && _settings.OpaqueType == 0) - type = ScreenshotTask.BackgroundType.Checkerboard; - else if (_settings.UseOpaqueBackground && _settings.OpaqueType == 1) - type = ScreenshotTask.BackgroundType.SolidColor; - - return + return new ScreenshotTask( WindowsApi.GetForegroundWindow(), _settings.UseClipboard, @@ -100,8 +94,10 @@ private ScreenshotTask GetParamteresFromUI() _settings.Resize, _settings.WindowWidth, _settings.WindowHeight, - type, - _settings.OpaqueColor, + _settings.UseOpaqueBackground + ? _settings.BackgroundType + : ScreenshotBackgroundType.Transparent, + _settings.OpaqueBackgroundColor, _settings.CheckerSize, _settings.UseAeroColor, _settings.AeroColor, diff --git a/Main.cs b/Main.cs index 2719ccb..91b1fd3 100644 --- a/Main.cs +++ b/Main.cs @@ -43,10 +43,12 @@ public MainForm() resizeCheckbox.Checked = _settings.Resize; windowWidth.Value = _settings.WindowWidth; windowHeight.Value = _settings.WindowHeight; - opaqueCheckbox.Checked = _settings.UseOpaqueBackground; - opaqueType.SelectedIndex = _settings.OpaqueType; + opaqueCheckbox.Checked = _settings.UseOpaqueBackground; + opaqueType.SelectedIndex = _settings.BackgroundType == ScreenshotBackgroundType.Checkerboard ? 0 + : _settings.BackgroundType == ScreenshotBackgroundType.SolidColor ? 1 + : -1; checkerValue.Value = _settings.CheckerSize; - opaqueColorHexBox.Text = HexColor.Encode(_settings.OpaqueColor); + opaqueColorHexBox.Text = HexColor.Encode(_settings.OpaqueBackgroundColor); aeroColorCheckbox.Checked = _settings.UseAeroColor; aeroColorHexBox.Text = HexColor.Encode(_settings.AeroColor); mouseCheckbox.Checked = _settings.CaputreMouse; diff --git a/Screenshot.cs b/Screenshot.cs index d338308..af2ae76 100644 --- a/Screenshot.cs +++ b/Screenshot.cs @@ -28,14 +28,7 @@ namespace AeroShot { internal struct ScreenshotTask { - public enum BackgroundType - { - Transparent, - Checkerboard, - SolidColor - } - - public BackgroundType Background; + public ScreenshotBackgroundType Background; public Color BackgroundColor; public bool CaptureMouse; public bool DisableClearType; @@ -51,7 +44,7 @@ public enum BackgroundType public ScreenshotTask(IntPtr window, bool clipboard, string file, bool resize, int resizeX, int resizeY, - BackgroundType backType, Color backColor, + ScreenshotBackgroundType backType, Color backColor, int checkerSize, bool customGlass, Color aeroColor, bool mouse, bool clearType) { @@ -71,7 +64,14 @@ public ScreenshotTask(IntPtr window, bool clipboard, string file, } } - internal static class Screenshot + enum ScreenshotBackgroundType + { + Transparent, + Checkerboard, + SolidColor + } + + internal static class Screenshot { private const uint SWP_NOACTIVATE = 0x0010; private const int GWL_STYLE = -16; @@ -186,7 +186,7 @@ internal static void CaptureWindow(ref ScreenshotTask data) { if (data.ClipboardNotDisk && data.Background != - ScreenshotTask.BackgroundType.Transparent) + ScreenshotBackgroundType.Transparent) // Screenshot is already opaque, don't need to modify it Clipboard.SetImage(s); else if (data.ClipboardNotDisk) @@ -342,8 +342,8 @@ private static unsafe Bitmap CaptureCompositeScreenshot( ref ScreenshotTask data) { Color tmpColor = data.BackgroundColor; - if (data.Background == ScreenshotTask.BackgroundType.Transparent || - data.Background == ScreenshotTask.BackgroundType.Checkerboard) + if (data.Background == ScreenshotBackgroundType.Transparent || + data.Background == ScreenshotBackgroundType.Checkerboard) tmpColor = Color.White; var backdrop = new Form { @@ -401,7 +401,7 @@ private static unsafe Bitmap CaptureCompositeScreenshot( rct.Right - rct.Left, rct.Bottom - rct.Top)); - if (data.Background == ScreenshotTask.BackgroundType.SolidColor) + if (data.Background == ScreenshotBackgroundType.SolidColor) { backdrop.Dispose(); if (data.CaptureMouse) @@ -432,7 +432,7 @@ private static unsafe Bitmap CaptureCompositeScreenshot( whiteShot.Dispose(); blackShot.Dispose(); - if (data.Background == ScreenshotTask.BackgroundType.Checkerboard) + if (data.Background == ScreenshotBackgroundType.Checkerboard) { var final = new Bitmap(transparentImage.Width, transparentImage.Height, diff --git a/Settings.cs b/Settings.cs index 10a1377..43d419b 100644 --- a/Settings.cs +++ b/Settings.cs @@ -27,9 +27,9 @@ sealed class Settings public bool UseDisk; public bool UseClipboard; public string FolderPath; - public bool UseOpaqueBackground; - public byte OpaqueType; - public Color OpaqueColor; + public bool UseOpaqueBackground; + public ScreenshotBackgroundType BackgroundType; + public Color OpaqueBackgroundColor; public int CheckerSize = 8; public bool UseAeroColor; public Color AeroColor; @@ -85,16 +85,17 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); + BackgroundType = ScreenshotBackgroundType.Transparent; UseOpaqueBackground = (b[0] & 1) == 1; if ((b[0] & 2) == 2) - OpaqueType = 0; + BackgroundType = ScreenshotBackgroundType.Checkerboard; if ((b[0] & 4) == 4) - OpaqueType = 1; + BackgroundType = ScreenshotBackgroundType.SolidColor; CheckerSize = b[1] + 2; - OpaqueColor = Color.FromArgb(b[2], b[3], b[4]); + OpaqueBackgroundColor = Color.FromArgb(b[2], b[3], b[4]); } else - OpaqueType = 0; + BackgroundType = 0; if ((value = _registryKey.GetValue("AeroColor")) != null && value.GetType() == (typeof(long))) @@ -106,7 +107,7 @@ public Settings() AeroColor = Color.FromArgb(b[1], b[2], b[3]); } else - OpaqueType = 0; + BackgroundType = 0; if ((value = _registryKey.GetValue("CapturePointer")) != null && value.GetType() == (typeof(int))) From 9ce6caaa6bb7f08f93b524f2a267420b3f26401e Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 13:25:06 +0200 Subject: [PATCH 07/31] Fix for reversed default window resize settings --- Settings.cs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Settings.cs b/Settings.cs index 43d419b..56ae368 100644 --- a/Settings.cs +++ b/Settings.cs @@ -28,14 +28,14 @@ sealed class Settings public bool UseClipboard; public string FolderPath; public bool UseOpaqueBackground; - public ScreenshotBackgroundType BackgroundType; - public Color OpaqueBackgroundColor; - public int CheckerSize = 8; + public ScreenshotBackgroundType OpaqueBackgroundType; + public Color SolidBackgroundColor; + public int CheckerboardBackgroundCheckerSize = 8; public bool UseAeroColor; public Color AeroColor; public bool Resize; - public int WindowHeight = 640; - public int WindowWidth = 480; + public int WindowHeight = 480; + public int WindowWidth = 640; public bool CaputreMouse; public bool DelayCapture; public byte DelayCaptureSeconds = 3; @@ -85,17 +85,17 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - BackgroundType = ScreenshotBackgroundType.Transparent; + OpaqueBackgroundType = ScreenshotBackgroundType.Transparent; UseOpaqueBackground = (b[0] & 1) == 1; if ((b[0] & 2) == 2) - BackgroundType = ScreenshotBackgroundType.Checkerboard; + OpaqueBackgroundType = ScreenshotBackgroundType.Checkerboard; if ((b[0] & 4) == 4) - BackgroundType = ScreenshotBackgroundType.SolidColor; - CheckerSize = b[1] + 2; - OpaqueBackgroundColor = Color.FromArgb(b[2], b[3], b[4]); + OpaqueBackgroundType = ScreenshotBackgroundType.SolidColor; + CheckerboardBackgroundCheckerSize = b[1] + 2; + SolidBackgroundColor = Color.FromArgb(b[2], b[3], b[4]); } else - BackgroundType = 0; + OpaqueBackgroundType = 0; if ((value = _registryKey.GetValue("AeroColor")) != null && value.GetType() == (typeof(long))) @@ -107,7 +107,7 @@ public Settings() AeroColor = Color.FromArgb(b[1], b[2], b[3]); } else - BackgroundType = 0; + OpaqueBackgroundType = 0; if ((value = _registryKey.GetValue("CapturePointer")) != null && value.GetType() == (typeof(int))) From 8de88647db9c3fa20820dd9d8d51ac53aea51056 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 13:35:27 +0200 Subject: [PATCH 08/31] Stronger-type resize settings --- Hotkeys.cs | 11 +++++------ Main.cs | 14 +++++++------- Screenshot.cs | 26 +++++++++++++------------- Settings.cs | 12 ++++++------ 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/Hotkeys.cs b/Hotkeys.cs index 7321580..4d2f1b0 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ using System; +using System.Drawing; using System.Threading; using System.Windows.Forms; @@ -91,14 +92,12 @@ private ScreenshotTask GetParamteresFromUI() WindowsApi.GetForegroundWindow(), _settings.UseClipboard, _settings.FolderPath, - _settings.Resize, - _settings.WindowWidth, - _settings.WindowHeight, + _settings.UseResizeDimensions ? _settings.ResizeDimensions : (Size?) null, _settings.UseOpaqueBackground - ? _settings.BackgroundType + ? _settings.OpaqueBackgroundType : ScreenshotBackgroundType.Transparent, - _settings.OpaqueBackgroundColor, - _settings.CheckerSize, + _settings.SolidBackgroundColor, + _settings.CheckerboardBackgroundCheckerSize, _settings.UseAeroColor, _settings.AeroColor, _settings.CaputreMouse, diff --git a/Main.cs b/Main.cs index 91b1fd3..2cd864a 100644 --- a/Main.cs +++ b/Main.cs @@ -40,15 +40,15 @@ public MainForm() folderTextBox.Text = _settings.FolderPath; clipboardButton.Checked = _settings.UseClipboard; diskButton.Checked = _settings.UseDisk; - resizeCheckbox.Checked = _settings.Resize; - windowWidth.Value = _settings.WindowWidth; - windowHeight.Value = _settings.WindowHeight; + resizeCheckbox.Checked = _settings.UseResizeDimensions; + windowWidth.Value = _settings.ResizeDimensions.Width; + windowHeight.Value = _settings.ResizeDimensions.Height; opaqueCheckbox.Checked = _settings.UseOpaqueBackground; - opaqueType.SelectedIndex = _settings.BackgroundType == ScreenshotBackgroundType.Checkerboard ? 0 - : _settings.BackgroundType == ScreenshotBackgroundType.SolidColor ? 1 + opaqueType.SelectedIndex = _settings.OpaqueBackgroundType == ScreenshotBackgroundType.Checkerboard ? 0 + : _settings.OpaqueBackgroundType == ScreenshotBackgroundType.SolidColor ? 1 : -1; - checkerValue.Value = _settings.CheckerSize; - opaqueColorHexBox.Text = HexColor.Encode(_settings.OpaqueBackgroundColor); + checkerValue.Value = _settings.CheckerboardBackgroundCheckerSize; + opaqueColorHexBox.Text = HexColor.Encode(_settings.SolidBackgroundColor); aeroColorCheckbox.Checked = _settings.UseAeroColor; aeroColorHexBox.Text = HexColor.Encode(_settings.AeroColor); mouseCheckbox.Checked = _settings.CaputreMouse; diff --git a/Screenshot.cs b/Screenshot.cs index af2ae76..058b7c2 100644 --- a/Screenshot.cs +++ b/Screenshot.cs @@ -16,6 +16,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ using System; +using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.IO; @@ -26,7 +27,7 @@ You should have received a copy of the GNU General Public License namespace AeroShot { - internal struct ScreenshotTask + internal struct ScreenshotTask { public ScreenshotBackgroundType Background; public Color BackgroundColor; @@ -37,13 +38,11 @@ internal struct ScreenshotTask public Color AeroColor; public bool ClipboardNotDisk; public string DiskSaveDirectory; - public bool DoResize; - public int ResizeX; - public int ResizeY; + public Size? Resize; public IntPtr WindowHandle; public ScreenshotTask(IntPtr window, bool clipboard, string file, - bool resize, int resizeX, int resizeY, + Size? resize, ScreenshotBackgroundType backType, Color backColor, int checkerSize, bool customGlass, Color aeroColor, bool mouse, bool clearType) @@ -51,9 +50,7 @@ public ScreenshotTask(IntPtr window, bool clipboard, string file, WindowHandle = window; ClipboardNotDisk = clipboard; DiskSaveDirectory = file; - DoResize = resize; - ResizeX = resizeX; - ResizeY = resizeY; + Resize = resize; Background = backType; BackgroundColor = backColor; CheckerboardSize = checkerSize; @@ -139,7 +136,7 @@ internal static void CaptureWindow(ref ScreenshotTask data) } var r = new WindowsRect(0); - if (data.DoResize) + if (data.Resize != null) { SmartResizeWindow(ref data, out r); Thread.Sleep(100); @@ -237,7 +234,7 @@ internal static void CaptureWindow(ref ScreenshotTask data) s.Dispose(); } - if (data.DoResize) + if (data.Resize != null) { if ( (WindowsApi.GetWindowLong(data.WindowHandle, @@ -309,6 +306,9 @@ private static bool ClearTypeEnabled() private static void SmartResizeWindow(ref ScreenshotTask data, out WindowsRect oldWindowSize) { + Debug.Assert(data.Resize != null); + var dim = data.Resize.Value; + oldWindowSize = new WindowsRect(0); if ((WindowsApi.GetWindowLong(data.WindowHandle, GWL_STYLE) & WS_SIZEBOX) != WS_SIZEBOX) @@ -323,9 +323,9 @@ private static void SmartResizeWindow(ref ScreenshotTask data, { WindowsApi.SetWindowPos(data.WindowHandle, (IntPtr)0, r.Left, r.Top, - data.ResizeX - + dim.Width - (f.Width - (r.Right - r.Left)), - data.ResizeY - + dim.Height - (f.Height - (r.Bottom - r.Top)), SWP_SHOWWINDOW); f.Dispose(); @@ -333,7 +333,7 @@ private static void SmartResizeWindow(ref ScreenshotTask data, else { WindowsApi.SetWindowPos(data.WindowHandle, (IntPtr)0, r.Left, - r.Top, data.ResizeX, data.ResizeY, + r.Top, dim.Width, dim.Height, SWP_SHOWWINDOW); } } diff --git a/Settings.cs b/Settings.cs index 56ae368..b7c3c0d 100644 --- a/Settings.cs +++ b/Settings.cs @@ -33,9 +33,8 @@ sealed class Settings public int CheckerboardBackgroundCheckerSize = 8; public bool UseAeroColor; public Color AeroColor; - public bool Resize; - public int WindowHeight = 480; - public int WindowWidth = 640; + public bool UseResizeDimensions; + public Size ResizeDimensions = new Size(640, 480); public bool CaputreMouse; public bool DelayCapture; public byte DelayCaptureSeconds = 3; @@ -74,9 +73,10 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - Resize = (b[0] & 1) == 1; - WindowWidth = b[1] << 16 | b[2] << 8 | b[3]; - WindowHeight = b[4] << 16 | b[5] << 8 | b[6]; + UseResizeDimensions = (b[0] & 1) == 1; + var width = b[1] << 16 | b[2] << 8 | b[3]; + var height = b[4] << 16 | b[5] << 8 | b[6]; + ResizeDimensions = new Size(width, height); } if ((value = _registryKey.GetValue("Opaque")) != null && From 915b3e3a0c07a66f1f53b746d43c150b9cbf2b0a Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 13:38:34 +0200 Subject: [PATCH 09/31] Stronger-type capture delay setting Using TimeSpan instead of a technical and weaker type like byte --- Hotkeys.cs | 2 +- Main.cs | 2 +- Settings.cs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Hotkeys.cs b/Hotkeys.cs index 4d2f1b0..e1b39d5 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -67,7 +67,7 @@ protected override void WndProc(ref Message m) if (CtrlAlt) Thread.Sleep(TimeSpan.FromSeconds(3)); else if (_settings.DelayCapture) - Thread.Sleep(TimeSpan.FromSeconds(_settings.DelayCaptureSeconds)); + Thread.Sleep(_settings.DelayCaptureDuration); try { Screenshot.CaptureWindow(ref info); diff --git a/Main.cs b/Main.cs index 2cd864a..4818d0a 100644 --- a/Main.cs +++ b/Main.cs @@ -53,7 +53,7 @@ public MainForm() aeroColorHexBox.Text = HexColor.Encode(_settings.AeroColor); mouseCheckbox.Checked = _settings.CaputreMouse; delayCheckbox.Checked = _settings.DelayCapture; - delaySeconds.Value = _settings.DelayCaptureSeconds; + delaySeconds.Value = (decimal) _settings.DelayCaptureDuration.TotalSeconds; clearTypeCheckbox.Checked = _settings.DisableClearType; if (!GlassAvailable()) diff --git a/Settings.cs b/Settings.cs index b7c3c0d..bee1a38 100644 --- a/Settings.cs +++ b/Settings.cs @@ -37,7 +37,7 @@ sealed class Settings public Size ResizeDimensions = new Size(640, 480); public bool CaputreMouse; public bool DelayCapture; - public byte DelayCaptureSeconds = 3; + public TimeSpan DelayCaptureDuration = TimeSpan.FromSeconds(3); public bool DisableClearType; private readonly RegistryKey _registryKey; @@ -124,7 +124,7 @@ public Settings() for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); DelayCapture = (b[0] & 1) == 1; - DelayCaptureSeconds = b[1]; + DelayCaptureDuration = TimeSpan.FromSeconds(b[1]); } } } From 8a2a22bc8f3b301dbe44d5c26ed4f0c3dbd1900e Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 18:59:19 +0200 Subject: [PATCH 10/31] Folding bool + state settings into a Switch --- AeroShot.csproj | 1 + Hotkeys.cs | 17 +++++++---------- Main.cs | 20 ++++++++++---------- Screenshot.cs | 14 ++++++-------- Settings.cs | 44 ++++++++++++++++++++------------------------ Switch.cs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 91 insertions(+), 52 deletions(-) create mode 100644 Switch.cs diff --git a/AeroShot.csproj b/AeroShot.csproj index 52443ae..4115ee9 100644 --- a/AeroShot.csproj +++ b/AeroShot.csproj @@ -72,6 +72,7 @@ Form + diff --git a/Hotkeys.cs b/Hotkeys.cs index e1b39d5..a370893 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -64,10 +64,10 @@ protected override void WndProc(ref Message m) _busyCapturing = true; _worker = new Thread(() => { - if (CtrlAlt) - Thread.Sleep(TimeSpan.FromSeconds(3)); - else if (_settings.DelayCapture) - Thread.Sleep(_settings.DelayCaptureDuration); + if (CtrlAlt) + Thread.Sleep(TimeSpan.FromSeconds(3)); + else + _settings.DelayCaptureDuration.WhenOnThen(Thread.Sleep); try { Screenshot.CaptureWindow(ref info); @@ -92,14 +92,11 @@ private ScreenshotTask GetParamteresFromUI() WindowsApi.GetForegroundWindow(), _settings.UseClipboard, _settings.FolderPath, - _settings.UseResizeDimensions ? _settings.ResizeDimensions : (Size?) null, - _settings.UseOpaqueBackground - ? _settings.OpaqueBackgroundType - : ScreenshotBackgroundType.Transparent, + _settings.ResizeDimensions.Convert(v => (Size?) v), + _settings.OpaqueBackgroundType.GetValueOrDefault(), _settings.SolidBackgroundColor, _settings.CheckerboardBackgroundCheckerSize, - _settings.UseAeroColor, - _settings.AeroColor, + _settings.AeroColor.Convert(v => (Color?) v), _settings.CaputreMouse, _settings.DisableClearType); } diff --git a/Main.cs b/Main.cs index 4818d0a..6b9beb4 100644 --- a/Main.cs +++ b/Main.cs @@ -40,20 +40,20 @@ public MainForm() folderTextBox.Text = _settings.FolderPath; clipboardButton.Checked = _settings.UseClipboard; diskButton.Checked = _settings.UseDisk; - resizeCheckbox.Checked = _settings.UseResizeDimensions; - windowWidth.Value = _settings.ResizeDimensions.Width; - windowHeight.Value = _settings.ResizeDimensions.Height; - opaqueCheckbox.Checked = _settings.UseOpaqueBackground; - opaqueType.SelectedIndex = _settings.OpaqueBackgroundType == ScreenshotBackgroundType.Checkerboard ? 0 - : _settings.OpaqueBackgroundType == ScreenshotBackgroundType.SolidColor ? 1 + resizeCheckbox.Checked = _settings.ResizeDimensions.On; + windowWidth.Value = _settings.ResizeDimensions.Value.Width; + windowHeight.Value = _settings.ResizeDimensions.Value.Height; + opaqueCheckbox.Checked = _settings.OpaqueBackgroundType.On; + opaqueType.SelectedIndex = _settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.Checkerboard ? 0 + : _settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.SolidColor ? 1 : -1; checkerValue.Value = _settings.CheckerboardBackgroundCheckerSize; opaqueColorHexBox.Text = HexColor.Encode(_settings.SolidBackgroundColor); - aeroColorCheckbox.Checked = _settings.UseAeroColor; - aeroColorHexBox.Text = HexColor.Encode(_settings.AeroColor); + aeroColorCheckbox.Checked = _settings.AeroColor.On; + aeroColorHexBox.Text = HexColor.Encode(_settings.AeroColor.Value); mouseCheckbox.Checked = _settings.CaputreMouse; - delayCheckbox.Checked = _settings.DelayCapture; - delaySeconds.Value = (decimal) _settings.DelayCaptureDuration.TotalSeconds; + delayCheckbox.Checked = _settings.DelayCaptureDuration.On; + delaySeconds.Value = (decimal) _settings.DelayCaptureDuration.Value.TotalSeconds; clearTypeCheckbox.Checked = _settings.DisableClearType; if (!GlassAvailable()) diff --git a/Screenshot.cs b/Screenshot.cs index 058b7c2..0de70ec 100644 --- a/Screenshot.cs +++ b/Screenshot.cs @@ -34,8 +34,7 @@ internal struct ScreenshotTask public bool CaptureMouse; public bool DisableClearType; public int CheckerboardSize; - public bool CustomGlass; - public Color AeroColor; + public Color? AeroColor; public bool ClipboardNotDisk; public string DiskSaveDirectory; public Size? Resize; @@ -44,18 +43,17 @@ internal struct ScreenshotTask public ScreenshotTask(IntPtr window, bool clipboard, string file, Size? resize, ScreenshotBackgroundType backType, Color backColor, - int checkerSize, bool customGlass, Color aeroColor, + int checkerSize, Color? aeroColor, bool mouse, bool clearType) { WindowHandle = window; ClipboardNotDisk = clipboard; DiskSaveDirectory = file; - Resize = resize; + Resize = resize.HasValue && resize.Value.IsEmpty ? null : resize; Background = backType; BackgroundColor = backColor; CheckerboardSize = checkerSize; - CustomGlass = customGlass; - AeroColor = aeroColor; + AeroColor = aeroColor.HasValue && aeroColor.Value.IsEmpty ? null : aeroColor; CaptureMouse = mouse; DisableClearType = clearType; } @@ -117,7 +115,7 @@ internal static void CaptureWindow(ref ScreenshotTask data) bool AeroColorToggled = false; WindowsApi.DWM_COLORIZATION_PARAMS originalParameters; WindowsApi.DwmGetColorizationParameters(out originalParameters); - if (data.CustomGlass && AeroEnabled()) + if (data.AeroColor != null && AeroEnabled()) { // Original colorization parameters originalParameters.clrGlassReflectionIntensity = 50; @@ -127,7 +125,7 @@ internal static void CaptureWindow(ref ScreenshotTask data) WindowsApi.DwmGetColorizationParameters(out parameters); parameters.clrAfterGlowBalance = 2; parameters.clrBlurBalance = 29; - parameters.clrColor = ColorToBgra(data.AeroColor); + parameters.clrColor = ColorToBgra(data.AeroColor.Value); parameters.nIntensity = 69; // Call the DwmSetColorizationParameters to make the change take effect. diff --git a/Settings.cs b/Settings.cs index bee1a38..670800c 100644 --- a/Settings.cs +++ b/Settings.cs @@ -16,28 +16,23 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ using System; +using System.Drawing; using Microsoft.Win32; namespace AeroShot { - using System.Drawing; - sealed class Settings { public bool UseDisk; public bool UseClipboard; public string FolderPath; - public bool UseOpaqueBackground; - public ScreenshotBackgroundType OpaqueBackgroundType; + public Switch OpaqueBackgroundType; public Color SolidBackgroundColor; public int CheckerboardBackgroundCheckerSize = 8; - public bool UseAeroColor; - public Color AeroColor; - public bool UseResizeDimensions; - public Size ResizeDimensions = new Size(640, 480); + public Switch AeroColor; + public Switch ResizeDimensions = Switch.Off(new Size(640, 480)); public bool CaputreMouse; - public bool DelayCapture; - public TimeSpan DelayCaptureDuration = TimeSpan.FromSeconds(3); + public Switch DelayCaptureDuration = Switch.Off(TimeSpan.FromSeconds(3)); public bool DisableClearType; private readonly RegistryKey _registryKey; @@ -73,29 +68,30 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - UseResizeDimensions = (b[0] & 1) == 1; + var use = (b[0] & 1) == 1; var width = b[1] << 16 | b[2] << 8 | b[3]; var height = b[4] << 16 | b[5] << 8 | b[6]; - ResizeDimensions = new Size(width, height); + ResizeDimensions = Switch.Create(use, new Size(width, height)); } + var defaultOpaqueBackgroundType = Switch.Off(ScreenshotBackgroundType.Checkerboard); + if ((value = _registryKey.GetValue("Opaque")) != null && value.GetType() == (typeof(long))) { var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - OpaqueBackgroundType = ScreenshotBackgroundType.Transparent; - UseOpaqueBackground = (b[0] & 1) == 1; - if ((b[0] & 2) == 2) - OpaqueBackgroundType = ScreenshotBackgroundType.Checkerboard; - if ((b[0] & 4) == 4) - OpaqueBackgroundType = ScreenshotBackgroundType.SolidColor; + var use = (b[0] & 1) == 1; + var type = (b[0] & 2) == 2 ? ScreenshotBackgroundType.Checkerboard + : (b[0] & 4) == 4 ? ScreenshotBackgroundType.SolidColor + : ScreenshotBackgroundType.Transparent; + OpaqueBackgroundType = Switch.Create(use, type); CheckerboardBackgroundCheckerSize = b[1] + 2; SolidBackgroundColor = Color.FromArgb(b[2], b[3], b[4]); } else - OpaqueBackgroundType = 0; + OpaqueBackgroundType = defaultOpaqueBackgroundType; if ((value = _registryKey.GetValue("AeroColor")) != null && value.GetType() == (typeof(long))) @@ -103,11 +99,11 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - UseAeroColor = (b[0] & 1) == 1; - AeroColor = Color.FromArgb(b[1], b[2], b[3]); + var use = (b[0] & 1) == 1; + AeroColor = Switch.Create(use, Color.FromArgb(b[1], b[2], b[3])); } else - OpaqueBackgroundType = 0; + OpaqueBackgroundType = defaultOpaqueBackgroundType; if ((value = _registryKey.GetValue("CapturePointer")) != null && value.GetType() == (typeof(int))) @@ -123,8 +119,8 @@ public Settings() var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); - DelayCapture = (b[0] & 1) == 1; - DelayCaptureDuration = TimeSpan.FromSeconds(b[1]); + var use = (b[0] & 1) == 1; + DelayCaptureDuration = Switch.Create(use, TimeSpan.FromSeconds(b[1])); } } } diff --git a/Switch.cs b/Switch.cs new file mode 100644 index 0000000..affe9c1 --- /dev/null +++ b/Switch.cs @@ -0,0 +1,47 @@ +/* AeroShot - Transparent screenshot utility for Windows + Copyright (C) 2015 toe_head2001 + Copyright (C) 2012 Caleb Joseph + + AeroShot is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + AeroShot is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +namespace AeroShot +{ + using System; + + static class Switch + { + public static Switch On(T value) { return Create(true, value); } + public static Switch Off(T value) { return Create(false, value); } + public static Switch Create(bool on, T value) { return new Switch(on, value); } + } + + sealed class Switch + { + public bool On { get; private set; } + public T Value { get; private set; } + + public Switch(bool on, T value) { On = on; Value = value; } + + public T GetValueOrDefault() { return On ? Value : default(T); } + + public TResult Convert(Converter onSelector, TResult offValue = default(TResult)) + { + return On ? onSelector(Value) : offValue; + } + + public void WhenOnThen(Action then) { if (On) then(Value); } + + public override string ToString() { return string.Format("{0}", Value); } + } +} \ No newline at end of file From b9c3ceac68750530dc8098b2edad23b800c2283f Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 19:07:21 +0200 Subject: [PATCH 11/31] Moving registry load of settings from ctor to own method --- Hotkeys.cs | 2 +- Main.cs | 2 +- Settings.cs | 56 +++++++++++++++++++++++++++-------------------------- Tray.cs | 2 +- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/Hotkeys.cs b/Hotkeys.cs index a370893..48e47dd 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -55,7 +55,7 @@ protected override void WndProc(ref Message m) if (m.Msg == WM_HOTKEY) { - _settings = new Settings(); + _settings = Settings.LoadSettingsFromRegistry(); if (_busyCapturing) return; diff --git a/Main.cs b/Main.cs index 6b9beb4..63a7b61 100644 --- a/Main.cs +++ b/Main.cs @@ -29,7 +29,7 @@ public sealed partial class MainForm : Form private const uint SPI_GETFONTSMOOTHINGTYPE = 0x200A; private readonly RegistryKey _registryKey; - Settings _settings = new Settings(); + Settings _settings = Settings.LoadSettingsFromRegistry(); public MainForm() { diff --git a/Settings.cs b/Settings.cs index 670800c..d031363 100644 --- a/Settings.cs +++ b/Settings.cs @@ -34,35 +34,35 @@ sealed class Settings public bool CaputreMouse; public Switch DelayCaptureDuration = Switch.Off(TimeSpan.FromSeconds(3)); public bool DisableClearType; - private readonly RegistryKey _registryKey; + public static Settings LoadSettingsFromRegistry() + { + var settings = new Settings(); - public Settings() - { - object value; - _registryKey = Registry.CurrentUser.CreateSubKey(@"Software\AeroShot"); + object value; + var registryKey = Registry.CurrentUser.CreateSubKey(@"Software\AeroShot"); - if ((value = _registryKey.GetValue("LastPath")) != null && + if ((value = registryKey.GetValue("LastPath")) != null && value.GetType() == (typeof(string))) { if (((string)value).Substring(0, 1) == "*") { - FolderPath = ((string)value).Substring(1); - UseClipboard = true; + settings.FolderPath = ((string)value).Substring(1); + settings.UseClipboard = true; } else { - FolderPath = (string)value; - UseDisk = true; + settings.FolderPath = (string)value; + settings.UseDisk = true; } } else { - FolderPath = + settings.FolderPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); } - if ((value = _registryKey.GetValue("WindowSize")) != null && + if ((value = registryKey.GetValue("WindowSize")) != null && value.GetType() == (typeof(long))) { var b = new byte[8]; @@ -71,12 +71,12 @@ public Settings() var use = (b[0] & 1) == 1; var width = b[1] << 16 | b[2] << 8 | b[3]; var height = b[4] << 16 | b[5] << 8 | b[6]; - ResizeDimensions = Switch.Create(use, new Size(width, height)); + settings.ResizeDimensions = Switch.Create(use, new Size(width, height)); } var defaultOpaqueBackgroundType = Switch.Off(ScreenshotBackgroundType.Checkerboard); - if ((value = _registryKey.GetValue("Opaque")) != null && + if ((value = registryKey.GetValue("Opaque")) != null && value.GetType() == (typeof(long))) { var b = new byte[8]; @@ -86,42 +86,44 @@ public Settings() var type = (b[0] & 2) == 2 ? ScreenshotBackgroundType.Checkerboard : (b[0] & 4) == 4 ? ScreenshotBackgroundType.SolidColor : ScreenshotBackgroundType.Transparent; - OpaqueBackgroundType = Switch.Create(use, type); - CheckerboardBackgroundCheckerSize = b[1] + 2; - SolidBackgroundColor = Color.FromArgb(b[2], b[3], b[4]); + settings.OpaqueBackgroundType = Switch.Create(use, type); + settings.CheckerboardBackgroundCheckerSize = b[1] + 2; + settings.SolidBackgroundColor = Color.FromArgb(b[2], b[3], b[4]); } else - OpaqueBackgroundType = defaultOpaqueBackgroundType; + settings.OpaqueBackgroundType = defaultOpaqueBackgroundType; - if ((value = _registryKey.GetValue("AeroColor")) != null && + if ((value = registryKey.GetValue("AeroColor")) != null && value.GetType() == (typeof(long))) { var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); var use = (b[0] & 1) == 1; - AeroColor = Switch.Create(use, Color.FromArgb(b[1], b[2], b[3])); + settings.AeroColor = Switch.Create(use, Color.FromArgb(b[1], b[2], b[3])); } else - OpaqueBackgroundType = defaultOpaqueBackgroundType; + settings.OpaqueBackgroundType = defaultOpaqueBackgroundType; - if ((value = _registryKey.GetValue("CapturePointer")) != null && + if ((value = registryKey.GetValue("CapturePointer")) != null && value.GetType() == (typeof(int))) - CaputreMouse = ((int)value & 1) == 1; + settings.CaputreMouse = ((int)value & 1) == 1; - if ((value = _registryKey.GetValue("ClearType")) != null && + if ((value = registryKey.GetValue("ClearType")) != null && value.GetType() == (typeof(int))) - DisableClearType = ((int)value & 1) == 1; + settings.DisableClearType = ((int)value & 1) == 1; - if ((value = _registryKey.GetValue("Delay")) != null && + if ((value = registryKey.GetValue("Delay")) != null && value.GetType() == (typeof(long))) { var b = new byte[8]; for (int i = 0; i < 8; i++) b[i] = (byte)(((long)value >> (i * 8)) & 0xff); var use = (b[0] & 1) == 1; - DelayCaptureDuration = Switch.Create(use, TimeSpan.FromSeconds(b[1])); + settings.DelayCaptureDuration = Switch.Create(use, TimeSpan.FromSeconds(b[1])); } + + return settings; } } diff --git a/Tray.cs b/Tray.cs index 0e90a72..8d706ae 100644 --- a/Tray.cs +++ b/Tray.cs @@ -27,7 +27,7 @@ public class SysTray : Form MainForm _window = new MainForm(); Hotkeys _hotkeys = new Hotkeys(); - Settings _settings = new Settings(); + Settings _settings = Settings.LoadSettingsFromRegistry(); public SysTray() { From 8b82909b6031c4261222ae5892a68fe463ba8740 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 19:09:28 +0200 Subject: [PATCH 12/31] Eager disposal of registry key is a good thing --- Settings.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Settings.cs b/Settings.cs index d031363..49e8679 100644 --- a/Settings.cs +++ b/Settings.cs @@ -36,11 +36,16 @@ sealed class Settings public bool DisableClearType; public static Settings LoadSettingsFromRegistry() + { + using (var registryKey = Registry.CurrentUser.CreateSubKey(@"Software\AeroShot")) + return LoadSettings(registryKey); + } + + public static Settings LoadSettings(RegistryKey registryKey) { var settings = new Settings(); object value; - var registryKey = Registry.CurrentUser.CreateSubKey(@"Software\AeroShot"); if ((value = registryKey.GetValue("LastPath")) != null && value.GetType() == (typeof(string))) From c9037c9ae8a6e6be031d6f5815c62cfdec843dd8 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 19:11:13 +0200 Subject: [PATCH 13/31] ScreenshotTask is immutable --- Screenshot.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Screenshot.cs b/Screenshot.cs index 0de70ec..c031a21 100644 --- a/Screenshot.cs +++ b/Screenshot.cs @@ -29,16 +29,16 @@ namespace AeroShot { internal struct ScreenshotTask { - public ScreenshotBackgroundType Background; - public Color BackgroundColor; - public bool CaptureMouse; - public bool DisableClearType; - public int CheckerboardSize; - public Color? AeroColor; - public bool ClipboardNotDisk; - public string DiskSaveDirectory; - public Size? Resize; - public IntPtr WindowHandle; + public readonly ScreenshotBackgroundType Background; + public readonly Color BackgroundColor; + public readonly bool CaptureMouse; + public readonly bool DisableClearType; + public readonly int CheckerboardSize; + public readonly Color? AeroColor; + public readonly bool ClipboardNotDisk; + public readonly string DiskSaveDirectory; + public readonly Size? Resize; + public readonly IntPtr WindowHandle; public ScreenshotTask(IntPtr window, bool clipboard, string file, Size? resize, From 3cd936fd21b7ea2aae329796428de81b703d07b4 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Wed, 22 Jul 2015 19:44:46 +0200 Subject: [PATCH 14/31] Moving saving of settings closer to loading --- Main.cs | 81 +++++++++++------------------------------------------ Settings.cs | 75 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 65 deletions(-) diff --git a/Main.cs b/Main.cs index 63a7b61..727d86d 100644 --- a/Main.cs +++ b/Main.cs @@ -28,7 +28,6 @@ public sealed partial class MainForm : Form private const uint SPI_GETFONTSMOOTHING = 0x004A; private const uint SPI_GETFONTSMOOTHINGTYPE = 0x200A; - private readonly RegistryKey _registryKey; Settings _settings = Settings.LoadSettingsFromRegistry(); public MainForm() @@ -74,8 +73,6 @@ public MainForm() delayGroupBox.Enabled = delayCheckbox.Checked; clearTypeGroupBox.Enabled = clearTypeCheckbox.Checked; aeroColorGroupBox.Enabled = aeroColorCheckbox.Checked; - - _registryKey = Registry.CurrentUser.CreateSubKey(@"Software\AeroShot"); } private static bool GlassAvailable() @@ -281,67 +278,23 @@ private void AeroColorTextboxTextChange(object sender, EventArgs e) private void OkButtonClick(object sender, EventArgs e) { - if (clipboardButton.Checked) - _registryKey.SetValue("LastPath", "*" + folderTextBox.Text); - else - _registryKey.SetValue("LastPath", folderTextBox.Text); - - // Save resizing settings in an 8-byte long - var b = new byte[8]; - b[0] = (byte)(resizeCheckbox.Checked ? 1 : 0); - - b[3] = (byte)((int)windowWidth.Value & 0xff); - b[2] = (byte)(((int)windowWidth.Value >> 8) & 0xff); - b[1] = (byte)(((int)windowWidth.Value >> 16) & 0xff); - - b[6] = (byte)((int)windowHeight.Value & 0xff); - b[5] = (byte)(((int)windowHeight.Value >> 8) & 0xff); - b[4] = (byte)(((int)windowHeight.Value >> 16) & 0xff); - - long data = BitConverter.ToInt64(b, 0); - _registryKey.SetValue("WindowSize", data, RegistryValueKind.QWord); - - // Save background color settings in an 8-byte long - b = new byte[8]; - b[0] = (byte)(opaqueCheckbox.Checked ? 1 : 0); - b[0] += (byte)Math.Pow(2, opaqueType.SelectedIndex + 1); - - b[1] = (byte)(checkerValue.Value - 2); - - b[2] = opaqueColorDialog.Color.R; - b[3] = opaqueColorDialog.Color.G; - b[4] = opaqueColorDialog.Color.B; - - data = BitConverter.ToInt64(b, 0); - _registryKey.SetValue("Opaque", data, RegistryValueKind.QWord); - - // Save background color settings in an 8-byte long - b = new byte[8]; - b[0] = (byte)(aeroColorCheckbox.Checked ? 1 : 0); - - b[1] = aeroColorDialog.Color.R; - b[2] = aeroColorDialog.Color.G; - b[3] = aeroColorDialog.Color.B; - - data = BitConverter.ToInt64(b, 0); - _registryKey.SetValue("AeroColor", data, RegistryValueKind.QWord); - - _registryKey.SetValue("CapturePointer", - mouseCheckbox.Checked ? 1 : 0, - RegistryValueKind.DWord); - - _registryKey.SetValue("ClearType", - clearTypeCheckbox.Checked ? 1 : 0, - RegistryValueKind.DWord); - - // Save delay settings in an 8-byte long - b = new byte[8]; - b[0] = (byte)(delayCheckbox.Checked ? 1 : 0); - - b[1] = (byte)(((int)delaySeconds.Value) & 0xff); - - data = BitConverter.ToInt64(b, 0); - _registryKey.SetValue("Delay", data, RegistryValueKind.QWord); + Settings.SaveSettingsToRegistry(new Settings + { + UseClipboard = clipboardButton.Checked, + FolderPath = folderTextBox.Text, + ResizeDimensions = Switch.Create(resizeCheckbox.Checked, + new Size((int) windowWidth.Value, + (int) windowHeight.Value)), + OpaqueBackgroundType = Switch.Create(opaqueCheckbox.Checked, + opaqueType.SelectedIndex == 1 + ? ScreenshotBackgroundType.SolidColor + : ScreenshotBackgroundType.Checkerboard), + SolidBackgroundColor = opaqueColorDialog.Color, + AeroColor = Switch.Create(aeroColorCheckbox.Checked, aeroColorDialog.Color), + CaputreMouse = mouseCheckbox.Checked, + DisableClearType = clearTypeCheckbox.Checked, + DelayCaptureDuration = Switch.Create(delayCheckbox.Checked, TimeSpan.FromSeconds((int) delaySeconds.Value)), + }); this.Close(); } diff --git a/Settings.cs b/Settings.cs index 49e8679..edb7ba2 100644 --- a/Settings.cs +++ b/Settings.cs @@ -35,9 +35,14 @@ sealed class Settings public Switch DelayCaptureDuration = Switch.Off(TimeSpan.FromSeconds(3)); public bool DisableClearType; + static RegistryKey CreateRegistryKey() + { + return Registry.CurrentUser.CreateSubKey(@"Software\AeroShot"); + } + public static Settings LoadSettingsFromRegistry() { - using (var registryKey = Registry.CurrentUser.CreateSubKey(@"Software\AeroShot")) + using (var registryKey = CreateRegistryKey()) return LoadSettings(registryKey); } @@ -130,6 +135,74 @@ public static Settings LoadSettings(RegistryKey registryKey) return settings; } + + public static void SaveSettingsToRegistry(Settings settings) + { + using (var registryKey = CreateRegistryKey()) + SaveSettings(settings, registryKey); + } + + public static void SaveSettings(Settings settings, RegistryKey registryKey) + { + registryKey.SetValue("LastPath", (settings.UseClipboard ? "*" : null) + settings.FolderPath); + + // Save resizing settings in an 8-byte long + var b = new byte[8]; + b[0] = settings.ResizeDimensions.Convert(_ => (byte) 1); + + var x = settings.ResizeDimensions.Value.Width; + b[3] = (byte)(x & 0xff); + b[2] = (byte)((x >> 8) & 0xff); + b[1] = (byte)((x >> 16) & 0xff); + + var y = settings.ResizeDimensions.Value.Height; + b[6] = (byte)(y & 0xff); + b[5] = (byte)((y >> 8) & 0xff); + b[4] = (byte)((y >> 16) & 0xff); + + var data = BitConverter.ToInt64(b, 0); + registryKey.SetValue("WindowSize", data, RegistryValueKind.QWord); + + // Save background color settings in an 8-byte long + b = new byte[8]; + b[0] = settings.OpaqueBackgroundType.Convert(_ => (byte) 1); + b[0] += (byte)Math.Pow(2, settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.SolidColor ? 2 : 1); + + b[1] = (byte)(settings.CheckerboardBackgroundCheckerSize - 2); + + b[2] = settings.SolidBackgroundColor.R; + b[3] = settings.SolidBackgroundColor.G; + b[4] = settings.SolidBackgroundColor.B; + + data = BitConverter.ToInt64(b, 0); + registryKey.SetValue("Opaque", data, RegistryValueKind.QWord); + + // Save background color settings in an 8-byte long + b = new byte[8]; + b[0] = settings.AeroColor.Convert(_ => (byte) 1); + + b[1] = settings.AeroColor.Value.R; + b[2] = settings.AeroColor.Value.G; + b[3] = settings.AeroColor.Value.B; + + data = BitConverter.ToInt64(b, 0); + registryKey.SetValue("AeroColor", data, RegistryValueKind.QWord); + + registryKey.SetValue("CapturePointer", settings.CaputreMouse ? 1 : 0, + RegistryValueKind.DWord); + + registryKey.SetValue("ClearType", settings.DisableClearType ? 1 : 0, + RegistryValueKind.DWord); + + // Save delay settings in an 8-byte long + b = new byte[8]; + b[0] = settings.DelayCaptureDuration.Convert(_ => (byte) 1); + + b[1] = (byte)(((int) settings.DelayCaptureDuration.Value.TotalSeconds) & 0xff); + + data = BitConverter.ToInt64(b, 0); + registryKey.SetValue("Delay", data, RegistryValueKind.QWord); + } } static class HexColor From d680d19ebf030eab021087a4b707bf18efeddb68 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Thu, 23 Jul 2015 01:17:42 +0200 Subject: [PATCH 15/31] Fix for uninitialized Settings fields --- Settings.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Settings.cs b/Settings.cs index edb7ba2..9032ae7 100644 --- a/Settings.cs +++ b/Settings.cs @@ -26,10 +26,10 @@ sealed class Settings public bool UseDisk; public bool UseClipboard; public string FolderPath; - public Switch OpaqueBackgroundType; + public Switch OpaqueBackgroundType = Switch.Off(ScreenshotBackgroundType.Checkerboard); public Color SolidBackgroundColor; public int CheckerboardBackgroundCheckerSize = 8; - public Switch AeroColor; + public Switch AeroColor = Switch.Off(Color.White); public Switch ResizeDimensions = Switch.Off(new Size(640, 480)); public bool CaputreMouse; public Switch DelayCaptureDuration = Switch.Off(TimeSpan.FromSeconds(3)); From c639a2362ace5f3de9cf22759f015ea2a592c0f1 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Thu, 23 Jul 2015 18:03:17 +0200 Subject: [PATCH 16/31] Save & load of settings to & from INI file --- .gitignore | 1 + AeroShot.csproj | 5 + App_Packages/Gini/Ini.cs | 391 +++++ Hotkeys.cs | 2 +- LinqBridge.cs | 3100 ++++++++++++++++++++++++++++++++++++++ Main.cs | 5 +- Settings.cs | 216 ++- Tray.cs | 2 +- packages.config | 5 + 9 files changed, 3718 insertions(+), 9 deletions(-) create mode 100644 App_Packages/Gini/Ini.cs create mode 100644 LinqBridge.cs create mode 100644 packages.config diff --git a/.gitignore b/.gitignore index 0a37a27..6a528ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ bin/ obj/ +packages/ *.userprefs *.suo \ No newline at end of file diff --git a/AeroShot.csproj b/AeroShot.csproj index 4115ee9..70bbbcf 100644 --- a/AeroShot.csproj +++ b/AeroShot.csproj @@ -56,9 +56,11 @@ AnyCPU + Form + Form @@ -96,5 +98,8 @@ true + + + \ No newline at end of file diff --git a/App_Packages/Gini/Ini.cs b/App_Packages/Gini/Ini.cs new file mode 100644 index 0000000..67241dd --- /dev/null +++ b/App_Packages/Gini/Ini.cs @@ -0,0 +1,391 @@ +#region The MIT License (MIT) +// +// Copyright (c) 2013 Atif Aziz. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#endregion + +namespace Gini +{ + #region Imports + + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Diagnostics; + using System.Linq; + using System.Text.RegularExpressions; + + #endregion + + #if GINI_PUBLIC + public partial class Ini { } + #endif + + static partial class Ini + { + static class Parser + { + static readonly Regex Regex; + static readonly int SectionNumber; + static readonly int KeyNumber; + static readonly int ValueNumber; + + static Parser() + { + var re = Regex = + new Regex(@"^ *(\[(?[a-z0-9-._][a-z0-9-._ ]*)\]|(?[a-z0-9-._][a-z0-9-._ ]*)= *(?[^\r\n]*))\s*$", + RegexOptions.Multiline + | RegexOptions.IgnoreCase + | RegexOptions.CultureInvariant); + SectionNumber = re.GroupNumberFromName("s"); + KeyNumber = re.GroupNumberFromName("k"); + ValueNumber = re.GroupNumberFromName("v"); + } + + // ReSharper disable once MemberHidesStaticFromOuterClass + public static IEnumerable Parse(string ini, Func selector) + { + return from Match m in Regex.Matches(ini ?? string.Empty) + select m.Groups into g + select selector(g[SectionNumber].Value.TrimEnd(), + g[KeyNumber].Value.TrimEnd(), + g[ValueNumber].Value.TrimEnd()); + } + } + + public static IEnumerable>> Parse(string ini) + { + return Parse(ini, KeyValuePair.Create); + } + + public static IEnumerable> Parse(string ini, Func settingSelector) + { + return Parse(ini, (_, k, v) => settingSelector(k, v)); + } + + public static IEnumerable> Parse(string ini, Func settingSelector) + { + if (settingSelector == null) throw new ArgumentNullException("settingSelector"); + + ini = ini.Trim(); + if (string.IsNullOrEmpty(ini)) + return Enumerable.Empty>(); + + var entries = + from ms in new[] + { + Parser.Parse(ini, (s, k, v) => new + { + Section = s, + Setting = KeyValuePair.Create(k, v) + }) + } + from p in Enumerable.Repeat(new { Section = (string) null, + Setting = KeyValuePair.Create(string.Empty, string.Empty) }, 1) + .Concat(ms) + .GroupAdjacent(s => s.Section == null || s.Section.Length > 0) + .Pairwise((prev, curr) => new { Prev = prev, Curr = curr }) + where p.Prev.Key + select KeyValuePair.Create(p.Prev.Last().Section, p.Curr) into e + from s in e.Value + select KeyValuePair.Create(e.Key, settingSelector(e.Key, s.Setting.Key, s.Setting.Value)); + + return entries.GroupAdjacent(e => e.Key, e => e.Value); + } + + public static IDictionary> ParseHash(string ini) + { + return ParseHash(ini, null); + } + + public static IDictionary> ParseHash(string ini, IEqualityComparer comparer) + { + comparer = comparer ?? StringComparer.OrdinalIgnoreCase; + var sections = Parse(ini); + return sections.GroupBy(g => g.Key ?? string.Empty, comparer) + .ToDictionary(g => g.Key, + g => (IDictionary) g.SelectMany(e => e) + .GroupBy(e => e.Key, comparer) + .ToDictionary(e => e.Key, e => e.Last().Value, comparer), + comparer); + } + + public static IDictionary ParseFlatHash(string ini, Func keyMerger) + { + return ParseFlatHash(ini, keyMerger, null); + } + + public static IDictionary ParseFlatHash(string ini, Func keyMerger, IEqualityComparer comparer) + { + if (keyMerger == null) throw new ArgumentNullException("keyMerger"); + + var settings = new Dictionary(comparer ?? StringComparer.OrdinalIgnoreCase); + foreach (var setting in from section in Parse(ini) + from setting in section + select KeyValuePair.Create(keyMerger(section.Key, setting.Key), setting.Value)) + { + settings[setting.Key] = setting.Value; + } + return settings; + } + + static class KeyValuePair + { + public static KeyValuePair Create(TKey key, TValue value) + { + return new KeyValuePair(key, value); + } + } + + #region MoreLINQ + + // MoreLINQ - Extensions to LINQ to Objects + // Copyright (c) 2008 Jonathan Skeet. All rights reserved. + // + // Licensed under the Apache License, Version 2.0 (the "License"); + // you may not use this file except in compliance with the License. + // You may obtain a copy of the License at + // + // http://www.apache.org/licenses/LICENSE-2.0 + // + // Unless required by applicable law or agreed to in writing, software + // distributed under the License is distributed on an "AS IS" BASIS, + // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + // See the License for the specific language governing permissions and + // limitations under the License. + + static IEnumerable Pairwise(this IEnumerable source, Func resultSelector) + { + if (source == null) throw new ArgumentNullException("source"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + return PairwiseImpl(source, resultSelector); + } + + static IEnumerable PairwiseImpl(this IEnumerable source, Func resultSelector) + { + Debug.Assert(source != null); + Debug.Assert(resultSelector != null); + + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + yield break; + + var previous = e.Current; + while (e.MoveNext()) + { + yield return resultSelector(previous, e.Current); + previous = e.Current; + } + } + } + + static IEnumerable> GroupAdjacent( + this IEnumerable source, + Func keySelector) + { + // ReSharper disable once IntroduceOptionalParameters.Local + return GroupAdjacent(source, keySelector, null); + } + + static IEnumerable> GroupAdjacent( + this IEnumerable source, + Func keySelector, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + + return GroupAdjacent(source, keySelector, e => e, comparer); + } + + static IEnumerable> GroupAdjacent( + this IEnumerable source, + Func keySelector, + Func elementSelector) + { + // ReSharper disable once IntroduceOptionalParameters.Local + return GroupAdjacent(source, keySelector, elementSelector, null); + } + + static IEnumerable> GroupAdjacent( + this IEnumerable source, + Func keySelector, + Func elementSelector, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + if (elementSelector == null) throw new ArgumentNullException("elementSelector"); + + return GroupAdjacentImpl(source, keySelector, elementSelector, + comparer ?? EqualityComparer.Default); + } + + static IEnumerable> GroupAdjacentImpl( + this IEnumerable source, + Func keySelector, + Func elementSelector, + IEqualityComparer comparer) + { + Debug.Assert(source != null); + Debug.Assert(keySelector != null); + Debug.Assert(elementSelector != null); + Debug.Assert(comparer != null); + + using (var iterator = source.Select(item => KeyValuePair.Create(keySelector(item), elementSelector(item))) + .GetEnumerator()) + { + var group = default(TKey); + var members = (List) null; + + while (iterator.MoveNext()) + { + var item = iterator.Current; + if (members != null && comparer.Equals(group, item.Key)) + { + members.Add(item.Value); + } + else + { + if (members != null) + yield return CreateGroupAdjacentGrouping(group, members); + group = item.Key; + members = new List { item.Value }; + } + } + + if (members != null) + yield return CreateGroupAdjacentGrouping(group, members); + } + } + + static Grouping CreateGroupAdjacentGrouping(TKey key, IList members) + { + Debug.Assert(members != null); + return new Grouping(key, members.IsReadOnly ? members : new ReadOnlyCollection(members)); + } + + sealed class Grouping : IGrouping + { + readonly IEnumerable _members; + + public Grouping(TKey key, IEnumerable members) + { + Debug.Assert(members != null); + Key = key; + _members = members; + } + + public TKey Key { get; private set; } + + public IEnumerator GetEnumerator() { return _members.GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } + } + + #endregion + } +} + +#if GINI_DYNAMIC + +namespace Gini +{ + #region Imports + + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Dynamic; + using System.Globalization; + using System.Linq; + + #endregion + + static partial class Ini + { + public static dynamic ParseObject(string ini) + { + return ParseObject(ini, null); + } + + public static dynamic ParseObject(string ini, IEqualityComparer comparer) + { + comparer = comparer ?? StringComparer.OrdinalIgnoreCase; + var config = new Dictionary>(comparer); + foreach (var section in from g in Parse(ini).GroupBy(e => e.Key ?? string.Empty, comparer) + select KeyValuePair.Create(g.Key, g.SelectMany(e => e))) + { + var settings = new Dictionary(comparer); + foreach (var setting in section.Value) + settings[setting.Key] = setting.Value; + config[section.Key] = new Config(settings); + } + return new Config>(config); + } + + public static dynamic ParseFlatObject(string ini, Func keyMerger) + { + return ParseFlatObject(ini, keyMerger, null); + } + + public static dynamic ParseFlatObject(string ini, Func keyMerger, IEqualityComparer comparer) + { + if (keyMerger == null) throw new ArgumentNullException("keyMerger"); + return new Config(ParseFlatHash(ini, keyMerger, comparer)); + } + + sealed class Config : DynamicObject + { + readonly IDictionary _entries; + + public Config(IDictionary entries) + { + Debug.Assert(entries != null); + _entries = entries; + } + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + if (binder == null) throw new ArgumentNullException("binder"); + result = Find(binder.Name); + return true; + } + + public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) + { + if (indexes == null) throw new ArgumentNullException("indexes"); + if (indexes.Length != 1) throw new ArgumentException("Too many indexes supplied."); + var index = indexes[0]; + result = Find(index == null ? null : Convert.ToString(index, CultureInfo.InvariantCulture)); + return true; + } + + object Find(string name) + { + T value; + return _entries.TryGetValue(name, out value) ? value : default(T); + } + } + } +} + +#endif diff --git a/Hotkeys.cs b/Hotkeys.cs index 48e47dd..4f310e0 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -55,7 +55,7 @@ protected override void WndProc(ref Message m) if (m.Msg == WM_HOTKEY) { - _settings = Settings.LoadSettingsFromRegistry(); + _settings = Settings.LoadSettings(); if (_busyCapturing) return; diff --git a/LinqBridge.cs b/LinqBridge.cs new file mode 100644 index 0000000..3f19511 --- /dev/null +++ b/LinqBridge.cs @@ -0,0 +1,3100 @@ +#region License, Terms and Author(s) +// +// LINQBridge +// Copyright (c) 2007 Atif Aziz, Joseph Albahari. All rights reserved. +// +// Author(s): +// +// Atif Aziz, http://www.raboof.com +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the New BSD License, a copy of which should have +// been delivered along with this distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +#endregion + +// $Id: Enumerable.cs c08984d432b1 2012/04/17 16:05:19 azizatif $ + +namespace System.Linq +{ + #region Imports + + using System; + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics; + using LinqBridge; + + #endregion + + /// + /// Provides a set of static (Shared in Visual Basic) methods for + /// querying objects that implement . + /// + + static partial class Enumerable + { + /// + /// Returns the input typed as . + /// + + public static IEnumerable AsEnumerable(this IEnumerable source) + { + return source; + } + + /// + /// Returns an empty that has the + /// specified type argument. + /// + + public static IEnumerable Empty() + { + return Sequence.Empty; + } + + /// + /// Converts the elements of an to the + /// specified type. + /// + + public static IEnumerable Cast( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return CastYield(source); + } + + private static IEnumerable CastYield( + IEnumerable source) + { + foreach (var item in source) + yield return (TResult) item; + } + + /// + /// Filters the elements of an based on a specified type. + /// + + public static IEnumerable OfType( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return OfTypeYield(source); + } + + private static IEnumerable OfTypeYield( + IEnumerable source) + { + foreach (var item in source) + if (item is TResult) + yield return (TResult) item; + } + + /// + /// Generates a sequence of integral numbers within a specified range. + /// + /// The value of the first integer in the sequence. + /// The number of sequential integers to generate. + + public static IEnumerable Range(int start, int count) + { + if (count < 0) + throw new ArgumentOutOfRangeException("count", count, null); + + var end = (long) start + count; + if (end - 1 >= int.MaxValue) + throw new ArgumentOutOfRangeException("count", count, null); + + return RangeYield(start, end); + } + + private static IEnumerable RangeYield(int start, long end) + { + for (var i = start; i < end; i++) + yield return i; + } + + /// + /// Generates a sequence that contains one repeated value. + /// + + public static IEnumerable Repeat(TResult element, int count) + { + if (count < 0) throw new ArgumentOutOfRangeException("count", count, null); + + return RepeatYield(element, count); + } + + private static IEnumerable RepeatYield(TResult element, int count) + { + for (var i = 0; i < count; i++) + yield return element; + } + + /// + /// Filters a sequence of values based on a predicate. + /// + + public static IEnumerable Where( + this IEnumerable source, + Func predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + + return source.Where((item, i) => predicate(item)); + } + + /// + /// Filters a sequence of values based on a predicate. + /// Each element's index is used in the logic of the predicate function. + /// + + public static IEnumerable Where( + this IEnumerable source, + Func predicate) + { + if (source == null) throw new ArgumentNullException("source"); + if (predicate == null) throw new ArgumentNullException("predicate"); + + return WhereYield(source, predicate); + } + + private static IEnumerable WhereYield( + IEnumerable source, + Func predicate) + { + var i = 0; + foreach (var item in source) + if (predicate(item, i++)) + yield return item; + } + + /// + /// Projects each element of a sequence into a new form. + /// + + public static IEnumerable Select( + this IEnumerable source, + Func selector) + { + if (selector == null) throw new ArgumentNullException("selector"); + + return source.Select((item, i) => selector(item)); + } + + /// + /// Projects each element of a sequence into a new form by + /// incorporating the element's index. + /// + + public static IEnumerable Select( + this IEnumerable source, + Func selector) + { + if (source == null) throw new ArgumentNullException("source"); + if (selector == null) throw new ArgumentNullException("selector"); + + return SelectYield(source, selector); + } + + private static IEnumerable SelectYield( + IEnumerable source, + Func selector) + { + var i = 0; + foreach (var item in source) + yield return selector(item, i++); + } + + /// + /// Projects each element of a sequence to an + /// and flattens the resulting sequences into one sequence. + /// + + public static IEnumerable SelectMany( + this IEnumerable source, + Func> selector) + { + if (selector == null) throw new ArgumentNullException("selector"); + + return source.SelectMany((item, i) => selector(item)); + } + + /// + /// Projects each element of a sequence to an , + /// and flattens the resulting sequences into one sequence. The + /// index of each source element is used in the projected form of + /// that element. + /// + + public static IEnumerable SelectMany( + this IEnumerable source, + Func> selector) + { + if (selector == null) throw new ArgumentNullException("selector"); + + return source.SelectMany(selector, (item, subitem) => subitem); + } + + /// + /// Projects each element of a sequence to an , + /// flattens the resulting sequences into one sequence, and invokes + /// a result selector function on each element therein. + /// + + public static IEnumerable SelectMany( + this IEnumerable source, + Func> collectionSelector, + Func resultSelector) + { + if (collectionSelector == null) throw new ArgumentNullException("collectionSelector"); + + return source.SelectMany((item, i) => collectionSelector(item), resultSelector); + } + + /// + /// Projects each element of a sequence to an , + /// flattens the resulting sequences into one sequence, and invokes + /// a result selector function on each element therein. The index of + /// each source element is used in the intermediate projected form + /// of that element. + /// + + public static IEnumerable SelectMany( + this IEnumerable source, + Func> collectionSelector, + Func resultSelector) + { + if (source == null) throw new ArgumentNullException("source"); + if (collectionSelector == null) throw new ArgumentNullException("collectionSelector"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + + return SelectManyYield(source, collectionSelector, resultSelector); + } + + private static IEnumerable SelectManyYield( + this IEnumerable source, + Func> collectionSelector, + Func resultSelector) + { + var i = 0; + foreach (var item in source) + foreach (var subitem in collectionSelector(item, i++)) + yield return resultSelector(item, subitem); + } + + /// + /// Returns elements from a sequence as long as a specified condition is true. + /// + + public static IEnumerable TakeWhile( + this IEnumerable source, + Func predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + + return source.TakeWhile((item, i) => predicate(item)); + } + + /// + /// Returns elements from a sequence as long as a specified condition is true. + /// The element's index is used in the logic of the predicate function. + /// + + public static IEnumerable TakeWhile( + this IEnumerable source, + Func predicate) + { + if (source == null) throw new ArgumentNullException("source"); + if (predicate == null) throw new ArgumentNullException("predicate"); + + return TakeWhileYield(source, predicate); + } + + private static IEnumerable TakeWhileYield( + this IEnumerable source, + Func predicate) + { + var i = 0; + foreach (var item in source) + if (predicate(item, i++)) + yield return item; + else + break; + } + + /// + /// Returns a specified number of contiguous elements from the start + /// of a sequence. + /// + + public static IEnumerable Take( + this IEnumerable source, + int count) + { + return source.TakeWhile((item, i) => i < count); + } + + private static class Futures + { + public static readonly Func Default = () => default(T); + public static readonly Func Undefined = () => { throw new InvalidOperationException(); }; + } + + /// + /// Base implementation of First operator. + /// + + private static TSource FirstImpl( + this IEnumerable source, + Func empty) + { + if (source == null) throw new ArgumentNullException("source"); + Debug.Assert(empty != null); + + var list = source as IList; // optimized case for lists + if (list != null) + return list.Count > 0 ? list[0] : empty(); + + using (var e = source.GetEnumerator()) // fallback for enumeration + return e.MoveNext() ? e.Current : empty(); + } + + /// + /// Returns the first element of a sequence. + /// + + public static TSource First( + this IEnumerable source) + { + return source.FirstImpl(Futures.Undefined); + } + + /// + /// Returns the first element in a sequence that satisfies a specified condition. + /// + + public static TSource First( + this IEnumerable source, + Func predicate) + { + return First(source.Where(predicate)); + } + + /// + /// Returns the first element of a sequence, or a default value if + /// the sequence contains no elements. + /// + + public static TSource FirstOrDefault( + this IEnumerable source) + { + return source.FirstImpl(Futures.Default); + } + + /// + /// Returns the first element of the sequence that satisfies a + /// condition or a default value if no such element is found. + /// + + public static TSource FirstOrDefault( + this IEnumerable source, + Func predicate) + { + return FirstOrDefault(source.Where(predicate)); + } + + /// + /// Base implementation of Last operator. + /// + + private static TSource LastImpl( + this IEnumerable source, + Func empty) + { + if (source == null) throw new ArgumentNullException("source"); + + var list = source as IList; // optimized case for lists + if (list != null) + return list.Count > 0 ? list[list.Count - 1] : empty(); + + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + return empty(); + + var last = e.Current; + while (e.MoveNext()) + last = e.Current; + + return last; + } + } + + /// + /// Returns the last element of a sequence. + /// + public static TSource Last( + this IEnumerable source) + { + return source.LastImpl(Futures.Undefined); + } + + /// + /// Returns the last element of a sequence that satisfies a + /// specified condition. + /// + + public static TSource Last( + this IEnumerable source, + Func predicate) + { + return Last(source.Where(predicate)); + } + + /// + /// Returns the last element of a sequence, or a default value if + /// the sequence contains no elements. + /// + + public static TSource LastOrDefault( + this IEnumerable source) + { + return source.LastImpl(Futures.Default); + } + + /// + /// Returns the last element of a sequence that satisfies a + /// condition or a default value if no such element is found. + /// + + public static TSource LastOrDefault( + this IEnumerable source, + Func predicate) + { + return LastOrDefault(source.Where(predicate)); + } + + /// + /// Base implementation of Single operator. + /// + + private static TSource SingleImpl( + this IEnumerable source, + Func empty) + { + if (source == null) throw new ArgumentNullException("source"); + + using (var e = source.GetEnumerator()) + { + if (e.MoveNext()) + { + var single = e.Current; + if (!e.MoveNext()) + return single; + + throw new InvalidOperationException(); + } + + return empty(); + } + } + + /// + /// Returns the only element of a sequence, and throws an exception + /// if there is not exactly one element in the sequence. + /// + + public static TSource Single( + this IEnumerable source) + { + return source.SingleImpl(Futures.Undefined); + } + + /// + /// Returns the only element of a sequence that satisfies a + /// specified condition, and throws an exception if more than one + /// such element exists. + /// + + public static TSource Single( + this IEnumerable source, + Func predicate) + { + return Single(source.Where(predicate)); + } + + /// + /// Returns the only element of a sequence, or a default value if + /// the sequence is empty; this method throws an exception if there + /// is more than one element in the sequence. + /// + + public static TSource SingleOrDefault( + this IEnumerable source) + { + return source.SingleImpl(Futures.Default); + } + + /// + /// Returns the only element of a sequence that satisfies a + /// specified condition or a default value if no such element + /// exists; this method throws an exception if more than one element + /// satisfies the condition. + /// + + public static TSource SingleOrDefault( + this IEnumerable source, + Func predicate) + { + return SingleOrDefault(source.Where(predicate)); + } + + /// + /// Returns the element at a specified index in a sequence. + /// + + public static TSource ElementAt( + this IEnumerable source, + int index) + { + if (source == null) throw new ArgumentNullException("source"); + + if (index < 0) + throw new ArgumentOutOfRangeException("index", index, null); + + var list = source as IList; + if (list != null) + return list[index]; + + try + { + return source.SkipWhile((item, i) => i < index).First(); + } + catch (InvalidOperationException) // if thrown by First + { + throw new ArgumentOutOfRangeException("index", index, null); + } + } + + /// + /// Returns the element at a specified index in a sequence or a + /// default value if the index is out of range. + /// + + public static TSource ElementAtOrDefault( + this IEnumerable source, + int index) + { + if (source == null) throw new ArgumentNullException("source"); + + if (index < 0) + return default(TSource); + + var list = source as IList; + if (list != null) + return index < list.Count ? list[index] : default(TSource); + + return source.SkipWhile((item, i) => i < index).FirstOrDefault(); + } + + /// + /// Inverts the order of the elements in a sequence. + /// + + public static IEnumerable Reverse( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return ReverseYield(source); + } + + private static IEnumerable ReverseYield(IEnumerable source) + { + var stack = new Stack(); + foreach (var item in source) + stack.Push(item); + + foreach (var item in stack) + yield return item; + } + + /// + /// Bypasses elements in a sequence as long as a specified condition + /// is true and then returns the remaining elements. + /// + + public static IEnumerable SkipWhile( + this IEnumerable source, + Func predicate) + { + if (predicate == null) throw new ArgumentNullException("predicate"); + + return source.SkipWhile((item, i) => predicate(item)); + } + + /// + /// Bypasses elements in a sequence as long as a specified condition + /// is true and then returns the remaining elements. The element's + /// index is used in the logic of the predicate function. + /// + + public static IEnumerable SkipWhile( + this IEnumerable source, + Func predicate) + { + if (source == null) throw new ArgumentNullException("source"); + if (predicate == null) throw new ArgumentNullException("predicate"); + + return SkipWhileYield(source, predicate); + } + + private static IEnumerable SkipWhileYield( + IEnumerable source, + Func predicate) + { + using (var e = source.GetEnumerator()) + { + for (var i = 0; ; i++) + { + if (!e.MoveNext()) + yield break; + + if (!predicate(e.Current, i)) + break; + } + + do { yield return e.Current; } while (e.MoveNext()); + } + } + + /// + /// Bypasses a specified number of elements in a sequence and then + /// returns the remaining elements. + /// + + public static IEnumerable Skip( + this IEnumerable source, + int count) + { + return source.SkipWhile((item, i) => i < count); + } + + /// + /// Returns the number of elements in a sequence. + /// + + public static int Count( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + var collection = source as ICollection; + return collection != null + ? collection.Count + : source.Aggregate(0, (count, item) => checked(count + 1)); + } + + /// + /// Returns a number that represents how many elements in the + /// specified sequence satisfy a condition. + /// + + public static int Count( + this IEnumerable source, + Func predicate) + { + return Count(source.Where(predicate)); + } + + /// + /// Returns an that represents the total number + /// of elements in a sequence. + /// + + public static long LongCount( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + var array = source as Array; + return array != null + ? array.LongLength + : source.Aggregate(0L, (count, item) => count + 1); + } + + /// + /// Returns an that represents how many elements + /// in a sequence satisfy a condition. + /// + + public static long LongCount( + this IEnumerable source, + Func predicate) + { + return LongCount(source.Where(predicate)); + } + + /// + /// Concatenates two sequences. + /// + + public static IEnumerable Concat( + this IEnumerable first, + IEnumerable second) + { + if (first == null) throw new ArgumentNullException("first"); + if (second == null) throw new ArgumentNullException("second"); + + return ConcatYield(first, second); + } + + private static IEnumerable ConcatYield( + IEnumerable first, + IEnumerable second) + { + foreach (var item in first) + yield return item; + + foreach (var item in second) + yield return item; + } + + /// + /// Creates a from an . + /// + + public static List ToList( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return new List(source); + } + + /// + /// Creates an array from an . + /// + + public static TSource[] ToArray( + this IEnumerable source) + { + return source.ToList().ToArray(); + } + + /// + /// Returns distinct elements from a sequence by using the default + /// equality comparer to compare values. + /// + + public static IEnumerable Distinct( + this IEnumerable source) + { + return Distinct(source, /* comparer */ null); + } + + /// + /// Returns distinct elements from a sequence by using a specified + /// to compare values. + /// + + public static IEnumerable Distinct( + this IEnumerable source, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + + return DistinctYield(source, comparer); + } + + private static IEnumerable DistinctYield( + IEnumerable source, + IEqualityComparer comparer) + { + var set = new Dictionary(comparer); + var gotNull = false; + + foreach (var item in source) + { + if (item == null) + { + if (gotNull) + continue; + gotNull = true; + } + else + { + if (set.ContainsKey(item)) + continue; + set.Add(item, null); + } + + yield return item; + } + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function. + /// + + public static ILookup ToLookup( + this IEnumerable source, + Func keySelector) + { + return ToLookup(source, keySelector, e => e, /* comparer */ null); + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function and a key comparer. + /// + + public static ILookup ToLookup( + this IEnumerable source, + Func keySelector, + IEqualityComparer comparer) + { + return ToLookup(source, keySelector, e => e, comparer); + } + + /// + /// Creates a from an + /// according to specified key + /// and element selector functions. + /// + + public static ILookup ToLookup( + this IEnumerable source, + Func keySelector, + Func elementSelector) + { + return ToLookup(source, keySelector, elementSelector, /* comparer */ null); + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function, a comparer and an element selector function. + /// + + public static ILookup ToLookup( + this IEnumerable source, + Func keySelector, + Func elementSelector, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + if (elementSelector == null) throw new ArgumentNullException("elementSelector"); + + var lookup = new Lookup(comparer); + + foreach (var item in source) + { + var key = keySelector(item); + + var grouping = (Grouping) lookup.Find(key); + if (grouping == null) + { + grouping = new Grouping(key); + lookup.Add(grouping); + } + + grouping.Add(elementSelector(item)); + } + + return lookup; + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function. + /// + + public static IEnumerable> GroupBy( + this IEnumerable source, + Func keySelector) + { + return GroupBy(source, keySelector, /* comparer */ null); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and compares the keys by using a specified + /// comparer. + /// + + public static IEnumerable> GroupBy( + this IEnumerable source, + Func keySelector, + IEqualityComparer comparer) + { + return GroupBy(source, keySelector, e => e, comparer); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and projects the elements for each group by + /// using a specified function. + /// + + public static IEnumerable> GroupBy( + this IEnumerable source, + Func keySelector, + Func elementSelector) + { + return GroupBy(source, keySelector, elementSelector, /* comparer */ null); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and creates a result value from each group and + /// its key. + /// + + public static IEnumerable> GroupBy( + this IEnumerable source, + Func keySelector, + Func elementSelector, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + if (elementSelector == null) throw new ArgumentNullException("elementSelector"); + + return ToLookup(source, keySelector, elementSelector, comparer); + } + + /// + /// Groups the elements of a sequence according to a key selector + /// function. The keys are compared by using a comparer and each + /// group's elements are projected by using a specified function. + /// + + public static IEnumerable GroupBy( + this IEnumerable source, + Func keySelector, + Func, TResult> resultSelector) + { + return GroupBy(source, keySelector, resultSelector, /* comparer */ null); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and creates a result value from each group and + /// its key. The elements of each group are projected by using a + /// specified function. + /// + + public static IEnumerable GroupBy( + this IEnumerable source, + Func keySelector, + Func, TResult> resultSelector, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + + return ToLookup(source, keySelector, comparer).Select(g => resultSelector(g.Key, g)); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and creates a result value from each group and + /// its key. The keys are compared by using a specified comparer. + /// + + public static IEnumerable GroupBy( + this IEnumerable source, + Func keySelector, + Func elementSelector, + Func, TResult> resultSelector) + { + return GroupBy(source, keySelector, elementSelector, resultSelector, /* comparer */ null); + } + + /// + /// Groups the elements of a sequence according to a specified key + /// selector function and creates a result value from each group and + /// its key. Key values are compared by using a specified comparer, + /// and the elements of each group are projected by using a + /// specified function. + /// + + public static IEnumerable GroupBy( + this IEnumerable source, + Func keySelector, + Func elementSelector, + Func, TResult> resultSelector, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + if (elementSelector == null) throw new ArgumentNullException("elementSelector"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + + return ToLookup(source, keySelector, elementSelector, comparer) + .Select(g => resultSelector(g.Key, g)); + } + + /// + /// Applies an accumulator function over a sequence. + /// + + public static TSource Aggregate( + this IEnumerable source, + Func func) + { + if (source == null) throw new ArgumentNullException("source"); + if (func == null) throw new ArgumentNullException("func"); + + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + throw new InvalidOperationException(); + + return e.Renumerable().Skip(1).Aggregate(e.Current, func); + } + } + + /// + /// Applies an accumulator function over a sequence. The specified + /// seed value is used as the initial accumulator value. + /// + + public static TAccumulate Aggregate( + this IEnumerable source, + TAccumulate seed, + Func func) + { + return Aggregate(source, seed, func, r => r); + } + + /// + /// Applies an accumulator function over a sequence. The specified + /// seed value is used as the initial accumulator value, and the + /// specified function is used to select the result value. + /// + + public static TResult Aggregate( + this IEnumerable source, + TAccumulate seed, + Func func, + Func resultSelector) + { + if (source == null) throw new ArgumentNullException("source"); + if (func == null) throw new ArgumentNullException("func"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + + var result = seed; + + foreach (var item in source) + result = func(result, item); + + return resultSelector(result); + } + + /// + /// Produces the set union of two sequences by using the default + /// equality comparer. + /// + + public static IEnumerable Union( + this IEnumerable first, + IEnumerable second) + { + return Union(first, second, /* comparer */ null); + } + + /// + /// Produces the set union of two sequences by using a specified + /// . + /// + + public static IEnumerable Union( + this IEnumerable first, + IEnumerable second, + IEqualityComparer comparer) + { + return first.Concat(second).Distinct(comparer); + } + + /// + /// Returns the elements of the specified sequence or the type + /// parameter's default value in a singleton collection if the + /// sequence is empty. + /// + + public static IEnumerable DefaultIfEmpty( + this IEnumerable source) + { + return source.DefaultIfEmpty(default(TSource)); + } + + /// + /// Returns the elements of the specified sequence or the specified + /// value in a singleton collection if the sequence is empty. + /// + + public static IEnumerable DefaultIfEmpty( + this IEnumerable source, + TSource defaultValue) + { + if (source == null) throw new ArgumentNullException("source"); + + return DefaultIfEmptyYield(source, defaultValue); + } + + private static IEnumerable DefaultIfEmptyYield( + IEnumerable source, + TSource defaultValue) + { + using (var e = source.GetEnumerator()) + { + if (!e.MoveNext()) + yield return defaultValue; + else + do { yield return e.Current; } while (e.MoveNext()); + } + } + + /// + /// Determines whether all elements of a sequence satisfy a condition. + /// + + public static bool All( + this IEnumerable source, + Func predicate) + { + if (source == null) throw new ArgumentNullException("source"); + if (predicate == null) throw new ArgumentNullException("predicate"); + + foreach (var item in source) + if (!predicate(item)) + return false; + + return true; + } + + /// + /// Determines whether a sequence contains any elements. + /// + + public static bool Any( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + using (var e = source.GetEnumerator()) + return e.MoveNext(); + } + + /// + /// Determines whether any element of a sequence satisfies a + /// condition. + /// + + public static bool Any( + this IEnumerable source, + Func predicate) + { + return source.Where(predicate).Any(); + } + + /// + /// Determines whether a sequence contains a specified element by + /// using the default equality comparer. + /// + + public static bool Contains( + this IEnumerable source, + TSource value) + { + return source.Contains(value, /* comparer */ null); + } + + /// + /// Determines whether a sequence contains a specified element by + /// using a specified . + /// + + public static bool Contains( + this IEnumerable source, + TSource value, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + + if (comparer == null) + { + var collection = source as ICollection; + if (collection != null) + return collection.Contains(value); + } + + comparer = comparer ?? EqualityComparer.Default; + return source.Any(item => comparer.Equals(item, value)); + } + + /// + /// Determines whether two sequences are equal by comparing the + /// elements by using the default equality comparer for their type. + /// + + public static bool SequenceEqual( + this IEnumerable first, + IEnumerable second) + { + return first.SequenceEqual(second, /* comparer */ null); + } + + /// + /// Determines whether two sequences are equal by comparing their + /// elements by using a specified . + /// + + public static bool SequenceEqual( + this IEnumerable first, + IEnumerable second, + IEqualityComparer comparer) + { + if (first == null) throw new ArgumentNullException("frist"); + if (second == null) throw new ArgumentNullException("second"); + + comparer = comparer ?? EqualityComparer.Default; + + using (IEnumerator lhs = first.GetEnumerator(), + rhs = second.GetEnumerator()) + { + do + { + if (!lhs.MoveNext()) + return !rhs.MoveNext(); + + if (!rhs.MoveNext()) + return false; + } + while (comparer.Equals(lhs.Current, rhs.Current)); + } + + return false; + } + + /// + /// Base implementation for Min/Max operator. + /// + + private static TSource MinMaxImpl( + this IEnumerable source, + Func lesser) + { + if (source == null) throw new ArgumentNullException("source"); + Debug.Assert(lesser != null); + + if (typeof(TSource).IsClass) // ReSharper disable CompareNonConstrainedGenericWithNull + source = source.Where(e => e != null).DefaultIfEmpty(); // ReSharper restore CompareNonConstrainedGenericWithNull + + return source.Aggregate((a, item) => lesser(a, item) ? a : item); + } + + /// + /// Base implementation for Min/Max operator for nullable types. + /// + + private static TSource? MinMaxImpl( + this IEnumerable source, + TSource? seed, Func lesser) where TSource : struct + { + if (source == null) throw new ArgumentNullException("source"); + Debug.Assert(lesser != null); + + return source.Aggregate(seed, (a, item) => lesser(a, item) ? a : item); + // == MinMaxImpl(Repeat(null, 1).Concat(source), lesser); + } + + /// + /// Returns the minimum value in a generic sequence. + /// + + public static TSource Min( + this IEnumerable source) + { + var comparer = Comparer.Default; + return source.MinMaxImpl((x, y) => comparer.Compare(x, y) < 0); + } + + /// + /// Invokes a transform function on each element of a generic + /// sequence and returns the minimum resulting value. + /// + + public static TResult Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a generic sequence. + /// + + public static TSource Max( + this IEnumerable source) + { + var comparer = Comparer.Default; + return source.MinMaxImpl((x, y) => comparer.Compare(x, y) > 0); + } + + /// + /// Invokes a transform function on each element of a generic + /// sequence and returns the maximum resulting value. + /// + + public static TResult Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + + /// + /// Makes an enumerator seen as enumerable once more. + /// + /// + /// The supplied enumerator must have been started. The first element + /// returned is the element the enumerator was on when passed in. + /// DO NOT use this method if the caller must be a generator. It is + /// mostly safe among aggregate operations. + /// + + private static IEnumerable Renumerable(this IEnumerator e) + { + Debug.Assert(e != null); + + do { yield return e.Current; } while (e.MoveNext()); + } + + /// + /// Sorts the elements of a sequence in ascending order according to a key. + /// + + public static IOrderedEnumerable OrderBy( + this IEnumerable source, + Func keySelector) + { + return source.OrderBy(keySelector, /* comparer */ null); + } + + /// + /// Sorts the elements of a sequence in ascending order by using a + /// specified comparer. + /// + + public static IOrderedEnumerable OrderBy( + this IEnumerable source, + Func keySelector, + IComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + + return new OrderedEnumerable(source, keySelector, comparer, /* descending */ false); + } + + /// + /// Sorts the elements of a sequence in descending order according to a key. + /// + + public static IOrderedEnumerable OrderByDescending( + this IEnumerable source, + Func keySelector) + { + return source.OrderByDescending(keySelector, /* comparer */ null); + } + + /// + /// Sorts the elements of a sequence in descending order by using a + /// specified comparer. + /// + + public static IOrderedEnumerable OrderByDescending( + this IEnumerable source, + Func keySelector, + IComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (source == null) throw new ArgumentNullException("keySelector"); + + return new OrderedEnumerable(source, keySelector, comparer, /* descending */ true); + } + + /// + /// Performs a subsequent ordering of the elements in a sequence in + /// ascending order according to a key. + /// + + public static IOrderedEnumerable ThenBy( + this IOrderedEnumerable source, + Func keySelector) + { + return source.ThenBy(keySelector, /* comparer */ null); + } + + /// + /// Performs a subsequent ordering of the elements in a sequence in + /// ascending order by using a specified comparer. + /// + + public static IOrderedEnumerable ThenBy( + this IOrderedEnumerable source, + Func keySelector, + IComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + + return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ false); + } + + /// + /// Performs a subsequent ordering of the elements in a sequence in + /// descending order, according to a key. + /// + + public static IOrderedEnumerable ThenByDescending( + this IOrderedEnumerable source, + Func keySelector) + { + return source.ThenByDescending(keySelector, /* comparer */ null); + } + + /// + /// Performs a subsequent ordering of the elements in a sequence in + /// descending order by using a specified comparer. + /// + + public static IOrderedEnumerable ThenByDescending( + this IOrderedEnumerable source, + Func keySelector, + IComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + + return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ true); + } + + /// + /// Base implementation for Intersect and Except operators. + /// + + private static IEnumerable IntersectExceptImpl( + this IEnumerable first, + IEnumerable second, + IEqualityComparer comparer, + bool flag) + { + if (first == null) throw new ArgumentNullException("first"); + if (second == null) throw new ArgumentNullException("second"); + + var keys = new List>(); + var flags = new Dictionary, bool>(new KeyComparer(comparer)); + + foreach (var item in from item in first + select new Key(item) into item + where !flags.ContainsKey(item) + select item) + { + flags.Add(item, !flag); + keys.Add(item); + } + + foreach (var item in from item in second + select new Key(item) into item + where flags.ContainsKey(item) + select item) + { + flags[item] = flag; + } + + // + // As per docs, "the marked elements are yielded in the order in + // which they were collected. + // + + return from item in keys where flags[item] select item.Value; + } + + /// + /// Produces the set intersection of two sequences by using the + /// default equality comparer to compare values. + /// + + public static IEnumerable Intersect( + this IEnumerable first, + IEnumerable second) + { + return first.Intersect(second, /* comparer */ null); + } + + /// + /// Produces the set intersection of two sequences by using the + /// specified to compare values. + /// + + public static IEnumerable Intersect( + this IEnumerable first, + IEnumerable second, + IEqualityComparer comparer) + { + return IntersectExceptImpl(first, second, comparer, /* flag */ true); + } + + /// + /// Produces the set difference of two sequences by using the + /// default equality comparer to compare values. + /// + + public static IEnumerable Except( + this IEnumerable first, + IEnumerable second) + { + return first.Except(second, /* comparer */ null); + } + + /// + /// Produces the set difference of two sequences by using the + /// specified to compare values. + /// + + public static IEnumerable Except( + this IEnumerable first, + IEnumerable second, + IEqualityComparer comparer) + { + return IntersectExceptImpl(first, second, comparer, /* flag */ false); + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function. + /// + + public static Dictionary ToDictionary( + this IEnumerable source, + Func keySelector) + { + return source.ToDictionary(keySelector, /* comparer */ null); + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function and key comparer. + /// + + public static Dictionary ToDictionary( + this IEnumerable source, + Func keySelector, + IEqualityComparer comparer) + { + return source.ToDictionary(keySelector, e => e, comparer); + } + + /// + /// Creates a from an + /// according to specified key + /// selector and element selector functions. + /// + + public static Dictionary ToDictionary( + this IEnumerable source, + Func keySelector, + Func elementSelector) + { + return source.ToDictionary(keySelector, elementSelector, /* comparer */ null); + } + + /// + /// Creates a from an + /// according to a specified key + /// selector function, a comparer, and an element selector function. + /// + + public static Dictionary ToDictionary( + this IEnumerable source, + Func keySelector, + Func elementSelector, + IEqualityComparer comparer) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + if (elementSelector == null) throw new ArgumentNullException("elementSelector"); + + var dict = new Dictionary(comparer); + + foreach (var item in source) + { + // + // ToDictionary is meant to throw ArgumentNullException if + // keySelector produces a key that is null and + // Argument exception if keySelector produces duplicate keys + // for two elements. Incidentally, the doucmentation for + // IDictionary.Add says that the Add method + // throws the same exceptions under the same circumstances + // so we don't need to do any additional checking or work + // here and let the Add implementation do all the heavy + // lifting. + // + + dict.Add(keySelector(item), elementSelector(item)); + } + + return dict; + } + + /// + /// Correlates the elements of two sequences based on matching keys. + /// The default equality comparer is used to compare keys. + /// + + public static IEnumerable Join( + this IEnumerable outer, + IEnumerable inner, + Func outerKeySelector, + Func innerKeySelector, + Func resultSelector) + { + return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null); + } + + /// + /// Correlates the elements of two sequences based on matching keys. + /// The default equality comparer is used to compare keys. A + /// specified is used to compare keys. + /// + + public static IEnumerable Join( + this IEnumerable outer, + IEnumerable inner, + Func outerKeySelector, + Func innerKeySelector, + Func resultSelector, + IEqualityComparer comparer) + { + if (outer == null) throw new ArgumentNullException("outer"); + if (inner == null) throw new ArgumentNullException("inner"); + if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector"); + if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + + var lookup = inner.ToLookup(innerKeySelector, comparer); + + return + from o in outer + from i in lookup[outerKeySelector(o)] + select resultSelector(o, i); + } + + /// + /// Correlates the elements of two sequences based on equality of + /// keys and groups the results. The default equality comparer is + /// used to compare keys. + /// + + public static IEnumerable GroupJoin( + this IEnumerable outer, + IEnumerable inner, + Func outerKeySelector, + Func innerKeySelector, + Func, TResult> resultSelector) + { + return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null); + } + + /// + /// Correlates the elements of two sequences based on equality of + /// keys and groups the results. The default equality comparer is + /// used to compare keys. A specified + /// is used to compare keys. + /// + + public static IEnumerable GroupJoin( + this IEnumerable outer, + IEnumerable inner, + Func outerKeySelector, + Func innerKeySelector, + Func, TResult> resultSelector, + IEqualityComparer comparer) + { + if (outer == null) throw new ArgumentNullException("outer"); + if (inner == null) throw new ArgumentNullException("inner"); + if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector"); + if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector"); + if (resultSelector == null) throw new ArgumentNullException("resultSelector"); + + var lookup = inner.ToLookup(innerKeySelector, comparer); + return outer.Select(o => resultSelector(o, lookup[outerKeySelector(o)])); + } + + private static class Sequence + { + public static readonly IEnumerable Empty = new T[0]; + } + + private sealed class Grouping : List, IGrouping + { + internal Grouping(K key) + { + Key = key; + } + + public K Key { get; private set; } + } + } +} + +// $Id: Enumerable.g.tt 71137f497bf2 2012/04/16 20:01:27 azizatif $ + +namespace System.Linq +{ + #region Imports + + using System; + using System.Collections.Generic; + + #endregion + + // This partial implementation was template-generated: + // Mon, 16 Apr 2012 20:05:53 GMT + + partial class Enumerable + { + /// + /// Computes the sum of a sequence of nullable values. + /// + + public static int Sum( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + int sum = 0; + foreach (var num in source) + sum = checked(sum + num); + + return sum; + } + + /// + /// Computes the sum of a sequence of nullable + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static int Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of nullable values. + /// + + public static double Average( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + long sum = 0; + long count = 0; + + foreach (var num in source) + checked + { + sum += (int) num; + count++; + } + + if (count == 0) + throw new InvalidOperationException(); + + return (double) sum / count; + } + + /// + /// Computes the average of a sequence of nullable values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + + /// + /// Computes the sum of a sequence of values. + /// + + public static int? Sum( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + int sum = 0; + foreach (var num in source) + sum = checked(sum + (num ?? 0)); + + return sum; + } + + /// + /// Computes the sum of a sequence of + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static int? Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of values. + /// + + public static double? Average( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + long sum = 0; + long count = 0; + + foreach (var num in source.Where(n => n != null)) + checked + { + sum += (int) num; + count++; + } + + if (count == 0) + return null; + + return (double?) sum / count; + } + + /// + /// Computes the average of a sequence of values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double? Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + /// + /// Returns the minimum value in a sequence of nullable + /// values. + /// + + public static int? Min( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the minimum nullable value. + /// + + public static int? Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a sequence of nullable + /// values. + /// + + public static int? Max( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return MinMaxImpl(source.Where(x => x != null), + null, (max, x) => x == null || (max != null && x.Value < max.Value)); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the maximum nullable value. + /// + + public static int? Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + + /// + /// Computes the sum of a sequence of nullable values. + /// + + public static long Sum( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + long sum = 0; + foreach (var num in source) + sum = checked(sum + num); + + return sum; + } + + /// + /// Computes the sum of a sequence of nullable + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static long Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of nullable values. + /// + + public static double Average( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + long sum = 0; + long count = 0; + + foreach (var num in source) + checked + { + sum += (long) num; + count++; + } + + if (count == 0) + throw new InvalidOperationException(); + + return (double) sum / count; + } + + /// + /// Computes the average of a sequence of nullable values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + + /// + /// Computes the sum of a sequence of values. + /// + + public static long? Sum( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + long sum = 0; + foreach (var num in source) + sum = checked(sum + (num ?? 0)); + + return sum; + } + + /// + /// Computes the sum of a sequence of + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static long? Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of values. + /// + + public static double? Average( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + long sum = 0; + long count = 0; + + foreach (var num in source.Where(n => n != null)) + checked + { + sum += (long) num; + count++; + } + + if (count == 0) + return null; + + return (double?) sum / count; + } + + /// + /// Computes the average of a sequence of values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double? Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + /// + /// Returns the minimum value in a sequence of nullable + /// values. + /// + + public static long? Min( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the minimum nullable value. + /// + + public static long? Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a sequence of nullable + /// values. + /// + + public static long? Max( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return MinMaxImpl(source.Where(x => x != null), + null, (max, x) => x == null || (max != null && x.Value < max.Value)); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the maximum nullable value. + /// + + public static long? Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + + /// + /// Computes the sum of a sequence of nullable values. + /// + + public static float Sum( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + float sum = 0; + foreach (var num in source) + sum = checked(sum + num); + + return sum; + } + + /// + /// Computes the sum of a sequence of nullable + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static float Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of nullable values. + /// + + public static float Average( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + float sum = 0; + long count = 0; + + foreach (var num in source) + checked + { + sum += (float) num; + count++; + } + + if (count == 0) + throw new InvalidOperationException(); + + return (float) sum / count; + } + + /// + /// Computes the average of a sequence of nullable values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static float Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + + /// + /// Computes the sum of a sequence of values. + /// + + public static float? Sum( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + float sum = 0; + foreach (var num in source) + sum = checked(sum + (num ?? 0)); + + return sum; + } + + /// + /// Computes the sum of a sequence of + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static float? Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of values. + /// + + public static float? Average( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + float sum = 0; + long count = 0; + + foreach (var num in source.Where(n => n != null)) + checked + { + sum += (float) num; + count++; + } + + if (count == 0) + return null; + + return (float?) sum / count; + } + + /// + /// Computes the average of a sequence of values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static float? Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + /// + /// Returns the minimum value in a sequence of nullable + /// values. + /// + + public static float? Min( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the minimum nullable value. + /// + + public static float? Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a sequence of nullable + /// values. + /// + + public static float? Max( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return MinMaxImpl(source.Where(x => x != null), + null, (max, x) => x == null || (max != null && x.Value < max.Value)); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the maximum nullable value. + /// + + public static float? Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + + /// + /// Computes the sum of a sequence of nullable values. + /// + + public static double Sum( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + double sum = 0; + foreach (var num in source) + sum = checked(sum + num); + + return sum; + } + + /// + /// Computes the sum of a sequence of nullable + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static double Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of nullable values. + /// + + public static double Average( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + double sum = 0; + long count = 0; + + foreach (var num in source) + checked + { + sum += (double) num; + count++; + } + + if (count == 0) + throw new InvalidOperationException(); + + return (double) sum / count; + } + + /// + /// Computes the average of a sequence of nullable values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + + /// + /// Computes the sum of a sequence of values. + /// + + public static double? Sum( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + double sum = 0; + foreach (var num in source) + sum = checked(sum + (num ?? 0)); + + return sum; + } + + /// + /// Computes the sum of a sequence of + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static double? Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of values. + /// + + public static double? Average( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + double sum = 0; + long count = 0; + + foreach (var num in source.Where(n => n != null)) + checked + { + sum += (double) num; + count++; + } + + if (count == 0) + return null; + + return (double?) sum / count; + } + + /// + /// Computes the average of a sequence of values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static double? Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + /// + /// Returns the minimum value in a sequence of nullable + /// values. + /// + + public static double? Min( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the minimum nullable value. + /// + + public static double? Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a sequence of nullable + /// values. + /// + + public static double? Max( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return MinMaxImpl(source.Where(x => x != null), + null, (max, x) => x == null || (max != null && x.Value < max.Value)); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the maximum nullable value. + /// + + public static double? Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + + /// + /// Computes the sum of a sequence of nullable values. + /// + + public static decimal Sum( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + decimal sum = 0; + foreach (var num in source) + sum = checked(sum + num); + + return sum; + } + + /// + /// Computes the sum of a sequence of nullable + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static decimal Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of nullable values. + /// + + public static decimal Average( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + decimal sum = 0; + long count = 0; + + foreach (var num in source) + checked + { + sum += (decimal) num; + count++; + } + + if (count == 0) + throw new InvalidOperationException(); + + return (decimal) sum / count; + } + + /// + /// Computes the average of a sequence of nullable values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static decimal Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + + /// + /// Computes the sum of a sequence of values. + /// + + public static decimal? Sum( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + decimal sum = 0; + foreach (var num in source) + sum = checked(sum + (num ?? 0)); + + return sum; + } + + /// + /// Computes the sum of a sequence of + /// values that are obtained by invoking a transform function on + /// each element of the input sequence. + /// + + public static decimal? Sum( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Sum(); + } + + /// + /// Computes the average of a sequence of values. + /// + + public static decimal? Average( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + decimal sum = 0; + long count = 0; + + foreach (var num in source.Where(n => n != null)) + checked + { + sum += (decimal) num; + count++; + } + + if (count == 0) + return null; + + return (decimal?) sum / count; + } + + /// + /// Computes the average of a sequence of values + /// that are obtained by invoking a transform function on each + /// element of the input sequence. + /// + + public static decimal? Average( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Average(); + } + + /// + /// Returns the minimum value in a sequence of nullable + /// values. + /// + + public static decimal? Min( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the minimum nullable value. + /// + + public static decimal? Min( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Min(); + } + + /// + /// Returns the maximum value in a sequence of nullable + /// values. + /// + + public static decimal? Max( + this IEnumerable source) + { + if (source == null) throw new ArgumentNullException("source"); + + return MinMaxImpl(source.Where(x => x != null), + null, (max, x) => x == null || (max != null && x.Value < max.Value)); + } + + /// + /// Invokes a transform function on each element of a sequence and + /// returns the maximum nullable value. + /// + + public static decimal? Max( + this IEnumerable source, + Func selector) + { + return source.Select(selector).Max(); + } + } +} + +// $Id: ExtensionAttribute.cs 898b3d493ed6 2012/04/17 20:09:57 azizatif $ + +namespace System.Runtime.CompilerServices +{ + /// + /// This attribute allows us to define extension methods without + /// requiring .NET Framework 3.5. For more information, see the section, + /// Extension Methods in .NET Framework 2.0 Apps, + /// of Basic Instincts: Extension Methods + /// column in MSDN Magazine, + /// issue Nov 2007. + /// + + [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)] + sealed partial class ExtensionAttribute : Attribute { } +} + +// $Id: Func.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ + +namespace System +{ +#if LINQBRIDGE_LIB + public delegate TResult Func(); + public delegate TResult Func(T a); + public delegate TResult Func(T1 arg1, T2 arg2); + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); +#else + delegate TResult Func(); + delegate TResult Func(T a); + delegate TResult Func(T1 arg1, T2 arg2); + delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); + delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); +#endif +} + +// $Id: IGrouping.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ + +namespace System.Linq +{ + #region Imports + + using System.Collections.Generic; + + #endregion + + /// + /// Represents a collection of objects that have a common key. + /// + + partial interface IGrouping : IEnumerable + { + /// + /// Gets the key of the . + /// + + TKey Key { get; } + } +} + +// $Id: ILookup.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ + +namespace System.Linq +{ + using System.Collections.Generic; + + /// + /// Defines an indexer, size property, and Boolean search method for + /// data structures that map keys to + /// sequences of values. + /// + + partial interface ILookup : IEnumerable> + { + bool Contains(TKey key); + int Count { get; } + IEnumerable this[TKey key] { get; } + } +} + +// $Id: Internal.cs 1567e00f1a20 2012/04/17 16:09:51 azizatif $ + +namespace LinqBridge +{ + #region Imports + + using System; + using System.Collections.Generic; + + #endregion + + /// + /// This type is not intended to be used directly from user code. + /// It may be removed or changed in a future version without notice. + /// + + sealed class DelegatingComparer : IComparer + { + private readonly Func _comparer; + + public DelegatingComparer(Func comparer) + { + if (comparer == null) throw new ArgumentNullException("comparer"); + _comparer = comparer; + } + + public int Compare(T x, T y) { return _comparer(x, y); } + } + + /// + /// This type is not intended to be used directly from user code. + /// It may be removed or changed in a future version without notice. + /// + + struct Key + { + public Key(T value) : this() { Value = value; } + public T Value { get; private set; } + } + + /// + /// This type is not intended to be used directly from user code. + /// It may be removed or changed in a future version without notice. + /// + + sealed class KeyComparer : IEqualityComparer> + { + private readonly IEqualityComparer _innerComparer; + + public KeyComparer(IEqualityComparer innerComparer) + { + _innerComparer = innerComparer ?? EqualityComparer.Default; + } + + public bool Equals(Key x, Key y) + { + return _innerComparer.Equals(x.Value, y.Value); + } + + public int GetHashCode(Key obj) + { + return obj.Value == null ? 0 : _innerComparer.GetHashCode(obj.Value); + } + } +} + +// $Id: IOrderedEnumerable.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ + +namespace System.Linq +{ + using System.Collections.Generic; + + /// + /// Represents a sorted sequence. + /// + + partial interface IOrderedEnumerable : IEnumerable + { + /// + /// Performs a subsequent ordering on the elements of an + /// according to a key. + /// + + IOrderedEnumerable CreateOrderedEnumerable( + Func keySelector, IComparer comparer, bool descending); + } +} + +// $Id: Lookup.cs c08984d432b1 2012/04/17 16:05:19 azizatif $ + +namespace System.Linq +{ + #region Imports + + using System; + using System.Collections; + using System.Collections.Generic; + using IEnumerable=System.Collections.IEnumerable; + using LinqBridge; + + #endregion + + /// + /// Represents a collection of keys each mapped to one or more values. + /// + + internal sealed class Lookup : ILookup + { + private readonly Dictionary, IGrouping> _map; + private readonly List> _orderedKeys; // remember order of insertion + + internal Lookup(IEqualityComparer comparer) + { + _map = new Dictionary, IGrouping>(new KeyComparer(comparer)); + _orderedKeys = new List>(); + } + + internal void Add(IGrouping item) + { + var key = new Key(item.Key); + _map.Add(key, item); + _orderedKeys.Add(key); + } + + internal IEnumerable Find(TKey key) + { + IGrouping grouping; + return _map.TryGetValue(new Key(key), out grouping) ? grouping : null; + } + + /// + /// Gets the number of key/value collection pairs in the . + /// + + public int Count + { + get { return _map.Count; } + } + + /// + /// Gets the collection of values indexed by the specified key. + /// + + public IEnumerable this[TKey key] + { + get + { + IGrouping result; + return _map.TryGetValue(new Key(key), out result) ? result : Enumerable.Empty(); + } + } + + /// + /// Determines whether a specified key is in the . + /// + + public bool Contains(TKey key) + { + return _map.ContainsKey(new Key(key)); + } + + /// + /// Applies a transform function to each key and its associated + /// values and returns the results. + /// + + public IEnumerable ApplyResultSelector( + Func, TResult> resultSelector) + { + if (resultSelector == null) + throw new ArgumentNullException("resultSelector"); + + foreach (var pair in _map) + yield return resultSelector(pair.Key.Value, pair.Value); + } + + /// + /// Returns a generic enumerator that iterates through the . + /// + + public IEnumerator> GetEnumerator() + { + foreach (var key in _orderedKeys) + yield return _map[key]; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} + +// $Id: OrderedEnumerable.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ + +namespace LinqBridge +{ + #region Imports + + using System; + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics; + using System.Linq; + + #endregion + + internal sealed class OrderedEnumerable : IOrderedEnumerable + { + private readonly IEnumerable _source; + private readonly Func, IComparer> _comparerComposer; + + public OrderedEnumerable(IEnumerable source, + Func keySelector, IComparer comparer, bool descending) : + this(source, (_, next) => next, keySelector, comparer, descending) {} + + private OrderedEnumerable(IEnumerable source, + Func, IComparer> parent, + Func keySelector, IComparer comparer, bool descending) + { + if (source == null) throw new ArgumentNullException("source"); + if (keySelector == null) throw new ArgumentNullException("keySelector"); + Debug.Assert(parent != null); + + _source = source; + + comparer = comparer ?? Comparer.Default; + var direction = descending ? -1 : 1; + + _comparerComposer = (items, next) => + { + Debug.Assert(items != null); + Debug.Assert(next != null); + + var keys = new K[items.Length]; + for (var i = 0; i < items.Length; i++) + keys[i] = keySelector(items[i]); + + return parent(items, new DelegatingComparer((i, j) => + { + var result = direction * comparer.Compare(keys[i], keys[j]); + return result != 0 ? result : next.Compare(i, j); + })); + }; + } + + public IOrderedEnumerable CreateOrderedEnumerable( + Func keySelector, IComparer comparer, bool descending) + { + return new OrderedEnumerable(_source, _comparerComposer, keySelector, comparer, descending); + } + + public IEnumerator GetEnumerator() + { + // + // Sort using Array.Sort but docs say that it performs an + // unstable sort. LINQ, on the other hand, says OrderBy performs + // a stable sort. Use the item position then as a tie + // breaker when all keys compare equal, thus making the sort + // stable. + // + + var items = _source.ToArray(); + var positionComparer = new DelegatingComparer((i, j) => i.CompareTo(j)); + var comparer = _comparerComposer(items, positionComparer); + var keys = new int[items.Length]; + for (var i = 0; i < keys.Length; i++) + keys[i] = i; + Array.Sort(keys, items, comparer); + return ((IEnumerable) items).GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} + +// $Id: Action.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ + +namespace System +{ +#if LINQBRIDGE_LIB + public delegate void Action(); + public delegate void Action(T1 arg1, T2 arg2); + public delegate void Action(T1 arg1, T2 arg2, T3 arg3); + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); +#else + delegate void Action(); + delegate void Action(T1 arg1, T2 arg2); + delegate void Action(T1 arg1, T2 arg2, T3 arg3); + delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); +#endif +} + diff --git a/Main.cs b/Main.cs index 727d86d..1798495 100644 --- a/Main.cs +++ b/Main.cs @@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License using System.Drawing; using System.Text; using System.Windows.Forms; -using Microsoft.Win32; namespace AeroShot { @@ -28,7 +27,7 @@ public sealed partial class MainForm : Form private const uint SPI_GETFONTSMOOTHING = 0x004A; private const uint SPI_GETFONTSMOOTHINGTYPE = 0x200A; - Settings _settings = Settings.LoadSettingsFromRegistry(); + Settings _settings = Settings.LoadSettings(); public MainForm() { @@ -278,7 +277,7 @@ private void AeroColorTextboxTextChange(object sender, EventArgs e) private void OkButtonClick(object sender, EventArgs e) { - Settings.SaveSettingsToRegistry(new Settings + Settings.SaveSettings(new Settings { UseClipboard = clipboardButton.Checked, FolderPath = folderTextBox.Text, diff --git a/Settings.cs b/Settings.cs index 9032ae7..931c2b0 100644 --- a/Settings.cs +++ b/Settings.cs @@ -15,12 +15,19 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the You should have received a copy of the GNU General Public License along with this program. If not, see . */ -using System; -using System.Drawing; -using Microsoft.Win32; - namespace AeroShot { + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Text.RegularExpressions; + using System.Windows.Forms; + using Microsoft.Win32; + using Gini; + sealed class Settings { public bool UseDisk; @@ -35,6 +42,134 @@ sealed class Settings public Switch DelayCaptureDuration = Switch.Off(TimeSpan.FromSeconds(3)); public bool DisableClearType; + static string _iniFilePath; + + static string IniFilePath + { + get { return _iniFilePath ?? (_iniFilePath = Path.Combine(Application.StartupPath, "AeroShot.ini")); } + } + + public static Settings LoadSettings() + { + return File.Exists(IniFilePath) + ? LoadSettingsFromIniFile(IniFilePath) + : LoadSettingsFromRegistry(); + } + + static Settings LoadSettingsFromIniFile(string path) + { + return LoadSettingsFromIni(File.ReadAllText(path)); + } + + static Settings LoadSettingsFromIni(string source) + { + var settings = new Settings(); + + var ini = Ini.Parse(source) + .Where(s => string.IsNullOrEmpty(s.Key)) + .Select(s => s.ToDictionary(e => e.Key, e => e.Value, StringComparer.OrdinalIgnoreCase)) + .FirstOrDefault(); + + if (ini != null) + { + settings.UseDisk = ReadSetting(ini, "save-device", v => "file".Equals(v, StringComparison.OrdinalIgnoreCase)); + settings.UseClipboard = !settings.UseDisk; + settings.FolderPath = ReadSetting(ini, "save-file-path", Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), s => s); + settings.OpaqueBackgroundType + = Switch.Create(ReadSetting(ini, "use-opaque-background", Truthy.Parse), + ReadSetting(ini, "opaque-background-type", v => "solid".Equals(v, StringComparison.OrdinalIgnoreCase) + ? ScreenshotBackgroundType.SolidColor + : ScreenshotBackgroundType.Checkerboard)); + settings.SolidBackgroundColor + = ReadSetting(ini, "solid-background-color", settings.SolidBackgroundColor, ColorTranslator.FromHtml); + settings.CheckerboardBackgroundCheckerSize + = ReadSetting(ini, "checkerboard-background-checker-size", settings.CheckerboardBackgroundCheckerSize, ParseInt); + settings.AeroColor = Switch.Create(ReadSetting(ini, "use-aero-color", Truthy.Parse), + ReadSetting(ini, "aero-color", settings.AeroColor.Value, ColorTranslator.FromHtml)); + settings.ResizeDimensions = Switch.Create(ReadSetting(ini, "use-window-resize-dimensions", Truthy.Parse), + new Size(ReadSetting(ini, "resize-window-width", settings.ResizeDimensions.Value.Width, ParseInt), + ReadSetting(ini, "resize-window-height", settings.ResizeDimensions.Value.Height, ParseInt))); + settings.DelayCaptureDuration + = Switch.Create(ReadSetting(ini, "use-delay-capture", Truthy.Parse), + ReadSetting(ini, "delay-capture-seconds", settings.DelayCaptureDuration.Value, v => TimeSpan.FromSeconds(ParseInt(v)))); + settings.CaputreMouse = ReadSetting(ini, "capture-pointer", Truthy.Parse); + settings.DisableClearType = ReadSetting(ini, "disable-clear-type", Truthy.Parse); + } + + return settings; + } + + static T ReadSetting(IDictionary section, string key, Func selector) + { + return ReadSetting(section, key, default(T), selector); + } + + static T ReadSetting(IDictionary section, string key, T defaultValue, Func selector) + { + string value; + if (section.TryGetValue(key, out value)) + value = value.Trim(); + return !string.IsNullOrEmpty(value) ? selector(value) : defaultValue; + } + + static int ParseInt(string s) { return int.Parse(s, NumberStyles.None, CultureInfo.InvariantCulture); } + + static class Truthy + { + static readonly Regex Regex = new Regex(@"^\s*(true|yes|on|1)\s*$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); + public static bool Parse(string s) { return Regex.IsMatch(s); } + } + + public static void SaveSettings(Settings settings) + { + File.WriteAllText(IniFilePath, SettingsIni(settings)); + // TODO Handle UnauthorizedAccessException + } + + static string SettingsIni(Settings settings) + { + var section = new[] + { + Setting("app-version" , Application.ProductVersion), + Setting("save-device" , settings.UseClipboard ? "clipboard" : "file"), + Setting("save-file-path" , settings.FolderPath), + Setting("use-opaque-background" , settings.OpaqueBackgroundType.Convert(_ => true)), + Setting("opaque-background-type" , settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.SolidColor ? "solid" : "checkerboard"), + Setting("solid-background-color" , ColorTranslator.ToHtml(settings.SolidBackgroundColor)), + Setting("checkerboard-background-checker-size", settings.CheckerboardBackgroundCheckerSize), + Setting("use-aero-color" , settings.AeroColor.Convert(_ => true)), + Setting("aero-color" , ColorTranslator.ToHtml(settings.AeroColor.Value)), + Setting("use-window-resize-dimensions" , settings.ResizeDimensions.Convert(_ => true)), + Setting("resize-window-width" , settings.ResizeDimensions.Value.Width), + Setting("resize-window-height" , settings.ResizeDimensions.Value.Height), + Setting("capture-pointer" , settings.CaputreMouse), + Setting("use-delay-capture" , settings.DelayCaptureDuration.Convert(_ => true)), + Setting("delay-capture-seconds" , settings.DelayCaptureDuration.Value.TotalSeconds), + Setting("disable-clear-type" , settings.DisableClearType), + }; + + return string.Join(Environment.NewLine, + Ini.Format(new[] { section }, e => null, e => e, e => e) + .ToArray()); + } + + static KeyValuePair Setting(string key, string value) + { + return KeyValuePair.Create(key, value ?? string.Empty); + } + + static KeyValuePair Setting(string key, bool value) + { + return KeyValuePair.Create(key, value ? "true" : "false"); + } + + static KeyValuePair Setting(string key, object value) + { + return Setting(key, value == null + ? string.Empty + : Convert.ToString(value, CultureInfo.InvariantCulture)); + } + static RegistryKey CreateRegistryKey() { return Registry.CurrentUser.CreateSubKey(@"Software\AeroShot"); @@ -205,6 +340,14 @@ public static void SaveSettings(Settings settings, RegistryKey registryKey) } } + static class KeyValuePair + { + public static KeyValuePair Create(TKey key, TValue value) + { + return new KeyValuePair(key, value); + } + } + static class HexColor { public static string Encode(Color color) @@ -212,4 +355,69 @@ public static string Encode(Color color) return color.IsEmpty ? null : ColorTranslator.ToHtml(color).Substring(1); } } +} + +#region The MIT License (MIT) +// +// Copyright (c) 2015 Atif Aziz. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#endregion + +namespace Gini +{ + using System; + using System.Collections.Generic; + using System.Linq; + + partial class Ini + { + public static IEnumerable Format( + IEnumerable sections, + Func sectionNameSelector, + Func> entriesSelector, + Func> entrySelector) + { + if (sections == null) throw new ArgumentNullException("sections"); + if (sectionNameSelector == null) throw new ArgumentNullException("sectionNameSelector"); + if (entriesSelector == null) throw new ArgumentNullException("entriesSelector"); + if (entrySelector == null) throw new ArgumentNullException("entrySelector"); + + return + from section in sections + select new + { + Name = sectionNameSelector(section), + Entries = entriesSelector(section), + } + into section + from lines in new[] + { + new[] { !string.IsNullOrEmpty(section.Name) ? "[" + section.Name + "]" : null }, + from entry in section.Entries + select entrySelector(entry) into entry + select entry.Key + "=" + entry.Value, + new[] { string.Empty }, + } + from line in lines + where line != null + select line; + } + } } \ No newline at end of file diff --git a/Tray.cs b/Tray.cs index 8d706ae..115597a 100644 --- a/Tray.cs +++ b/Tray.cs @@ -27,7 +27,7 @@ public class SysTray : Form MainForm _window = new MainForm(); Hotkeys _hotkeys = new Hotkeys(); - Settings _settings = Settings.LoadSettingsFromRegistry(); + Settings _settings = Settings.LoadSettings(); public SysTray() { diff --git a/packages.config b/packages.config new file mode 100644 index 0000000..248d140 --- /dev/null +++ b/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file From b572df0e10f941a9dd6b09d6d0c834333f93152b Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Thu, 23 Jul 2015 19:01:02 +0200 Subject: [PATCH 17/31] Saving to registry no longer needed nor used --- Settings.cs | 68 ----------------------------------------------------- 1 file changed, 68 deletions(-) diff --git a/Settings.cs b/Settings.cs index 931c2b0..7820fdb 100644 --- a/Settings.cs +++ b/Settings.cs @@ -270,74 +270,6 @@ public static Settings LoadSettings(RegistryKey registryKey) return settings; } - - public static void SaveSettingsToRegistry(Settings settings) - { - using (var registryKey = CreateRegistryKey()) - SaveSettings(settings, registryKey); - } - - public static void SaveSettings(Settings settings, RegistryKey registryKey) - { - registryKey.SetValue("LastPath", (settings.UseClipboard ? "*" : null) + settings.FolderPath); - - // Save resizing settings in an 8-byte long - var b = new byte[8]; - b[0] = settings.ResizeDimensions.Convert(_ => (byte) 1); - - var x = settings.ResizeDimensions.Value.Width; - b[3] = (byte)(x & 0xff); - b[2] = (byte)((x >> 8) & 0xff); - b[1] = (byte)((x >> 16) & 0xff); - - var y = settings.ResizeDimensions.Value.Height; - b[6] = (byte)(y & 0xff); - b[5] = (byte)((y >> 8) & 0xff); - b[4] = (byte)((y >> 16) & 0xff); - - var data = BitConverter.ToInt64(b, 0); - registryKey.SetValue("WindowSize", data, RegistryValueKind.QWord); - - // Save background color settings in an 8-byte long - b = new byte[8]; - b[0] = settings.OpaqueBackgroundType.Convert(_ => (byte) 1); - b[0] += (byte)Math.Pow(2, settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.SolidColor ? 2 : 1); - - b[1] = (byte)(settings.CheckerboardBackgroundCheckerSize - 2); - - b[2] = settings.SolidBackgroundColor.R; - b[3] = settings.SolidBackgroundColor.G; - b[4] = settings.SolidBackgroundColor.B; - - data = BitConverter.ToInt64(b, 0); - registryKey.SetValue("Opaque", data, RegistryValueKind.QWord); - - // Save background color settings in an 8-byte long - b = new byte[8]; - b[0] = settings.AeroColor.Convert(_ => (byte) 1); - - b[1] = settings.AeroColor.Value.R; - b[2] = settings.AeroColor.Value.G; - b[3] = settings.AeroColor.Value.B; - - data = BitConverter.ToInt64(b, 0); - registryKey.SetValue("AeroColor", data, RegistryValueKind.QWord); - - registryKey.SetValue("CapturePointer", settings.CaputreMouse ? 1 : 0, - RegistryValueKind.DWord); - - registryKey.SetValue("ClearType", settings.DisableClearType ? 1 : 0, - RegistryValueKind.DWord); - - // Save delay settings in an 8-byte long - b = new byte[8]; - b[0] = settings.DelayCaptureDuration.Convert(_ => (byte) 1); - - b[1] = (byte)(((int) settings.DelayCaptureDuration.Value.TotalSeconds) & 0xff); - - data = BitConverter.ToInt64(b, 0); - registryKey.SetValue("Delay", data, RegistryValueKind.QWord); - } } static class KeyValuePair From bfda8cc298d3a104f698246fead98e902d5ef0c0 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Thu, 23 Jul 2015 19:10:41 +0200 Subject: [PATCH 18/31] Merge with master --- Hotkeys.cs | 2 +- Main.Designer.cs | 4 ++-- Main.cs | 4 +++- Program.cs | 6 +++--- Screenshot.cs | 2 +- Settings.cs | 2 +- Tray.cs | 2 +- UnsafeBitmap.cs | 2 +- WindowsAPI.cs | 2 +- 9 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Hotkeys.cs b/Hotkeys.cs index 4f310e0..8e41ef0 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -1,4 +1,4 @@ -/* AeroShot - Transparent screenshot utility for Windows +/* AeroShot - Transparent screenshot utility for Windows Copyright (C) 2015 toe_head2001 Copyright (C) 2012 Caleb Joseph diff --git a/Main.Designer.cs b/Main.Designer.cs index 1c2ab35..a092047 100644 --- a/Main.Designer.cs +++ b/Main.Designer.cs @@ -1,4 +1,4 @@ -/* AeroShot - Transparent screenshot utility for Windows +/* AeroShot - Transparent screenshot utility for Windows Copyright (C) 2015 toe_head2001 Copyright (C) 2012 Caleb Joseph @@ -702,7 +702,7 @@ private void InitializeComponent() this.Name = "MainForm"; this.ShowInTaskbar = false; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "AeroShot Mini v1.5.0 - Settings"; + this.Text = "{0} {1} - Settings"; ((System.ComponentModel.ISupportInitialize)(this.windowHeight)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.windowWidth)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.checkerValue)).EndInit(); diff --git a/Main.cs b/Main.cs index 1798495..c0918e6 100644 --- a/Main.cs +++ b/Main.cs @@ -35,7 +35,9 @@ public MainForm() Icon = new Icon(typeof(MainForm), "icon.ico"); InitializeComponent(); - folderTextBox.Text = _settings.FolderPath; + Text = string.Format(Text, Application.ProductName, Application.ProductVersion); + + folderTextBox.Text = _settings.FolderPath; clipboardButton.Checked = _settings.UseClipboard; diskButton.Checked = _settings.UseDisk; resizeCheckbox.Checked = _settings.ResizeDimensions.On; diff --git a/Program.cs b/Program.cs index 6148c76..00752ff 100644 --- a/Program.cs +++ b/Program.cs @@ -1,4 +1,4 @@ -/* AeroShot - Transparent screenshot utility for Windows +/* AeroShot - Transparent screenshot utility for Windows Copyright (C) 2015 toe_head2001 Copyright (C) 2012 Caleb Joseph @@ -23,7 +23,7 @@ You should have received a copy of the GNU General Public License [assembly: AssemblyTitle("AeroShot Mini")] [assembly: AssemblyProduct("AeroShot Mini")] [assembly: AssemblyDescription("Screenshot capture utility for Windows Aero")] -[assembly: AssemblyCopyright("© 2015 toe_head2001")] +[assembly: AssemblyCopyright("\u00a9 2015 toe_head2001")] [assembly: AssemblyVersion("1.5.0.0")] [assembly: AssemblyFileVersion("1.5.0.0")] [assembly: ComVisible(false)] @@ -37,7 +37,7 @@ private static void Main() { if (Environment.OSVersion.Version.Major < 6) { - MessageBox.Show("Windows Vista or newer is required.", "AeroShot"); + MessageBox.Show("Windows Vista or newer is required.", Application.ProductName); return; } diff --git a/Screenshot.cs b/Screenshot.cs index c031a21..41e9b3a 100644 --- a/Screenshot.cs +++ b/Screenshot.cs @@ -1,4 +1,4 @@ -/* AeroShot - Transparent screenshot utility for Windows +/* AeroShot - Transparent screenshot utility for Windows Copyright (C) 2015 toe_head2001 Copyright (C) 2012 Caleb Joseph diff --git a/Settings.cs b/Settings.cs index 7820fdb..c879569 100644 --- a/Settings.cs +++ b/Settings.cs @@ -1,4 +1,4 @@ -/* AeroShot - Transparent screenshot utility for Windows +/* AeroShot - Transparent screenshot utility for Windows Copyright (C) 2015 toe_head2001 Copyright (C) 2012 Caleb Joseph diff --git a/Tray.cs b/Tray.cs index 115597a..ff577dc 100644 --- a/Tray.cs +++ b/Tray.cs @@ -1,4 +1,4 @@ -/* AeroShot - Transparent screenshot utility for Windows +/* AeroShot - Transparent screenshot utility for Windows Copyright (C) 2015 toe_head2001 AeroShot is free software: you can redistribute it and/or modify diff --git a/UnsafeBitmap.cs b/UnsafeBitmap.cs index 6a9acae..eb5f661 100644 --- a/UnsafeBitmap.cs +++ b/UnsafeBitmap.cs @@ -1,4 +1,4 @@ -/* AeroShot - Transparent screenshot utility for Windows +/* AeroShot - Transparent screenshot utility for Windows Copyright (C) 2012 Caleb Joseph AeroShot is free software: you can redistribute it and/or modify diff --git a/WindowsAPI.cs b/WindowsAPI.cs index 7b92b12..73042d4 100644 --- a/WindowsAPI.cs +++ b/WindowsAPI.cs @@ -1,4 +1,4 @@ -/* AeroShot - Transparent screenshot utility for Windows +/* AeroShot - Transparent screenshot utility for Windows Copyright (C) 2015 toe_head2001 Copyright (C) 2012 Caleb Joseph From 15d2ee64e8c1a005ba168f1f33bf792f16e4fddb Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Thu, 23 Jul 2015 22:37:56 +0200 Subject: [PATCH 19/31] Targeting .NET Framework 3.5 See: https://github.com/toehead2001/aeroshot/pull/26#issuecomment-124226519 --- AeroShot.csproj | 5 +- LinqBridge.cs | 3100 ----------------------------------------------- app.config | 6 + packages.config | 1 - 4 files changed, 9 insertions(+), 3103 deletions(-) delete mode 100644 LinqBridge.cs create mode 100644 app.config diff --git a/AeroShot.csproj b/AeroShot.csproj index 70bbbcf..28f215e 100644 --- a/AeroShot.csproj +++ b/AeroShot.csproj @@ -10,7 +10,7 @@ Properties AeroShot AeroShot - v2.0 + v3.5 512 icon.ico AeroShot.Program @@ -33,6 +33,7 @@ false false true + Client true @@ -60,7 +61,6 @@ Form - Form @@ -99,6 +99,7 @@ + diff --git a/LinqBridge.cs b/LinqBridge.cs deleted file mode 100644 index 3f19511..0000000 --- a/LinqBridge.cs +++ /dev/null @@ -1,3100 +0,0 @@ -#region License, Terms and Author(s) -// -// LINQBridge -// Copyright (c) 2007 Atif Aziz, Joseph Albahari. All rights reserved. -// -// Author(s): -// -// Atif Aziz, http://www.raboof.com -// -// This library is free software; you can redistribute it and/or modify it -// under the terms of the New BSD License, a copy of which should have -// been delivered along with this distribution. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -#endregion - -// $Id: Enumerable.cs c08984d432b1 2012/04/17 16:05:19 azizatif $ - -namespace System.Linq -{ - #region Imports - - using System; - using System.Collections; - using System.Collections.Generic; - using System.Diagnostics; - using LinqBridge; - - #endregion - - /// - /// Provides a set of static (Shared in Visual Basic) methods for - /// querying objects that implement . - /// - - static partial class Enumerable - { - /// - /// Returns the input typed as . - /// - - public static IEnumerable AsEnumerable(this IEnumerable source) - { - return source; - } - - /// - /// Returns an empty that has the - /// specified type argument. - /// - - public static IEnumerable Empty() - { - return Sequence.Empty; - } - - /// - /// Converts the elements of an to the - /// specified type. - /// - - public static IEnumerable Cast( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return CastYield(source); - } - - private static IEnumerable CastYield( - IEnumerable source) - { - foreach (var item in source) - yield return (TResult) item; - } - - /// - /// Filters the elements of an based on a specified type. - /// - - public static IEnumerable OfType( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return OfTypeYield(source); - } - - private static IEnumerable OfTypeYield( - IEnumerable source) - { - foreach (var item in source) - if (item is TResult) - yield return (TResult) item; - } - - /// - /// Generates a sequence of integral numbers within a specified range. - /// - /// The value of the first integer in the sequence. - /// The number of sequential integers to generate. - - public static IEnumerable Range(int start, int count) - { - if (count < 0) - throw new ArgumentOutOfRangeException("count", count, null); - - var end = (long) start + count; - if (end - 1 >= int.MaxValue) - throw new ArgumentOutOfRangeException("count", count, null); - - return RangeYield(start, end); - } - - private static IEnumerable RangeYield(int start, long end) - { - for (var i = start; i < end; i++) - yield return i; - } - - /// - /// Generates a sequence that contains one repeated value. - /// - - public static IEnumerable Repeat(TResult element, int count) - { - if (count < 0) throw new ArgumentOutOfRangeException("count", count, null); - - return RepeatYield(element, count); - } - - private static IEnumerable RepeatYield(TResult element, int count) - { - for (var i = 0; i < count; i++) - yield return element; - } - - /// - /// Filters a sequence of values based on a predicate. - /// - - public static IEnumerable Where( - this IEnumerable source, - Func predicate) - { - if (predicate == null) throw new ArgumentNullException("predicate"); - - return source.Where((item, i) => predicate(item)); - } - - /// - /// Filters a sequence of values based on a predicate. - /// Each element's index is used in the logic of the predicate function. - /// - - public static IEnumerable Where( - this IEnumerable source, - Func predicate) - { - if (source == null) throw new ArgumentNullException("source"); - if (predicate == null) throw new ArgumentNullException("predicate"); - - return WhereYield(source, predicate); - } - - private static IEnumerable WhereYield( - IEnumerable source, - Func predicate) - { - var i = 0; - foreach (var item in source) - if (predicate(item, i++)) - yield return item; - } - - /// - /// Projects each element of a sequence into a new form. - /// - - public static IEnumerable Select( - this IEnumerable source, - Func selector) - { - if (selector == null) throw new ArgumentNullException("selector"); - - return source.Select((item, i) => selector(item)); - } - - /// - /// Projects each element of a sequence into a new form by - /// incorporating the element's index. - /// - - public static IEnumerable Select( - this IEnumerable source, - Func selector) - { - if (source == null) throw new ArgumentNullException("source"); - if (selector == null) throw new ArgumentNullException("selector"); - - return SelectYield(source, selector); - } - - private static IEnumerable SelectYield( - IEnumerable source, - Func selector) - { - var i = 0; - foreach (var item in source) - yield return selector(item, i++); - } - - /// - /// Projects each element of a sequence to an - /// and flattens the resulting sequences into one sequence. - /// - - public static IEnumerable SelectMany( - this IEnumerable source, - Func> selector) - { - if (selector == null) throw new ArgumentNullException("selector"); - - return source.SelectMany((item, i) => selector(item)); - } - - /// - /// Projects each element of a sequence to an , - /// and flattens the resulting sequences into one sequence. The - /// index of each source element is used in the projected form of - /// that element. - /// - - public static IEnumerable SelectMany( - this IEnumerable source, - Func> selector) - { - if (selector == null) throw new ArgumentNullException("selector"); - - return source.SelectMany(selector, (item, subitem) => subitem); - } - - /// - /// Projects each element of a sequence to an , - /// flattens the resulting sequences into one sequence, and invokes - /// a result selector function on each element therein. - /// - - public static IEnumerable SelectMany( - this IEnumerable source, - Func> collectionSelector, - Func resultSelector) - { - if (collectionSelector == null) throw new ArgumentNullException("collectionSelector"); - - return source.SelectMany((item, i) => collectionSelector(item), resultSelector); - } - - /// - /// Projects each element of a sequence to an , - /// flattens the resulting sequences into one sequence, and invokes - /// a result selector function on each element therein. The index of - /// each source element is used in the intermediate projected form - /// of that element. - /// - - public static IEnumerable SelectMany( - this IEnumerable source, - Func> collectionSelector, - Func resultSelector) - { - if (source == null) throw new ArgumentNullException("source"); - if (collectionSelector == null) throw new ArgumentNullException("collectionSelector"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - - return SelectManyYield(source, collectionSelector, resultSelector); - } - - private static IEnumerable SelectManyYield( - this IEnumerable source, - Func> collectionSelector, - Func resultSelector) - { - var i = 0; - foreach (var item in source) - foreach (var subitem in collectionSelector(item, i++)) - yield return resultSelector(item, subitem); - } - - /// - /// Returns elements from a sequence as long as a specified condition is true. - /// - - public static IEnumerable TakeWhile( - this IEnumerable source, - Func predicate) - { - if (predicate == null) throw new ArgumentNullException("predicate"); - - return source.TakeWhile((item, i) => predicate(item)); - } - - /// - /// Returns elements from a sequence as long as a specified condition is true. - /// The element's index is used in the logic of the predicate function. - /// - - public static IEnumerable TakeWhile( - this IEnumerable source, - Func predicate) - { - if (source == null) throw new ArgumentNullException("source"); - if (predicate == null) throw new ArgumentNullException("predicate"); - - return TakeWhileYield(source, predicate); - } - - private static IEnumerable TakeWhileYield( - this IEnumerable source, - Func predicate) - { - var i = 0; - foreach (var item in source) - if (predicate(item, i++)) - yield return item; - else - break; - } - - /// - /// Returns a specified number of contiguous elements from the start - /// of a sequence. - /// - - public static IEnumerable Take( - this IEnumerable source, - int count) - { - return source.TakeWhile((item, i) => i < count); - } - - private static class Futures - { - public static readonly Func Default = () => default(T); - public static readonly Func Undefined = () => { throw new InvalidOperationException(); }; - } - - /// - /// Base implementation of First operator. - /// - - private static TSource FirstImpl( - this IEnumerable source, - Func empty) - { - if (source == null) throw new ArgumentNullException("source"); - Debug.Assert(empty != null); - - var list = source as IList; // optimized case for lists - if (list != null) - return list.Count > 0 ? list[0] : empty(); - - using (var e = source.GetEnumerator()) // fallback for enumeration - return e.MoveNext() ? e.Current : empty(); - } - - /// - /// Returns the first element of a sequence. - /// - - public static TSource First( - this IEnumerable source) - { - return source.FirstImpl(Futures.Undefined); - } - - /// - /// Returns the first element in a sequence that satisfies a specified condition. - /// - - public static TSource First( - this IEnumerable source, - Func predicate) - { - return First(source.Where(predicate)); - } - - /// - /// Returns the first element of a sequence, or a default value if - /// the sequence contains no elements. - /// - - public static TSource FirstOrDefault( - this IEnumerable source) - { - return source.FirstImpl(Futures.Default); - } - - /// - /// Returns the first element of the sequence that satisfies a - /// condition or a default value if no such element is found. - /// - - public static TSource FirstOrDefault( - this IEnumerable source, - Func predicate) - { - return FirstOrDefault(source.Where(predicate)); - } - - /// - /// Base implementation of Last operator. - /// - - private static TSource LastImpl( - this IEnumerable source, - Func empty) - { - if (source == null) throw new ArgumentNullException("source"); - - var list = source as IList; // optimized case for lists - if (list != null) - return list.Count > 0 ? list[list.Count - 1] : empty(); - - using (var e = source.GetEnumerator()) - { - if (!e.MoveNext()) - return empty(); - - var last = e.Current; - while (e.MoveNext()) - last = e.Current; - - return last; - } - } - - /// - /// Returns the last element of a sequence. - /// - public static TSource Last( - this IEnumerable source) - { - return source.LastImpl(Futures.Undefined); - } - - /// - /// Returns the last element of a sequence that satisfies a - /// specified condition. - /// - - public static TSource Last( - this IEnumerable source, - Func predicate) - { - return Last(source.Where(predicate)); - } - - /// - /// Returns the last element of a sequence, or a default value if - /// the sequence contains no elements. - /// - - public static TSource LastOrDefault( - this IEnumerable source) - { - return source.LastImpl(Futures.Default); - } - - /// - /// Returns the last element of a sequence that satisfies a - /// condition or a default value if no such element is found. - /// - - public static TSource LastOrDefault( - this IEnumerable source, - Func predicate) - { - return LastOrDefault(source.Where(predicate)); - } - - /// - /// Base implementation of Single operator. - /// - - private static TSource SingleImpl( - this IEnumerable source, - Func empty) - { - if (source == null) throw new ArgumentNullException("source"); - - using (var e = source.GetEnumerator()) - { - if (e.MoveNext()) - { - var single = e.Current; - if (!e.MoveNext()) - return single; - - throw new InvalidOperationException(); - } - - return empty(); - } - } - - /// - /// Returns the only element of a sequence, and throws an exception - /// if there is not exactly one element in the sequence. - /// - - public static TSource Single( - this IEnumerable source) - { - return source.SingleImpl(Futures.Undefined); - } - - /// - /// Returns the only element of a sequence that satisfies a - /// specified condition, and throws an exception if more than one - /// such element exists. - /// - - public static TSource Single( - this IEnumerable source, - Func predicate) - { - return Single(source.Where(predicate)); - } - - /// - /// Returns the only element of a sequence, or a default value if - /// the sequence is empty; this method throws an exception if there - /// is more than one element in the sequence. - /// - - public static TSource SingleOrDefault( - this IEnumerable source) - { - return source.SingleImpl(Futures.Default); - } - - /// - /// Returns the only element of a sequence that satisfies a - /// specified condition or a default value if no such element - /// exists; this method throws an exception if more than one element - /// satisfies the condition. - /// - - public static TSource SingleOrDefault( - this IEnumerable source, - Func predicate) - { - return SingleOrDefault(source.Where(predicate)); - } - - /// - /// Returns the element at a specified index in a sequence. - /// - - public static TSource ElementAt( - this IEnumerable source, - int index) - { - if (source == null) throw new ArgumentNullException("source"); - - if (index < 0) - throw new ArgumentOutOfRangeException("index", index, null); - - var list = source as IList; - if (list != null) - return list[index]; - - try - { - return source.SkipWhile((item, i) => i < index).First(); - } - catch (InvalidOperationException) // if thrown by First - { - throw new ArgumentOutOfRangeException("index", index, null); - } - } - - /// - /// Returns the element at a specified index in a sequence or a - /// default value if the index is out of range. - /// - - public static TSource ElementAtOrDefault( - this IEnumerable source, - int index) - { - if (source == null) throw new ArgumentNullException("source"); - - if (index < 0) - return default(TSource); - - var list = source as IList; - if (list != null) - return index < list.Count ? list[index] : default(TSource); - - return source.SkipWhile((item, i) => i < index).FirstOrDefault(); - } - - /// - /// Inverts the order of the elements in a sequence. - /// - - public static IEnumerable Reverse( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return ReverseYield(source); - } - - private static IEnumerable ReverseYield(IEnumerable source) - { - var stack = new Stack(); - foreach (var item in source) - stack.Push(item); - - foreach (var item in stack) - yield return item; - } - - /// - /// Bypasses elements in a sequence as long as a specified condition - /// is true and then returns the remaining elements. - /// - - public static IEnumerable SkipWhile( - this IEnumerable source, - Func predicate) - { - if (predicate == null) throw new ArgumentNullException("predicate"); - - return source.SkipWhile((item, i) => predicate(item)); - } - - /// - /// Bypasses elements in a sequence as long as a specified condition - /// is true and then returns the remaining elements. The element's - /// index is used in the logic of the predicate function. - /// - - public static IEnumerable SkipWhile( - this IEnumerable source, - Func predicate) - { - if (source == null) throw new ArgumentNullException("source"); - if (predicate == null) throw new ArgumentNullException("predicate"); - - return SkipWhileYield(source, predicate); - } - - private static IEnumerable SkipWhileYield( - IEnumerable source, - Func predicate) - { - using (var e = source.GetEnumerator()) - { - for (var i = 0; ; i++) - { - if (!e.MoveNext()) - yield break; - - if (!predicate(e.Current, i)) - break; - } - - do { yield return e.Current; } while (e.MoveNext()); - } - } - - /// - /// Bypasses a specified number of elements in a sequence and then - /// returns the remaining elements. - /// - - public static IEnumerable Skip( - this IEnumerable source, - int count) - { - return source.SkipWhile((item, i) => i < count); - } - - /// - /// Returns the number of elements in a sequence. - /// - - public static int Count( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - var collection = source as ICollection; - return collection != null - ? collection.Count - : source.Aggregate(0, (count, item) => checked(count + 1)); - } - - /// - /// Returns a number that represents how many elements in the - /// specified sequence satisfy a condition. - /// - - public static int Count( - this IEnumerable source, - Func predicate) - { - return Count(source.Where(predicate)); - } - - /// - /// Returns an that represents the total number - /// of elements in a sequence. - /// - - public static long LongCount( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - var array = source as Array; - return array != null - ? array.LongLength - : source.Aggregate(0L, (count, item) => count + 1); - } - - /// - /// Returns an that represents how many elements - /// in a sequence satisfy a condition. - /// - - public static long LongCount( - this IEnumerable source, - Func predicate) - { - return LongCount(source.Where(predicate)); - } - - /// - /// Concatenates two sequences. - /// - - public static IEnumerable Concat( - this IEnumerable first, - IEnumerable second) - { - if (first == null) throw new ArgumentNullException("first"); - if (second == null) throw new ArgumentNullException("second"); - - return ConcatYield(first, second); - } - - private static IEnumerable ConcatYield( - IEnumerable first, - IEnumerable second) - { - foreach (var item in first) - yield return item; - - foreach (var item in second) - yield return item; - } - - /// - /// Creates a from an . - /// - - public static List ToList( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return new List(source); - } - - /// - /// Creates an array from an . - /// - - public static TSource[] ToArray( - this IEnumerable source) - { - return source.ToList().ToArray(); - } - - /// - /// Returns distinct elements from a sequence by using the default - /// equality comparer to compare values. - /// - - public static IEnumerable Distinct( - this IEnumerable source) - { - return Distinct(source, /* comparer */ null); - } - - /// - /// Returns distinct elements from a sequence by using a specified - /// to compare values. - /// - - public static IEnumerable Distinct( - this IEnumerable source, - IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - - return DistinctYield(source, comparer); - } - - private static IEnumerable DistinctYield( - IEnumerable source, - IEqualityComparer comparer) - { - var set = new Dictionary(comparer); - var gotNull = false; - - foreach (var item in source) - { - if (item == null) - { - if (gotNull) - continue; - gotNull = true; - } - else - { - if (set.ContainsKey(item)) - continue; - set.Add(item, null); - } - - yield return item; - } - } - - /// - /// Creates a from an - /// according to a specified key - /// selector function. - /// - - public static ILookup ToLookup( - this IEnumerable source, - Func keySelector) - { - return ToLookup(source, keySelector, e => e, /* comparer */ null); - } - - /// - /// Creates a from an - /// according to a specified key - /// selector function and a key comparer. - /// - - public static ILookup ToLookup( - this IEnumerable source, - Func keySelector, - IEqualityComparer comparer) - { - return ToLookup(source, keySelector, e => e, comparer); - } - - /// - /// Creates a from an - /// according to specified key - /// and element selector functions. - /// - - public static ILookup ToLookup( - this IEnumerable source, - Func keySelector, - Func elementSelector) - { - return ToLookup(source, keySelector, elementSelector, /* comparer */ null); - } - - /// - /// Creates a from an - /// according to a specified key - /// selector function, a comparer and an element selector function. - /// - - public static ILookup ToLookup( - this IEnumerable source, - Func keySelector, - Func elementSelector, - IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - if (elementSelector == null) throw new ArgumentNullException("elementSelector"); - - var lookup = new Lookup(comparer); - - foreach (var item in source) - { - var key = keySelector(item); - - var grouping = (Grouping) lookup.Find(key); - if (grouping == null) - { - grouping = new Grouping(key); - lookup.Add(grouping); - } - - grouping.Add(elementSelector(item)); - } - - return lookup; - } - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function. - /// - - public static IEnumerable> GroupBy( - this IEnumerable source, - Func keySelector) - { - return GroupBy(source, keySelector, /* comparer */ null); - } - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and compares the keys by using a specified - /// comparer. - /// - - public static IEnumerable> GroupBy( - this IEnumerable source, - Func keySelector, - IEqualityComparer comparer) - { - return GroupBy(source, keySelector, e => e, comparer); - } - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and projects the elements for each group by - /// using a specified function. - /// - - public static IEnumerable> GroupBy( - this IEnumerable source, - Func keySelector, - Func elementSelector) - { - return GroupBy(source, keySelector, elementSelector, /* comparer */ null); - } - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and creates a result value from each group and - /// its key. - /// - - public static IEnumerable> GroupBy( - this IEnumerable source, - Func keySelector, - Func elementSelector, - IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - if (elementSelector == null) throw new ArgumentNullException("elementSelector"); - - return ToLookup(source, keySelector, elementSelector, comparer); - } - - /// - /// Groups the elements of a sequence according to a key selector - /// function. The keys are compared by using a comparer and each - /// group's elements are projected by using a specified function. - /// - - public static IEnumerable GroupBy( - this IEnumerable source, - Func keySelector, - Func, TResult> resultSelector) - { - return GroupBy(source, keySelector, resultSelector, /* comparer */ null); - } - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and creates a result value from each group and - /// its key. The elements of each group are projected by using a - /// specified function. - /// - - public static IEnumerable GroupBy( - this IEnumerable source, - Func keySelector, - Func, TResult> resultSelector, - IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - - return ToLookup(source, keySelector, comparer).Select(g => resultSelector(g.Key, g)); - } - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and creates a result value from each group and - /// its key. The keys are compared by using a specified comparer. - /// - - public static IEnumerable GroupBy( - this IEnumerable source, - Func keySelector, - Func elementSelector, - Func, TResult> resultSelector) - { - return GroupBy(source, keySelector, elementSelector, resultSelector, /* comparer */ null); - } - - /// - /// Groups the elements of a sequence according to a specified key - /// selector function and creates a result value from each group and - /// its key. Key values are compared by using a specified comparer, - /// and the elements of each group are projected by using a - /// specified function. - /// - - public static IEnumerable GroupBy( - this IEnumerable source, - Func keySelector, - Func elementSelector, - Func, TResult> resultSelector, - IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - if (elementSelector == null) throw new ArgumentNullException("elementSelector"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - - return ToLookup(source, keySelector, elementSelector, comparer) - .Select(g => resultSelector(g.Key, g)); - } - - /// - /// Applies an accumulator function over a sequence. - /// - - public static TSource Aggregate( - this IEnumerable source, - Func func) - { - if (source == null) throw new ArgumentNullException("source"); - if (func == null) throw new ArgumentNullException("func"); - - using (var e = source.GetEnumerator()) - { - if (!e.MoveNext()) - throw new InvalidOperationException(); - - return e.Renumerable().Skip(1).Aggregate(e.Current, func); - } - } - - /// - /// Applies an accumulator function over a sequence. The specified - /// seed value is used as the initial accumulator value. - /// - - public static TAccumulate Aggregate( - this IEnumerable source, - TAccumulate seed, - Func func) - { - return Aggregate(source, seed, func, r => r); - } - - /// - /// Applies an accumulator function over a sequence. The specified - /// seed value is used as the initial accumulator value, and the - /// specified function is used to select the result value. - /// - - public static TResult Aggregate( - this IEnumerable source, - TAccumulate seed, - Func func, - Func resultSelector) - { - if (source == null) throw new ArgumentNullException("source"); - if (func == null) throw new ArgumentNullException("func"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - - var result = seed; - - foreach (var item in source) - result = func(result, item); - - return resultSelector(result); - } - - /// - /// Produces the set union of two sequences by using the default - /// equality comparer. - /// - - public static IEnumerable Union( - this IEnumerable first, - IEnumerable second) - { - return Union(first, second, /* comparer */ null); - } - - /// - /// Produces the set union of two sequences by using a specified - /// . - /// - - public static IEnumerable Union( - this IEnumerable first, - IEnumerable second, - IEqualityComparer comparer) - { - return first.Concat(second).Distinct(comparer); - } - - /// - /// Returns the elements of the specified sequence or the type - /// parameter's default value in a singleton collection if the - /// sequence is empty. - /// - - public static IEnumerable DefaultIfEmpty( - this IEnumerable source) - { - return source.DefaultIfEmpty(default(TSource)); - } - - /// - /// Returns the elements of the specified sequence or the specified - /// value in a singleton collection if the sequence is empty. - /// - - public static IEnumerable DefaultIfEmpty( - this IEnumerable source, - TSource defaultValue) - { - if (source == null) throw new ArgumentNullException("source"); - - return DefaultIfEmptyYield(source, defaultValue); - } - - private static IEnumerable DefaultIfEmptyYield( - IEnumerable source, - TSource defaultValue) - { - using (var e = source.GetEnumerator()) - { - if (!e.MoveNext()) - yield return defaultValue; - else - do { yield return e.Current; } while (e.MoveNext()); - } - } - - /// - /// Determines whether all elements of a sequence satisfy a condition. - /// - - public static bool All( - this IEnumerable source, - Func predicate) - { - if (source == null) throw new ArgumentNullException("source"); - if (predicate == null) throw new ArgumentNullException("predicate"); - - foreach (var item in source) - if (!predicate(item)) - return false; - - return true; - } - - /// - /// Determines whether a sequence contains any elements. - /// - - public static bool Any( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - using (var e = source.GetEnumerator()) - return e.MoveNext(); - } - - /// - /// Determines whether any element of a sequence satisfies a - /// condition. - /// - - public static bool Any( - this IEnumerable source, - Func predicate) - { - return source.Where(predicate).Any(); - } - - /// - /// Determines whether a sequence contains a specified element by - /// using the default equality comparer. - /// - - public static bool Contains( - this IEnumerable source, - TSource value) - { - return source.Contains(value, /* comparer */ null); - } - - /// - /// Determines whether a sequence contains a specified element by - /// using a specified . - /// - - public static bool Contains( - this IEnumerable source, - TSource value, - IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - - if (comparer == null) - { - var collection = source as ICollection; - if (collection != null) - return collection.Contains(value); - } - - comparer = comparer ?? EqualityComparer.Default; - return source.Any(item => comparer.Equals(item, value)); - } - - /// - /// Determines whether two sequences are equal by comparing the - /// elements by using the default equality comparer for their type. - /// - - public static bool SequenceEqual( - this IEnumerable first, - IEnumerable second) - { - return first.SequenceEqual(second, /* comparer */ null); - } - - /// - /// Determines whether two sequences are equal by comparing their - /// elements by using a specified . - /// - - public static bool SequenceEqual( - this IEnumerable first, - IEnumerable second, - IEqualityComparer comparer) - { - if (first == null) throw new ArgumentNullException("frist"); - if (second == null) throw new ArgumentNullException("second"); - - comparer = comparer ?? EqualityComparer.Default; - - using (IEnumerator lhs = first.GetEnumerator(), - rhs = second.GetEnumerator()) - { - do - { - if (!lhs.MoveNext()) - return !rhs.MoveNext(); - - if (!rhs.MoveNext()) - return false; - } - while (comparer.Equals(lhs.Current, rhs.Current)); - } - - return false; - } - - /// - /// Base implementation for Min/Max operator. - /// - - private static TSource MinMaxImpl( - this IEnumerable source, - Func lesser) - { - if (source == null) throw new ArgumentNullException("source"); - Debug.Assert(lesser != null); - - if (typeof(TSource).IsClass) // ReSharper disable CompareNonConstrainedGenericWithNull - source = source.Where(e => e != null).DefaultIfEmpty(); // ReSharper restore CompareNonConstrainedGenericWithNull - - return source.Aggregate((a, item) => lesser(a, item) ? a : item); - } - - /// - /// Base implementation for Min/Max operator for nullable types. - /// - - private static TSource? MinMaxImpl( - this IEnumerable source, - TSource? seed, Func lesser) where TSource : struct - { - if (source == null) throw new ArgumentNullException("source"); - Debug.Assert(lesser != null); - - return source.Aggregate(seed, (a, item) => lesser(a, item) ? a : item); - // == MinMaxImpl(Repeat(null, 1).Concat(source), lesser); - } - - /// - /// Returns the minimum value in a generic sequence. - /// - - public static TSource Min( - this IEnumerable source) - { - var comparer = Comparer.Default; - return source.MinMaxImpl((x, y) => comparer.Compare(x, y) < 0); - } - - /// - /// Invokes a transform function on each element of a generic - /// sequence and returns the minimum resulting value. - /// - - public static TResult Min( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Min(); - } - - /// - /// Returns the maximum value in a generic sequence. - /// - - public static TSource Max( - this IEnumerable source) - { - var comparer = Comparer.Default; - return source.MinMaxImpl((x, y) => comparer.Compare(x, y) > 0); - } - - /// - /// Invokes a transform function on each element of a generic - /// sequence and returns the maximum resulting value. - /// - - public static TResult Max( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Max(); - } - - /// - /// Makes an enumerator seen as enumerable once more. - /// - /// - /// The supplied enumerator must have been started. The first element - /// returned is the element the enumerator was on when passed in. - /// DO NOT use this method if the caller must be a generator. It is - /// mostly safe among aggregate operations. - /// - - private static IEnumerable Renumerable(this IEnumerator e) - { - Debug.Assert(e != null); - - do { yield return e.Current; } while (e.MoveNext()); - } - - /// - /// Sorts the elements of a sequence in ascending order according to a key. - /// - - public static IOrderedEnumerable OrderBy( - this IEnumerable source, - Func keySelector) - { - return source.OrderBy(keySelector, /* comparer */ null); - } - - /// - /// Sorts the elements of a sequence in ascending order by using a - /// specified comparer. - /// - - public static IOrderedEnumerable OrderBy( - this IEnumerable source, - Func keySelector, - IComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - - return new OrderedEnumerable(source, keySelector, comparer, /* descending */ false); - } - - /// - /// Sorts the elements of a sequence in descending order according to a key. - /// - - public static IOrderedEnumerable OrderByDescending( - this IEnumerable source, - Func keySelector) - { - return source.OrderByDescending(keySelector, /* comparer */ null); - } - - /// - /// Sorts the elements of a sequence in descending order by using a - /// specified comparer. - /// - - public static IOrderedEnumerable OrderByDescending( - this IEnumerable source, - Func keySelector, - IComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (source == null) throw new ArgumentNullException("keySelector"); - - return new OrderedEnumerable(source, keySelector, comparer, /* descending */ true); - } - - /// - /// Performs a subsequent ordering of the elements in a sequence in - /// ascending order according to a key. - /// - - public static IOrderedEnumerable ThenBy( - this IOrderedEnumerable source, - Func keySelector) - { - return source.ThenBy(keySelector, /* comparer */ null); - } - - /// - /// Performs a subsequent ordering of the elements in a sequence in - /// ascending order by using a specified comparer. - /// - - public static IOrderedEnumerable ThenBy( - this IOrderedEnumerable source, - Func keySelector, - IComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - - return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ false); - } - - /// - /// Performs a subsequent ordering of the elements in a sequence in - /// descending order, according to a key. - /// - - public static IOrderedEnumerable ThenByDescending( - this IOrderedEnumerable source, - Func keySelector) - { - return source.ThenByDescending(keySelector, /* comparer */ null); - } - - /// - /// Performs a subsequent ordering of the elements in a sequence in - /// descending order by using a specified comparer. - /// - - public static IOrderedEnumerable ThenByDescending( - this IOrderedEnumerable source, - Func keySelector, - IComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - - return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ true); - } - - /// - /// Base implementation for Intersect and Except operators. - /// - - private static IEnumerable IntersectExceptImpl( - this IEnumerable first, - IEnumerable second, - IEqualityComparer comparer, - bool flag) - { - if (first == null) throw new ArgumentNullException("first"); - if (second == null) throw new ArgumentNullException("second"); - - var keys = new List>(); - var flags = new Dictionary, bool>(new KeyComparer(comparer)); - - foreach (var item in from item in first - select new Key(item) into item - where !flags.ContainsKey(item) - select item) - { - flags.Add(item, !flag); - keys.Add(item); - } - - foreach (var item in from item in second - select new Key(item) into item - where flags.ContainsKey(item) - select item) - { - flags[item] = flag; - } - - // - // As per docs, "the marked elements are yielded in the order in - // which they were collected. - // - - return from item in keys where flags[item] select item.Value; - } - - /// - /// Produces the set intersection of two sequences by using the - /// default equality comparer to compare values. - /// - - public static IEnumerable Intersect( - this IEnumerable first, - IEnumerable second) - { - return first.Intersect(second, /* comparer */ null); - } - - /// - /// Produces the set intersection of two sequences by using the - /// specified to compare values. - /// - - public static IEnumerable Intersect( - this IEnumerable first, - IEnumerable second, - IEqualityComparer comparer) - { - return IntersectExceptImpl(first, second, comparer, /* flag */ true); - } - - /// - /// Produces the set difference of two sequences by using the - /// default equality comparer to compare values. - /// - - public static IEnumerable Except( - this IEnumerable first, - IEnumerable second) - { - return first.Except(second, /* comparer */ null); - } - - /// - /// Produces the set difference of two sequences by using the - /// specified to compare values. - /// - - public static IEnumerable Except( - this IEnumerable first, - IEnumerable second, - IEqualityComparer comparer) - { - return IntersectExceptImpl(first, second, comparer, /* flag */ false); - } - - /// - /// Creates a from an - /// according to a specified key - /// selector function. - /// - - public static Dictionary ToDictionary( - this IEnumerable source, - Func keySelector) - { - return source.ToDictionary(keySelector, /* comparer */ null); - } - - /// - /// Creates a from an - /// according to a specified key - /// selector function and key comparer. - /// - - public static Dictionary ToDictionary( - this IEnumerable source, - Func keySelector, - IEqualityComparer comparer) - { - return source.ToDictionary(keySelector, e => e, comparer); - } - - /// - /// Creates a from an - /// according to specified key - /// selector and element selector functions. - /// - - public static Dictionary ToDictionary( - this IEnumerable source, - Func keySelector, - Func elementSelector) - { - return source.ToDictionary(keySelector, elementSelector, /* comparer */ null); - } - - /// - /// Creates a from an - /// according to a specified key - /// selector function, a comparer, and an element selector function. - /// - - public static Dictionary ToDictionary( - this IEnumerable source, - Func keySelector, - Func elementSelector, - IEqualityComparer comparer) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - if (elementSelector == null) throw new ArgumentNullException("elementSelector"); - - var dict = new Dictionary(comparer); - - foreach (var item in source) - { - // - // ToDictionary is meant to throw ArgumentNullException if - // keySelector produces a key that is null and - // Argument exception if keySelector produces duplicate keys - // for two elements. Incidentally, the doucmentation for - // IDictionary.Add says that the Add method - // throws the same exceptions under the same circumstances - // so we don't need to do any additional checking or work - // here and let the Add implementation do all the heavy - // lifting. - // - - dict.Add(keySelector(item), elementSelector(item)); - } - - return dict; - } - - /// - /// Correlates the elements of two sequences based on matching keys. - /// The default equality comparer is used to compare keys. - /// - - public static IEnumerable Join( - this IEnumerable outer, - IEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - Func resultSelector) - { - return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null); - } - - /// - /// Correlates the elements of two sequences based on matching keys. - /// The default equality comparer is used to compare keys. A - /// specified is used to compare keys. - /// - - public static IEnumerable Join( - this IEnumerable outer, - IEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - Func resultSelector, - IEqualityComparer comparer) - { - if (outer == null) throw new ArgumentNullException("outer"); - if (inner == null) throw new ArgumentNullException("inner"); - if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector"); - if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - - var lookup = inner.ToLookup(innerKeySelector, comparer); - - return - from o in outer - from i in lookup[outerKeySelector(o)] - select resultSelector(o, i); - } - - /// - /// Correlates the elements of two sequences based on equality of - /// keys and groups the results. The default equality comparer is - /// used to compare keys. - /// - - public static IEnumerable GroupJoin( - this IEnumerable outer, - IEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - Func, TResult> resultSelector) - { - return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null); - } - - /// - /// Correlates the elements of two sequences based on equality of - /// keys and groups the results. The default equality comparer is - /// used to compare keys. A specified - /// is used to compare keys. - /// - - public static IEnumerable GroupJoin( - this IEnumerable outer, - IEnumerable inner, - Func outerKeySelector, - Func innerKeySelector, - Func, TResult> resultSelector, - IEqualityComparer comparer) - { - if (outer == null) throw new ArgumentNullException("outer"); - if (inner == null) throw new ArgumentNullException("inner"); - if (outerKeySelector == null) throw new ArgumentNullException("outerKeySelector"); - if (innerKeySelector == null) throw new ArgumentNullException("innerKeySelector"); - if (resultSelector == null) throw new ArgumentNullException("resultSelector"); - - var lookup = inner.ToLookup(innerKeySelector, comparer); - return outer.Select(o => resultSelector(o, lookup[outerKeySelector(o)])); - } - - private static class Sequence - { - public static readonly IEnumerable Empty = new T[0]; - } - - private sealed class Grouping : List, IGrouping - { - internal Grouping(K key) - { - Key = key; - } - - public K Key { get; private set; } - } - } -} - -// $Id: Enumerable.g.tt 71137f497bf2 2012/04/16 20:01:27 azizatif $ - -namespace System.Linq -{ - #region Imports - - using System; - using System.Collections.Generic; - - #endregion - - // This partial implementation was template-generated: - // Mon, 16 Apr 2012 20:05:53 GMT - - partial class Enumerable - { - /// - /// Computes the sum of a sequence of nullable values. - /// - - public static int Sum( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - int sum = 0; - foreach (var num in source) - sum = checked(sum + num); - - return sum; - } - - /// - /// Computes the sum of a sequence of nullable - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - - public static int Sum( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Sum(); - } - - /// - /// Computes the average of a sequence of nullable values. - /// - - public static double Average( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - long sum = 0; - long count = 0; - - foreach (var num in source) - checked - { - sum += (int) num; - count++; - } - - if (count == 0) - throw new InvalidOperationException(); - - return (double) sum / count; - } - - /// - /// Computes the average of a sequence of nullable values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - - public static double Average( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Average(); - } - - - /// - /// Computes the sum of a sequence of values. - /// - - public static int? Sum( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - int sum = 0; - foreach (var num in source) - sum = checked(sum + (num ?? 0)); - - return sum; - } - - /// - /// Computes the sum of a sequence of - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - - public static int? Sum( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Sum(); - } - - /// - /// Computes the average of a sequence of values. - /// - - public static double? Average( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - long sum = 0; - long count = 0; - - foreach (var num in source.Where(n => n != null)) - checked - { - sum += (int) num; - count++; - } - - if (count == 0) - return null; - - return (double?) sum / count; - } - - /// - /// Computes the average of a sequence of values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - - public static double? Average( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Average(); - } - - /// - /// Returns the minimum value in a sequence of nullable - /// values. - /// - - public static int? Min( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the minimum nullable value. - /// - - public static int? Min( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Min(); - } - - /// - /// Returns the maximum value in a sequence of nullable - /// values. - /// - - public static int? Max( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return MinMaxImpl(source.Where(x => x != null), - null, (max, x) => x == null || (max != null && x.Value < max.Value)); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the maximum nullable value. - /// - - public static int? Max( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Max(); - } - - /// - /// Computes the sum of a sequence of nullable values. - /// - - public static long Sum( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - long sum = 0; - foreach (var num in source) - sum = checked(sum + num); - - return sum; - } - - /// - /// Computes the sum of a sequence of nullable - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - - public static long Sum( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Sum(); - } - - /// - /// Computes the average of a sequence of nullable values. - /// - - public static double Average( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - long sum = 0; - long count = 0; - - foreach (var num in source) - checked - { - sum += (long) num; - count++; - } - - if (count == 0) - throw new InvalidOperationException(); - - return (double) sum / count; - } - - /// - /// Computes the average of a sequence of nullable values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - - public static double Average( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Average(); - } - - - /// - /// Computes the sum of a sequence of values. - /// - - public static long? Sum( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - long sum = 0; - foreach (var num in source) - sum = checked(sum + (num ?? 0)); - - return sum; - } - - /// - /// Computes the sum of a sequence of - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - - public static long? Sum( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Sum(); - } - - /// - /// Computes the average of a sequence of values. - /// - - public static double? Average( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - long sum = 0; - long count = 0; - - foreach (var num in source.Where(n => n != null)) - checked - { - sum += (long) num; - count++; - } - - if (count == 0) - return null; - - return (double?) sum / count; - } - - /// - /// Computes the average of a sequence of values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - - public static double? Average( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Average(); - } - - /// - /// Returns the minimum value in a sequence of nullable - /// values. - /// - - public static long? Min( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the minimum nullable value. - /// - - public static long? Min( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Min(); - } - - /// - /// Returns the maximum value in a sequence of nullable - /// values. - /// - - public static long? Max( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return MinMaxImpl(source.Where(x => x != null), - null, (max, x) => x == null || (max != null && x.Value < max.Value)); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the maximum nullable value. - /// - - public static long? Max( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Max(); - } - - /// - /// Computes the sum of a sequence of nullable values. - /// - - public static float Sum( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - float sum = 0; - foreach (var num in source) - sum = checked(sum + num); - - return sum; - } - - /// - /// Computes the sum of a sequence of nullable - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - - public static float Sum( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Sum(); - } - - /// - /// Computes the average of a sequence of nullable values. - /// - - public static float Average( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - float sum = 0; - long count = 0; - - foreach (var num in source) - checked - { - sum += (float) num; - count++; - } - - if (count == 0) - throw new InvalidOperationException(); - - return (float) sum / count; - } - - /// - /// Computes the average of a sequence of nullable values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - - public static float Average( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Average(); - } - - - /// - /// Computes the sum of a sequence of values. - /// - - public static float? Sum( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - float sum = 0; - foreach (var num in source) - sum = checked(sum + (num ?? 0)); - - return sum; - } - - /// - /// Computes the sum of a sequence of - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - - public static float? Sum( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Sum(); - } - - /// - /// Computes the average of a sequence of values. - /// - - public static float? Average( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - float sum = 0; - long count = 0; - - foreach (var num in source.Where(n => n != null)) - checked - { - sum += (float) num; - count++; - } - - if (count == 0) - return null; - - return (float?) sum / count; - } - - /// - /// Computes the average of a sequence of values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - - public static float? Average( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Average(); - } - - /// - /// Returns the minimum value in a sequence of nullable - /// values. - /// - - public static float? Min( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the minimum nullable value. - /// - - public static float? Min( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Min(); - } - - /// - /// Returns the maximum value in a sequence of nullable - /// values. - /// - - public static float? Max( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return MinMaxImpl(source.Where(x => x != null), - null, (max, x) => x == null || (max != null && x.Value < max.Value)); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the maximum nullable value. - /// - - public static float? Max( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Max(); - } - - /// - /// Computes the sum of a sequence of nullable values. - /// - - public static double Sum( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - double sum = 0; - foreach (var num in source) - sum = checked(sum + num); - - return sum; - } - - /// - /// Computes the sum of a sequence of nullable - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - - public static double Sum( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Sum(); - } - - /// - /// Computes the average of a sequence of nullable values. - /// - - public static double Average( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - double sum = 0; - long count = 0; - - foreach (var num in source) - checked - { - sum += (double) num; - count++; - } - - if (count == 0) - throw new InvalidOperationException(); - - return (double) sum / count; - } - - /// - /// Computes the average of a sequence of nullable values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - - public static double Average( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Average(); - } - - - /// - /// Computes the sum of a sequence of values. - /// - - public static double? Sum( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - double sum = 0; - foreach (var num in source) - sum = checked(sum + (num ?? 0)); - - return sum; - } - - /// - /// Computes the sum of a sequence of - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - - public static double? Sum( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Sum(); - } - - /// - /// Computes the average of a sequence of values. - /// - - public static double? Average( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - double sum = 0; - long count = 0; - - foreach (var num in source.Where(n => n != null)) - checked - { - sum += (double) num; - count++; - } - - if (count == 0) - return null; - - return (double?) sum / count; - } - - /// - /// Computes the average of a sequence of values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - - public static double? Average( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Average(); - } - - /// - /// Returns the minimum value in a sequence of nullable - /// values. - /// - - public static double? Min( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the minimum nullable value. - /// - - public static double? Min( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Min(); - } - - /// - /// Returns the maximum value in a sequence of nullable - /// values. - /// - - public static double? Max( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return MinMaxImpl(source.Where(x => x != null), - null, (max, x) => x == null || (max != null && x.Value < max.Value)); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the maximum nullable value. - /// - - public static double? Max( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Max(); - } - - /// - /// Computes the sum of a sequence of nullable values. - /// - - public static decimal Sum( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - decimal sum = 0; - foreach (var num in source) - sum = checked(sum + num); - - return sum; - } - - /// - /// Computes the sum of a sequence of nullable - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - - public static decimal Sum( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Sum(); - } - - /// - /// Computes the average of a sequence of nullable values. - /// - - public static decimal Average( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - decimal sum = 0; - long count = 0; - - foreach (var num in source) - checked - { - sum += (decimal) num; - count++; - } - - if (count == 0) - throw new InvalidOperationException(); - - return (decimal) sum / count; - } - - /// - /// Computes the average of a sequence of nullable values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - - public static decimal Average( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Average(); - } - - - /// - /// Computes the sum of a sequence of values. - /// - - public static decimal? Sum( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - decimal sum = 0; - foreach (var num in source) - sum = checked(sum + (num ?? 0)); - - return sum; - } - - /// - /// Computes the sum of a sequence of - /// values that are obtained by invoking a transform function on - /// each element of the input sequence. - /// - - public static decimal? Sum( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Sum(); - } - - /// - /// Computes the average of a sequence of values. - /// - - public static decimal? Average( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - decimal sum = 0; - long count = 0; - - foreach (var num in source.Where(n => n != null)) - checked - { - sum += (decimal) num; - count++; - } - - if (count == 0) - return null; - - return (decimal?) sum / count; - } - - /// - /// Computes the average of a sequence of values - /// that are obtained by invoking a transform function on each - /// element of the input sequence. - /// - - public static decimal? Average( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Average(); - } - - /// - /// Returns the minimum value in a sequence of nullable - /// values. - /// - - public static decimal? Min( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the minimum nullable value. - /// - - public static decimal? Min( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Min(); - } - - /// - /// Returns the maximum value in a sequence of nullable - /// values. - /// - - public static decimal? Max( - this IEnumerable source) - { - if (source == null) throw new ArgumentNullException("source"); - - return MinMaxImpl(source.Where(x => x != null), - null, (max, x) => x == null || (max != null && x.Value < max.Value)); - } - - /// - /// Invokes a transform function on each element of a sequence and - /// returns the maximum nullable value. - /// - - public static decimal? Max( - this IEnumerable source, - Func selector) - { - return source.Select(selector).Max(); - } - } -} - -// $Id: ExtensionAttribute.cs 898b3d493ed6 2012/04/17 20:09:57 azizatif $ - -namespace System.Runtime.CompilerServices -{ - /// - /// This attribute allows us to define extension methods without - /// requiring .NET Framework 3.5. For more information, see the section, - /// Extension Methods in .NET Framework 2.0 Apps, - /// of Basic Instincts: Extension Methods - /// column in MSDN Magazine, - /// issue Nov 2007. - /// - - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)] - sealed partial class ExtensionAttribute : Attribute { } -} - -// $Id: Func.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ - -namespace System -{ -#if LINQBRIDGE_LIB - public delegate TResult Func(); - public delegate TResult Func(T a); - public delegate TResult Func(T1 arg1, T2 arg2); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); -#else - delegate TResult Func(); - delegate TResult Func(T a); - delegate TResult Func(T1 arg1, T2 arg2); - delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); - delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); -#endif -} - -// $Id: IGrouping.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ - -namespace System.Linq -{ - #region Imports - - using System.Collections.Generic; - - #endregion - - /// - /// Represents a collection of objects that have a common key. - /// - - partial interface IGrouping : IEnumerable - { - /// - /// Gets the key of the . - /// - - TKey Key { get; } - } -} - -// $Id: ILookup.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ - -namespace System.Linq -{ - using System.Collections.Generic; - - /// - /// Defines an indexer, size property, and Boolean search method for - /// data structures that map keys to - /// sequences of values. - /// - - partial interface ILookup : IEnumerable> - { - bool Contains(TKey key); - int Count { get; } - IEnumerable this[TKey key] { get; } - } -} - -// $Id: Internal.cs 1567e00f1a20 2012/04/17 16:09:51 azizatif $ - -namespace LinqBridge -{ - #region Imports - - using System; - using System.Collections.Generic; - - #endregion - - /// - /// This type is not intended to be used directly from user code. - /// It may be removed or changed in a future version without notice. - /// - - sealed class DelegatingComparer : IComparer - { - private readonly Func _comparer; - - public DelegatingComparer(Func comparer) - { - if (comparer == null) throw new ArgumentNullException("comparer"); - _comparer = comparer; - } - - public int Compare(T x, T y) { return _comparer(x, y); } - } - - /// - /// This type is not intended to be used directly from user code. - /// It may be removed or changed in a future version without notice. - /// - - struct Key - { - public Key(T value) : this() { Value = value; } - public T Value { get; private set; } - } - - /// - /// This type is not intended to be used directly from user code. - /// It may be removed or changed in a future version without notice. - /// - - sealed class KeyComparer : IEqualityComparer> - { - private readonly IEqualityComparer _innerComparer; - - public KeyComparer(IEqualityComparer innerComparer) - { - _innerComparer = innerComparer ?? EqualityComparer.Default; - } - - public bool Equals(Key x, Key y) - { - return _innerComparer.Equals(x.Value, y.Value); - } - - public int GetHashCode(Key obj) - { - return obj.Value == null ? 0 : _innerComparer.GetHashCode(obj.Value); - } - } -} - -// $Id: IOrderedEnumerable.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ - -namespace System.Linq -{ - using System.Collections.Generic; - - /// - /// Represents a sorted sequence. - /// - - partial interface IOrderedEnumerable : IEnumerable - { - /// - /// Performs a subsequent ordering on the elements of an - /// according to a key. - /// - - IOrderedEnumerable CreateOrderedEnumerable( - Func keySelector, IComparer comparer, bool descending); - } -} - -// $Id: Lookup.cs c08984d432b1 2012/04/17 16:05:19 azizatif $ - -namespace System.Linq -{ - #region Imports - - using System; - using System.Collections; - using System.Collections.Generic; - using IEnumerable=System.Collections.IEnumerable; - using LinqBridge; - - #endregion - - /// - /// Represents a collection of keys each mapped to one or more values. - /// - - internal sealed class Lookup : ILookup - { - private readonly Dictionary, IGrouping> _map; - private readonly List> _orderedKeys; // remember order of insertion - - internal Lookup(IEqualityComparer comparer) - { - _map = new Dictionary, IGrouping>(new KeyComparer(comparer)); - _orderedKeys = new List>(); - } - - internal void Add(IGrouping item) - { - var key = new Key(item.Key); - _map.Add(key, item); - _orderedKeys.Add(key); - } - - internal IEnumerable Find(TKey key) - { - IGrouping grouping; - return _map.TryGetValue(new Key(key), out grouping) ? grouping : null; - } - - /// - /// Gets the number of key/value collection pairs in the . - /// - - public int Count - { - get { return _map.Count; } - } - - /// - /// Gets the collection of values indexed by the specified key. - /// - - public IEnumerable this[TKey key] - { - get - { - IGrouping result; - return _map.TryGetValue(new Key(key), out result) ? result : Enumerable.Empty(); - } - } - - /// - /// Determines whether a specified key is in the . - /// - - public bool Contains(TKey key) - { - return _map.ContainsKey(new Key(key)); - } - - /// - /// Applies a transform function to each key and its associated - /// values and returns the results. - /// - - public IEnumerable ApplyResultSelector( - Func, TResult> resultSelector) - { - if (resultSelector == null) - throw new ArgumentNullException("resultSelector"); - - foreach (var pair in _map) - yield return resultSelector(pair.Key.Value, pair.Value); - } - - /// - /// Returns a generic enumerator that iterates through the . - /// - - public IEnumerator> GetEnumerator() - { - foreach (var key in _orderedKeys) - yield return _map[key]; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} - -// $Id: OrderedEnumerable.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ - -namespace LinqBridge -{ - #region Imports - - using System; - using System.Collections; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - - #endregion - - internal sealed class OrderedEnumerable : IOrderedEnumerable - { - private readonly IEnumerable _source; - private readonly Func, IComparer> _comparerComposer; - - public OrderedEnumerable(IEnumerable source, - Func keySelector, IComparer comparer, bool descending) : - this(source, (_, next) => next, keySelector, comparer, descending) {} - - private OrderedEnumerable(IEnumerable source, - Func, IComparer> parent, - Func keySelector, IComparer comparer, bool descending) - { - if (source == null) throw new ArgumentNullException("source"); - if (keySelector == null) throw new ArgumentNullException("keySelector"); - Debug.Assert(parent != null); - - _source = source; - - comparer = comparer ?? Comparer.Default; - var direction = descending ? -1 : 1; - - _comparerComposer = (items, next) => - { - Debug.Assert(items != null); - Debug.Assert(next != null); - - var keys = new K[items.Length]; - for (var i = 0; i < items.Length; i++) - keys[i] = keySelector(items[i]); - - return parent(items, new DelegatingComparer((i, j) => - { - var result = direction * comparer.Compare(keys[i], keys[j]); - return result != 0 ? result : next.Compare(i, j); - })); - }; - } - - public IOrderedEnumerable CreateOrderedEnumerable( - Func keySelector, IComparer comparer, bool descending) - { - return new OrderedEnumerable(_source, _comparerComposer, keySelector, comparer, descending); - } - - public IEnumerator GetEnumerator() - { - // - // Sort using Array.Sort but docs say that it performs an - // unstable sort. LINQ, on the other hand, says OrderBy performs - // a stable sort. Use the item position then as a tie - // breaker when all keys compare equal, thus making the sort - // stable. - // - - var items = _source.ToArray(); - var positionComparer = new DelegatingComparer((i, j) => i.CompareTo(j)); - var comparer = _comparerComposer(items, positionComparer); - var keys = new int[items.Length]; - for (var i = 0; i < keys.Length; i++) - keys[i] = i; - Array.Sort(keys, items, comparer); - return ((IEnumerable) items).GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} - -// $Id: Action.cs 71137f497bf2 2012/04/16 20:01:27 azizatif $ - -namespace System -{ -#if LINQBRIDGE_LIB - public delegate void Action(); - public delegate void Action(T1 arg1, T2 arg2); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); -#else - delegate void Action(); - delegate void Action(T1 arg1, T2 arg2); - delegate void Action(T1 arg1, T2 arg2, T3 arg3); - delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); -#endif -} - diff --git a/app.config b/app.config new file mode 100644 index 0000000..ce099b3 --- /dev/null +++ b/app.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/packages.config b/packages.config index 248d140..8c01617 100644 --- a/packages.config +++ b/packages.config @@ -1,5 +1,4 @@  - \ No newline at end of file From 39c15252b0e4973066507b720fa7e1a6a98b6222 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Fri, 24 Jul 2015 08:09:00 +0200 Subject: [PATCH 20/31] Fixing target framework of import packages --- packages.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages.config b/packages.config index 8c01617..926cb52 100644 --- a/packages.config +++ b/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file From 1eb4c09504d0cfebaf8667f0b56ce1eae293e34b Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Fri, 24 Jul 2015 08:16:50 +0200 Subject: [PATCH 21/31] Settings fields into properties --- Settings.cs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/Settings.cs b/Settings.cs index c879569..e669ab6 100644 --- a/Settings.cs +++ b/Settings.cs @@ -30,17 +30,26 @@ namespace AeroShot sealed class Settings { - public bool UseDisk; - public bool UseClipboard; - public string FolderPath; - public Switch OpaqueBackgroundType = Switch.Off(ScreenshotBackgroundType.Checkerboard); - public Color SolidBackgroundColor; - public int CheckerboardBackgroundCheckerSize = 8; - public Switch AeroColor = Switch.Off(Color.White); - public Switch ResizeDimensions = Switch.Off(new Size(640, 480)); - public bool CaputreMouse; - public Switch DelayCaptureDuration = Switch.Off(TimeSpan.FromSeconds(3)); - public bool DisableClearType; + public bool UseDisk { get; set; } + public bool UseClipboard { get; set; } + public string FolderPath { get; set; } + public Switch OpaqueBackgroundType { get; set; } + public Color SolidBackgroundColor { get; set; } + public int CheckerboardBackgroundCheckerSize { get; set; } + public Switch AeroColor { get; set; } + public Switch ResizeDimensions { get; set; } + public bool CaputreMouse { get; set; } + public Switch DelayCaptureDuration { get; set; } + public bool DisableClearType { get; set; } + + public Settings() + { + OpaqueBackgroundType = Switch.Off(ScreenshotBackgroundType.Checkerboard); + CheckerboardBackgroundCheckerSize = 8; + AeroColor = Switch.Off(Color.White); + ResizeDimensions = Switch.Off(new Size(640, 480)); + DelayCaptureDuration = Switch.Off(TimeSpan.FromSeconds(3)); + } static string _iniFilePath; From cd1d5cf393b6f3bae2a0dd5a009ebd4095e81bb5 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Fri, 24 Jul 2015 08:19:11 +0200 Subject: [PATCH 22/31] Settings.UseClipboard & UseDisk are mutually exclusive --- Settings.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Settings.cs b/Settings.cs index e669ab6..78a81e4 100644 --- a/Settings.cs +++ b/Settings.cs @@ -31,7 +31,7 @@ namespace AeroShot sealed class Settings { public bool UseDisk { get; set; } - public bool UseClipboard { get; set; } + public bool UseClipboard { get { return !UseDisk; } set { UseDisk = !value; } } public string FolderPath { get; set; } public Switch OpaqueBackgroundType { get; set; } public Color SolidBackgroundColor { get; set; } @@ -82,7 +82,6 @@ static Settings LoadSettingsFromIni(string source) if (ini != null) { settings.UseDisk = ReadSetting(ini, "save-device", v => "file".Equals(v, StringComparison.OrdinalIgnoreCase)); - settings.UseClipboard = !settings.UseDisk; settings.FolderPath = ReadSetting(ini, "save-file-path", Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), s => s); settings.OpaqueBackgroundType = Switch.Create(ReadSetting(ini, "use-opaque-background", Truthy.Parse), From 094dee59d4a38cf2dc9b071150f1624b5d94807c Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Fri, 24 Jul 2015 08:23:55 +0200 Subject: [PATCH 23/31] Normalize color to RGB before hex encoding --- Settings.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Settings.cs b/Settings.cs index 78a81e4..b179a0e 100644 --- a/Settings.cs +++ b/Settings.cs @@ -292,7 +292,9 @@ static class HexColor { public static string Encode(Color color) { - return color.IsEmpty ? null : ColorTranslator.ToHtml(color).Substring(1); + if (color.IsEmpty) return null; + color = Color.FromArgb(color.ToArgb()); + return ColorTranslator.ToHtml(color).Substring(1); // remove # } } } From 32ee66b7a0c26595d3a4a34aa76601736078cd6f Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Fri, 24 Jul 2015 08:25:09 +0200 Subject: [PATCH 24/31] Inlining only use of Settings.CreateRegistryKey --- Settings.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Settings.cs b/Settings.cs index b179a0e..49cdf77 100644 --- a/Settings.cs +++ b/Settings.cs @@ -178,14 +178,9 @@ static KeyValuePair Setting(string key, object value) : Convert.ToString(value, CultureInfo.InvariantCulture)); } - static RegistryKey CreateRegistryKey() - { - return Registry.CurrentUser.CreateSubKey(@"Software\AeroShot"); - } - public static Settings LoadSettingsFromRegistry() { - using (var registryKey = CreateRegistryKey()) + using (var registryKey = Registry.CurrentUser.CreateSubKey(@"Software\AeroShot")) return LoadSettings(registryKey); } From a13388655875fbc201a81531d1675720482bdd55 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Fri, 24 Jul 2015 13:11:37 +0200 Subject: [PATCH 25/31] INI formatting extension into own file --- AeroShot.csproj | 1 + Gini.cs | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ Settings.cs | 65 ------------------------------------------------- 3 files changed, 65 insertions(+), 65 deletions(-) create mode 100644 Gini.cs diff --git a/AeroShot.csproj b/AeroShot.csproj index 28f215e..5340dd9 100644 --- a/AeroShot.csproj +++ b/AeroShot.csproj @@ -58,6 +58,7 @@ + Form diff --git a/Gini.cs b/Gini.cs new file mode 100644 index 0000000..013da8e --- /dev/null +++ b/Gini.cs @@ -0,0 +1,64 @@ +#region The MIT License (MIT) +// +// Copyright (c) 2015 Atif Aziz. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +#endregion + +namespace Gini +{ + using System; + using System.Collections.Generic; + using System.Linq; + + partial class Ini + { + public static IEnumerable Format( + IEnumerable sections, + Func sectionNameSelector, + Func> entriesSelector, + Func> entrySelector) + { + if (sections == null) throw new ArgumentNullException("sections"); + if (sectionNameSelector == null) throw new ArgumentNullException("sectionNameSelector"); + if (entriesSelector == null) throw new ArgumentNullException("entriesSelector"); + if (entrySelector == null) throw new ArgumentNullException("entrySelector"); + + return + from section in sections + select new + { + Name = sectionNameSelector(section), + Entries = entriesSelector(section), + } + into section + from lines in new[] + { + new[] { !string.IsNullOrEmpty(section.Name) ? "[" + section.Name + "]" : null }, + from entry in section.Entries + select entrySelector(entry) into entry + select entry.Key + "=" + entry.Value, + new[] { string.Empty }, + } + from line in lines + where line != null + select line; + } + } +} \ No newline at end of file diff --git a/Settings.cs b/Settings.cs index 49cdf77..1f85498 100644 --- a/Settings.cs +++ b/Settings.cs @@ -292,69 +292,4 @@ public static string Encode(Color color) return ColorTranslator.ToHtml(color).Substring(1); // remove # } } -} - -#region The MIT License (MIT) -// -// Copyright (c) 2015 Atif Aziz. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// -#endregion - -namespace Gini -{ - using System; - using System.Collections.Generic; - using System.Linq; - - partial class Ini - { - public static IEnumerable Format( - IEnumerable sections, - Func sectionNameSelector, - Func> entriesSelector, - Func> entrySelector) - { - if (sections == null) throw new ArgumentNullException("sections"); - if (sectionNameSelector == null) throw new ArgumentNullException("sectionNameSelector"); - if (entriesSelector == null) throw new ArgumentNullException("entriesSelector"); - if (entrySelector == null) throw new ArgumentNullException("entrySelector"); - - return - from section in sections - select new - { - Name = sectionNameSelector(section), - Entries = entriesSelector(section), - } - into section - from lines in new[] - { - new[] { !string.IsNullOrEmpty(section.Name) ? "[" + section.Name + "]" : null }, - from entry in section.Entries - select entrySelector(entry) into entry - select entry.Key + "=" + entry.Value, - new[] { string.Empty }, - } - from line in lines - where line != null - select line; - } - } } \ No newline at end of file From fa5cad599905bad7434ff77109d7ee0cf78f194c Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Fri, 24 Jul 2015 13:18:14 +0200 Subject: [PATCH 26/31] Open, don't create reg key on load --- Settings.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Settings.cs b/Settings.cs index 1f85498..24f6595 100644 --- a/Settings.cs +++ b/Settings.cs @@ -180,7 +180,7 @@ static KeyValuePair Setting(string key, object value) public static Settings LoadSettingsFromRegistry() { - using (var registryKey = Registry.CurrentUser.CreateSubKey(@"Software\AeroShot")) + using (var registryKey = Registry.CurrentUser.OpenSubKey(@"Software\AeroShot")) return LoadSettings(registryKey); } @@ -188,6 +188,9 @@ public static Settings LoadSettings(RegistryKey registryKey) { var settings = new Settings(); + if (registryKey == null) + return settings; + object value; if ((value = registryKey.GetValue("LastPath")) != null && From 277bfb9e95cd8a4cb07756a2fa9c1c87045b9532 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Fri, 24 Jul 2015 13:25:38 +0200 Subject: [PATCH 27/31] Simplification of reg value type checking --- Settings.cs | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/Settings.cs b/Settings.cs index 24f6595..1e7e4ab 100644 --- a/Settings.cs +++ b/Settings.cs @@ -193,17 +193,17 @@ public static Settings LoadSettings(RegistryKey registryKey) object value; - if ((value = registryKey.GetValue("LastPath")) != null && - value.GetType() == (typeof(string))) - { - if (((string)value).Substring(0, 1) == "*") + if ((value = registryKey.GetValue("LastPath")) is string) + { + var str = value.ToString(); + if (str.Substring(0, 1) == "*") { - settings.FolderPath = ((string)value).Substring(1); + settings.FolderPath = str.Substring(1); settings.UseClipboard = true; } else { - settings.FolderPath = (string)value; + settings.FolderPath = str; settings.UseDisk = true; } } @@ -213,8 +213,7 @@ public static Settings LoadSettings(RegistryKey registryKey) Environment.GetFolderPath(Environment.SpecialFolder.Desktop); } - if ((value = registryKey.GetValue("WindowSize")) != null && - value.GetType() == (typeof(long))) + if ((value = registryKey.GetValue("WindowSize")) is long) { var b = new byte[8]; for (int i = 0; i < 8; i++) @@ -227,8 +226,7 @@ public static Settings LoadSettings(RegistryKey registryKey) var defaultOpaqueBackgroundType = Switch.Off(ScreenshotBackgroundType.Checkerboard); - if ((value = registryKey.GetValue("Opaque")) != null && - value.GetType() == (typeof(long))) + if ((value = registryKey.GetValue("Opaque")) is long) { var b = new byte[8]; for (int i = 0; i < 8; i++) @@ -244,8 +242,7 @@ public static Settings LoadSettings(RegistryKey registryKey) else settings.OpaqueBackgroundType = defaultOpaqueBackgroundType; - if ((value = registryKey.GetValue("AeroColor")) != null && - value.GetType() == (typeof(long))) + if ((value = registryKey.GetValue("AeroColor")) is long) { var b = new byte[8]; for (int i = 0; i < 8; i++) @@ -256,16 +253,13 @@ public static Settings LoadSettings(RegistryKey registryKey) else settings.OpaqueBackgroundType = defaultOpaqueBackgroundType; - if ((value = registryKey.GetValue("CapturePointer")) != null && - value.GetType() == (typeof(int))) + if ((value = registryKey.GetValue("CapturePointer")) is int) settings.CaputreMouse = ((int)value & 1) == 1; - if ((value = registryKey.GetValue("ClearType")) != null && - value.GetType() == (typeof(int))) + if ((value = registryKey.GetValue("ClearType")) is int) settings.DisableClearType = ((int)value & 1) == 1; - if ((value = registryKey.GetValue("Delay")) != null && - value.GetType() == (typeof(long))) + if ((value = registryKey.GetValue("Delay")) is long) { var b = new byte[8]; for (int i = 0; i < 8; i++) From 049ded59faef3c408526dac9bcaa9ef04b589e68 Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Fri, 24 Jul 2015 13:50:00 +0200 Subject: [PATCH 28/31] INI keys and words into consts --- Settings.cs | 90 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 31 deletions(-) diff --git a/Settings.cs b/Settings.cs index 1e7e4ab..267d12c 100644 --- a/Settings.cs +++ b/Settings.cs @@ -65,6 +65,34 @@ public static Settings LoadSettings() : LoadSettingsFromRegistry(); } + static class IniKey + { + public const string AppVersion = "app-version"; + public const string SaveDevice = "save-device"; + public const string SaveFilePath = "save-file-path"; + public const string UseOpaqueBackground = "use-opaque-background"; + public const string OpaqueBackgroundType = "opaque-background-type"; + public const string SolidBackgroundColor = "solid-background-color"; + public const string CheckerboardBackgroundCheckerSize = "checkerboard-background-checker-size"; + public const string UseAeroColor = "use-aero-color"; + public const string AeroColor = "aero-color"; + public const string UseWindowResizeDimensions = "use-window-resize-dimensions"; + public const string ResizeWindowWidth = "resize-window-width"; + public const string ResizeWindowHeight = "resize-window-height"; + public const string UseDelayCapture = "use-delay-capture"; + public const string DelayCaptureSeconds = "delay-capture-seconds"; + public const string CapturePointer = "capture-pointer"; + public const string DisableClearType = "disable-clear-type"; + } + + static class IniWord + { + public const string File = "file"; + public const string Solid = "solid"; + public const string Clipboard = "clipboard"; + public const string Checkerboard = "checkerboard"; + } + static Settings LoadSettingsFromIniFile(string path) { return LoadSettingsFromIni(File.ReadAllText(path)); @@ -81,27 +109,27 @@ static Settings LoadSettingsFromIni(string source) if (ini != null) { - settings.UseDisk = ReadSetting(ini, "save-device", v => "file".Equals(v, StringComparison.OrdinalIgnoreCase)); - settings.FolderPath = ReadSetting(ini, "save-file-path", Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), s => s); + settings.UseDisk = ReadSetting(ini, IniKey.SaveDevice, v => IniWord.File.Equals(v, StringComparison.OrdinalIgnoreCase)); + settings.FolderPath = ReadSetting(ini, IniKey.SaveFilePath, Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), s => s); settings.OpaqueBackgroundType - = Switch.Create(ReadSetting(ini, "use-opaque-background", Truthy.Parse), - ReadSetting(ini, "opaque-background-type", v => "solid".Equals(v, StringComparison.OrdinalIgnoreCase) + = Switch.Create(ReadSetting(ini, IniKey.UseOpaqueBackground, Truthy.Parse), + ReadSetting(ini, IniKey.OpaqueBackgroundType, v => IniWord.Solid.Equals(v, StringComparison.OrdinalIgnoreCase) ? ScreenshotBackgroundType.SolidColor : ScreenshotBackgroundType.Checkerboard)); settings.SolidBackgroundColor - = ReadSetting(ini, "solid-background-color", settings.SolidBackgroundColor, ColorTranslator.FromHtml); + = ReadSetting(ini, IniKey.SolidBackgroundColor, settings.SolidBackgroundColor, ColorTranslator.FromHtml); settings.CheckerboardBackgroundCheckerSize - = ReadSetting(ini, "checkerboard-background-checker-size", settings.CheckerboardBackgroundCheckerSize, ParseInt); - settings.AeroColor = Switch.Create(ReadSetting(ini, "use-aero-color", Truthy.Parse), - ReadSetting(ini, "aero-color", settings.AeroColor.Value, ColorTranslator.FromHtml)); - settings.ResizeDimensions = Switch.Create(ReadSetting(ini, "use-window-resize-dimensions", Truthy.Parse), - new Size(ReadSetting(ini, "resize-window-width", settings.ResizeDimensions.Value.Width, ParseInt), - ReadSetting(ini, "resize-window-height", settings.ResizeDimensions.Value.Height, ParseInt))); + = ReadSetting(ini, IniKey.CheckerboardBackgroundCheckerSize, settings.CheckerboardBackgroundCheckerSize, ParseInt); + settings.AeroColor = Switch.Create(ReadSetting(ini, IniKey.UseAeroColor, Truthy.Parse), + ReadSetting(ini, IniKey.AeroColor, settings.AeroColor.Value, ColorTranslator.FromHtml)); + settings.ResizeDimensions = Switch.Create(ReadSetting(ini, IniKey.UseWindowResizeDimensions, Truthy.Parse), + new Size(ReadSetting(ini, IniKey.ResizeWindowWidth, settings.ResizeDimensions.Value.Width, ParseInt), + ReadSetting(ini, IniKey.ResizeWindowHeight, settings.ResizeDimensions.Value.Height, ParseInt))); settings.DelayCaptureDuration - = Switch.Create(ReadSetting(ini, "use-delay-capture", Truthy.Parse), - ReadSetting(ini, "delay-capture-seconds", settings.DelayCaptureDuration.Value, v => TimeSpan.FromSeconds(ParseInt(v)))); - settings.CaputreMouse = ReadSetting(ini, "capture-pointer", Truthy.Parse); - settings.DisableClearType = ReadSetting(ini, "disable-clear-type", Truthy.Parse); + = Switch.Create(ReadSetting(ini, IniKey.UseDelayCapture, Truthy.Parse), + ReadSetting(ini, IniKey.DelayCaptureSeconds, settings.DelayCaptureDuration.Value, v => TimeSpan.FromSeconds(ParseInt(v)))); + settings.CaputreMouse = ReadSetting(ini, IniKey.CapturePointer, Truthy.Parse); + settings.DisableClearType = ReadSetting(ini, IniKey.DisableClearType, Truthy.Parse); } return settings; @@ -138,22 +166,22 @@ static string SettingsIni(Settings settings) { var section = new[] { - Setting("app-version" , Application.ProductVersion), - Setting("save-device" , settings.UseClipboard ? "clipboard" : "file"), - Setting("save-file-path" , settings.FolderPath), - Setting("use-opaque-background" , settings.OpaqueBackgroundType.Convert(_ => true)), - Setting("opaque-background-type" , settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.SolidColor ? "solid" : "checkerboard"), - Setting("solid-background-color" , ColorTranslator.ToHtml(settings.SolidBackgroundColor)), - Setting("checkerboard-background-checker-size", settings.CheckerboardBackgroundCheckerSize), - Setting("use-aero-color" , settings.AeroColor.Convert(_ => true)), - Setting("aero-color" , ColorTranslator.ToHtml(settings.AeroColor.Value)), - Setting("use-window-resize-dimensions" , settings.ResizeDimensions.Convert(_ => true)), - Setting("resize-window-width" , settings.ResizeDimensions.Value.Width), - Setting("resize-window-height" , settings.ResizeDimensions.Value.Height), - Setting("capture-pointer" , settings.CaputreMouse), - Setting("use-delay-capture" , settings.DelayCaptureDuration.Convert(_ => true)), - Setting("delay-capture-seconds" , settings.DelayCaptureDuration.Value.TotalSeconds), - Setting("disable-clear-type" , settings.DisableClearType), + Setting(IniKey.AppVersion , Application.ProductVersion), + Setting(IniKey.SaveDevice , settings.UseClipboard ? IniWord.Clipboard : IniWord.File), + Setting(IniKey.SaveFilePath , settings.FolderPath), + Setting(IniKey.UseOpaqueBackground , settings.OpaqueBackgroundType.Convert(_ => true)), + Setting(IniKey.OpaqueBackgroundType , settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.SolidColor ? IniWord.Solid : IniWord.Checkerboard), + Setting(IniKey.SolidBackgroundColor , ColorTranslator.ToHtml(settings.SolidBackgroundColor)), + Setting(IniKey.CheckerboardBackgroundCheckerSize, settings.CheckerboardBackgroundCheckerSize), + Setting(IniKey.UseAeroColor , settings.AeroColor.Convert(_ => true)), + Setting(IniKey.AeroColor , ColorTranslator.ToHtml(settings.AeroColor.Value)), + Setting(IniKey.UseWindowResizeDimensions , settings.ResizeDimensions.Convert(_ => true)), + Setting(IniKey.ResizeWindowWidth , settings.ResizeDimensions.Value.Width), + Setting(IniKey.ResizeWindowHeight , settings.ResizeDimensions.Value.Height), + Setting(IniKey.CapturePointer , settings.CaputreMouse), + Setting(IniKey.UseDelayCapture , settings.DelayCaptureDuration.Convert(_ => true)), + Setting(IniKey.DelayCaptureSeconds , settings.DelayCaptureDuration.Value.TotalSeconds), + Setting(IniKey.DisableClearType , settings.DisableClearType), }; return string.Join(Environment.NewLine, From 9c9b066a16421a290762839655ed79fad5439cac Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Sat, 25 Jul 2015 13:25:59 +0200 Subject: [PATCH 29/31] Settings in MainForm can be scoped to ctor --- Main.cs | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Main.cs b/Main.cs index c0918e6..176609c 100644 --- a/Main.cs +++ b/Main.cs @@ -27,8 +27,6 @@ public sealed partial class MainForm : Form private const uint SPI_GETFONTSMOOTHING = 0x004A; private const uint SPI_GETFONTSMOOTHINGTYPE = 0x200A; - Settings _settings = Settings.LoadSettings(); - public MainForm() { DoubleBuffered = true; @@ -37,24 +35,26 @@ public MainForm() Text = string.Format(Text, Application.ProductName, Application.ProductVersion); - folderTextBox.Text = _settings.FolderPath; - clipboardButton.Checked = _settings.UseClipboard; - diskButton.Checked = _settings.UseDisk; - resizeCheckbox.Checked = _settings.ResizeDimensions.On; - windowWidth.Value = _settings.ResizeDimensions.Value.Width; - windowHeight.Value = _settings.ResizeDimensions.Value.Height; - opaqueCheckbox.Checked = _settings.OpaqueBackgroundType.On; - opaqueType.SelectedIndex = _settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.Checkerboard ? 0 - : _settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.SolidColor ? 1 + var settings = Settings.LoadSettings(); + + folderTextBox.Text = settings.FolderPath; + clipboardButton.Checked = settings.UseClipboard; + diskButton.Checked = settings.UseDisk; + resizeCheckbox.Checked = settings.ResizeDimensions.On; + windowWidth.Value = settings.ResizeDimensions.Value.Width; + windowHeight.Value = settings.ResizeDimensions.Value.Height; + opaqueCheckbox.Checked = settings.OpaqueBackgroundType.On; + opaqueType.SelectedIndex = settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.Checkerboard ? 0 + : settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.SolidColor ? 1 : -1; - checkerValue.Value = _settings.CheckerboardBackgroundCheckerSize; - opaqueColorHexBox.Text = HexColor.Encode(_settings.SolidBackgroundColor); - aeroColorCheckbox.Checked = _settings.AeroColor.On; - aeroColorHexBox.Text = HexColor.Encode(_settings.AeroColor.Value); - mouseCheckbox.Checked = _settings.CaputreMouse; - delayCheckbox.Checked = _settings.DelayCaptureDuration.On; - delaySeconds.Value = (decimal) _settings.DelayCaptureDuration.Value.TotalSeconds; - clearTypeCheckbox.Checked = _settings.DisableClearType; + checkerValue.Value = settings.CheckerboardBackgroundCheckerSize; + opaqueColorHexBox.Text = HexColor.Encode(settings.SolidBackgroundColor); + aeroColorCheckbox.Checked = settings.AeroColor.On; + aeroColorHexBox.Text = HexColor.Encode(settings.AeroColor.Value); + mouseCheckbox.Checked = settings.CaputreMouse; + delayCheckbox.Checked = settings.DelayCaptureDuration.On; + delaySeconds.Value = (decimal) settings.DelayCaptureDuration.Value.TotalSeconds; + clearTypeCheckbox.Checked = settings.DisableClearType; if (!GlassAvailable()) { From 9c276f45a265b3740f65f0c83d792567e2155d6f Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Sat, 25 Jul 2015 13:28:18 +0200 Subject: [PATCH 30/31] Settings loading into MainForm readability --- Main.cs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Main.cs b/Main.cs index 176609c..9a40d2d 100644 --- a/Main.cs +++ b/Main.cs @@ -37,23 +37,23 @@ public MainForm() var settings = Settings.LoadSettings(); - folderTextBox.Text = settings.FolderPath; - clipboardButton.Checked = settings.UseClipboard; - diskButton.Checked = settings.UseDisk; - resizeCheckbox.Checked = settings.ResizeDimensions.On; - windowWidth.Value = settings.ResizeDimensions.Value.Width; - windowHeight.Value = settings.ResizeDimensions.Value.Height; - opaqueCheckbox.Checked = settings.OpaqueBackgroundType.On; - opaqueType.SelectedIndex = settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.Checkerboard ? 0 - : settings.OpaqueBackgroundType.Value == ScreenshotBackgroundType.SolidColor ? 1 - : -1; - checkerValue.Value = settings.CheckerboardBackgroundCheckerSize; - opaqueColorHexBox.Text = HexColor.Encode(settings.SolidBackgroundColor); + folderTextBox.Text = settings.FolderPath; + clipboardButton.Checked = settings.UseClipboard; + diskButton.Checked = settings.UseDisk; + resizeCheckbox.Checked = settings.ResizeDimensions.On; + windowWidth.Value = settings.ResizeDimensions.Value.Width; + windowHeight.Value = settings.ResizeDimensions.Value.Height; + opaqueCheckbox.Checked = settings.OpaqueBackgroundType.On; + opaqueType.SelectedIndex = ScreenshotBackgroundType.Checkerboard == settings.OpaqueBackgroundType.Value ? 0 + : ScreenshotBackgroundType.SolidColor == settings.OpaqueBackgroundType.Value ? 1 + : -1; + checkerValue.Value = settings.CheckerboardBackgroundCheckerSize; + opaqueColorHexBox.Text = HexColor.Encode(settings.SolidBackgroundColor); aeroColorCheckbox.Checked = settings.AeroColor.On; - aeroColorHexBox.Text = HexColor.Encode(settings.AeroColor.Value); - mouseCheckbox.Checked = settings.CaputreMouse; - delayCheckbox.Checked = settings.DelayCaptureDuration.On; - delaySeconds.Value = (decimal) settings.DelayCaptureDuration.Value.TotalSeconds; + aeroColorHexBox.Text = HexColor.Encode(settings.AeroColor.Value); + mouseCheckbox.Checked = settings.CaputreMouse; + delayCheckbox.Checked = settings.DelayCaptureDuration.On; + delaySeconds.Value = (decimal) settings.DelayCaptureDuration.Value.TotalSeconds; clearTypeCheckbox.Checked = settings.DisableClearType; if (!GlassAvailable()) From c1d20cb532079aae8652f6a2347d016d14a9babc Mon Sep 17 00:00:00 2001 From: Atif Aziz Date: Sat, 25 Jul 2015 13:36:37 +0200 Subject: [PATCH 31/31] Scoping settings near its usage in HotKey --- Hotkeys.cs | 85 ++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/Hotkeys.cs b/Hotkeys.cs index 8e41ef0..44fab50 100644 --- a/Hotkeys.cs +++ b/Hotkeys.cs @@ -30,7 +30,6 @@ public class Hotkeys : Form private readonly int[] _windowId; private Thread _worker; private bool _busyCapturing; - Settings _settings; public Hotkeys() { @@ -52,53 +51,51 @@ private void FormClose(object sender, FormClosingEventArgs e) protected override void WndProc(ref Message m) { base.WndProc(ref m); - if (m.Msg == WM_HOTKEY) - { - _settings = Settings.LoadSettings(); - - if (_busyCapturing) - return; - ScreenshotTask info = GetParamteresFromUI(); - var CtrlAlt = (m.LParam.ToInt32() & (MOD_ALT | MOD_CONTROL)) == (MOD_ALT | MOD_CONTROL); - _busyCapturing = true; - _worker = new Thread(() => - { - if (CtrlAlt) - Thread.Sleep(TimeSpan.FromSeconds(3)); - else - _settings.DelayCaptureDuration.WhenOnThen(Thread.Sleep); - try - { - Screenshot.CaptureWindow(ref info); - } - finally - { - _busyCapturing = false; - } - }) - { - IsBackground = true - }; - _worker.SetApartmentState(ApartmentState.STA); - _worker.Start(); - } + OnHotKey(m); } - private ScreenshotTask GetParamteresFromUI() + void OnHotKey(Message message) { - return - new ScreenshotTask( - WindowsApi.GetForegroundWindow(), - _settings.UseClipboard, - _settings.FolderPath, - _settings.ResizeDimensions.Convert(v => (Size?) v), - _settings.OpaqueBackgroundType.GetValueOrDefault(), - _settings.SolidBackgroundColor, - _settings.CheckerboardBackgroundCheckerSize, - _settings.AeroColor.Convert(v => (Color?) v), - _settings.CaputreMouse, - _settings.DisableClearType); + if (_busyCapturing) + return; + + var settings = Settings.LoadSettings(); + + var info = new ScreenshotTask( + WindowsApi.GetForegroundWindow(), + settings.UseClipboard, + settings.FolderPath, + settings.ResizeDimensions.Convert(v => (Size?) v), + settings.OpaqueBackgroundType.GetValueOrDefault(), + settings.SolidBackgroundColor, + settings.CheckerboardBackgroundCheckerSize, + settings.AeroColor.Convert(v => (Color?) v), + settings.CaputreMouse, + settings.DisableClearType); + + var CtrlAlt = (message.LParam.ToInt32() & (MOD_ALT | MOD_CONTROL)) == (MOD_ALT | MOD_CONTROL); + _busyCapturing = true; + _worker = new Thread(() => + { + if (CtrlAlt) + Thread.Sleep(TimeSpan.FromSeconds(3)); + else + settings.DelayCaptureDuration.WhenOnThen(Thread.Sleep); + try + { + Screenshot.CaptureWindow(ref info); + } + finally + { + _busyCapturing = false; + } + }) + { + IsBackground = true + }; + _worker.SetApartmentState(ApartmentState.STA); + _worker.Start(); } } } \ No newline at end of file