diff --git a/.gitignore b/.gitignore index 54ed6bdf5..3321bd633 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +1,211 @@ -.svn/ -*.gsp -*.bak -Greenshot*INSTALLER*.exe -Greenshot*INSTALLER*.zip -*.paf.exe -*-SVN.* -/Greenshot*/bin/ -obj/ -fugue/ -*Credentials.private.cs -*Credentials.orig.cs -/Greenshot/UpgradeLog*.htm -/Greenshot/UpgradeLog*.XML -/Greenshot/_UpgradeReport_Files/* -*.log -/Greenshot/releases/additional_files/readme.txt -/*.error -/Greenshot/releases/innosetup/setup.iss -/Greenshot/packages -/Greenshot/releases/appinfo.ini -/Greenshot/Backup* +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. -/Greenshot/tools/PortableApps.comInstaller/Data/PortableApps.comInstallerLog.txt +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Visual Studio 2015 cache/options directory +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +## TODO: Comment the next line if you want to checkin your +## web deploy settings but do note that will include unencrypted +## passwords +#*.pubxml + +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml diff --git a/Greenshot/Greenshot.sln b/Greenshot.sln similarity index 80% rename from Greenshot/Greenshot.sln rename to Greenshot.sln index e49aeb8c5..b76fba9a6 100644 --- a/Greenshot/Greenshot.sln +++ b/Greenshot.sln @@ -1,37 +1,40 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -# SharpDevelop 4.2.2.8818 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot", "Greenshot.csproj", "{CD642BF4-D815-4D67-A0B5-C69F0B8231AF}" +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot", "Greenshot\Greenshot.csproj", "{CD642BF4-D815-4D67-A0B5-C69F0B8231AF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotPlugin", "..\GreenshotPlugin\GreenshotPlugin.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotPlugin", "GreenshotPlugin\GreenshotPlugin.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotExternalCommandPlugin", "..\GreenshotExternalCommandPlugin\GreenshotExternalCommandPlugin.csproj", "{47F23C86-604E-4CC3-8767-B3D4088F30BB}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotExternalCommandPlugin", "GreenshotExternalCommandPlugin\GreenshotExternalCommandPlugin.csproj", "{47F23C86-604E-4CC3-8767-B3D4088F30BB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotConfluencePlugin", "..\GreenshotConfluencePlugin\GreenshotConfluencePlugin.csproj", "{C3052651-598A-44E2-AAB3-2E41311D50F9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotConfluencePlugin", "GreenshotConfluencePlugin\GreenshotConfluencePlugin.csproj", "{C3052651-598A-44E2-AAB3-2E41311D50F9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotImgurPlugin", "..\GreenshotImgurPlugin\GreenshotImgurPlugin.csproj", "{80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotImgurPlugin", "GreenshotImgurPlugin\GreenshotImgurPlugin.csproj", "{80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotJiraPlugin", "..\GreenshotJiraPlugin\GreenshotJiraPlugin.csproj", "{19FEEF09-313F-43C7-819D-F1BCA782B08B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotJiraPlugin", "GreenshotJiraPlugin\GreenshotJiraPlugin.csproj", "{19FEEF09-313F-43C7-819D-F1BCA782B08B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotOCRPlugin", "..\GreenshotOCRPlugin\GreenshotOCRPlugin.csproj", "{C6988EE8-2FEE-4349-9F09-F9628A0D8965}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotOCRPlugin", "GreenshotOCRPlugin\GreenshotOCRPlugin.csproj", "{C6988EE8-2FEE-4349-9F09-F9628A0D8965}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotOCRCommand", "..\GreenshotOCRCommand\GreenshotOCRCommand.csproj", "{D61E6ECE-E0B6-4467-B492-F08A06BA8F02}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotOCRCommand", "GreenshotOCRCommand\GreenshotOCRCommand.csproj", "{D61E6ECE-E0B6-4467-B492-F08A06BA8F02}" ProjectSection(ProjectDependencies) = postProject {C6988EE8-2FEE-4349-9F09-F9628A0D8965} = {C6988EE8-2FEE-4349-9F09-F9628A0D8965} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotBoxPlugin", "..\GreenshotBoxPlugin\GreenshotBoxPlugin.csproj", "{697CF066-9077-4F22-99D9-D989CCE7282B}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotBoxPlugin", "GreenshotBoxPlugin\GreenshotBoxPlugin.csproj", "{697CF066-9077-4F22-99D9-D989CCE7282B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotDropboxPlugin", "..\GreenshotDropboxPlugin\GreenshotDropboxPlugin.csproj", "{AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotDropboxPlugin", "GreenshotDropboxPlugin\GreenshotDropboxPlugin.csproj", "{AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotFlickrPlugin", "..\GreenshotFlickrPlugin\GreenshotFlickrPlugin.csproj", "{7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotFlickrPlugin", "GreenshotFlickrPlugin\GreenshotFlickrPlugin.csproj", "{7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotPicasaPlugin", "..\GreenshotPicasaPlugin\GreenshotPicasaPlugin.csproj", "{1893A2E4-A78A-4713-A8E7-E70058DABEE0}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotPicasaPlugin", "GreenshotPicasaPlugin\GreenshotPicasaPlugin.csproj", "{1893A2E4-A78A-4713-A8E7-E70058DABEE0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotOfficePlugin", "..\GreenshotOfficePlugin\GreenshotOfficePlugin.csproj", "{92599C09-FF29-4ABD-B6E6-C48ECD781BAB}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotOfficePlugin", "GreenshotOfficePlugin\GreenshotOfficePlugin.csproj", "{92599C09-FF29-4ABD-B6E6-C48ECD781BAB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotPhotobucketPlugin", "..\GreenshotPhotobucketPlugin\GreenshotPhotobucketPlugin.csproj", "{9C0ECC4C-7807-4111-916A-4F57BB29788A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotPhotobucketPlugin", "GreenshotPhotobucketPlugin\GreenshotPhotobucketPlugin.csproj", "{9C0ECC4C-7807-4111-916A-4F57BB29788A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GreenshotWin10Plugin", "GreenshotWin10Plugin\GreenshotWin10Plugin.csproj", "{9801F62C-540F-4BFE-9211-6405DEDE563B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -107,6 +110,7 @@ Global {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {C6988EE8-2FEE-4349-9F09-F9628A0D8965}.Release|x86.ActiveCfg = Release|x86 {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|Any CPU.ActiveCfg = Debug|x86 + {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|Any CPU.Build.0 = Debug|x86 {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|x86.ActiveCfg = Debug|x86 {D61E6ECE-E0B6-4467-B492-F08A06BA8F02}.Debug|x86.Build.0 = Debug|x86 @@ -175,6 +179,16 @@ Global {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|Mixed Platforms.Build.0 = Release|Any CPU {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|x86.ActiveCfg = Release|x86 {9C0ECC4C-7807-4111-916A-4F57BB29788A}.Release|x86.Build.0 = Release|x86 + {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|x86.ActiveCfg = Debug|Any CPU + {9801F62C-540F-4BFE-9211-6405DEDE563B}.Debug|x86.Build.0 = Debug|Any CPU + {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|x86.ActiveCfg = Release|Any CPU + {9801F62C-540F-4BFE-9211-6405DEDE563B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Greenshot/AssemblyInfo.cs b/Greenshot/AssemblyInfo.cs index 71277cb02..efd0f77c8 100644 --- a/Greenshot/AssemblyInfo.cs +++ b/Greenshot/AssemblyInfo.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,7 +21,6 @@ using System.Reflection; using System.Runtime.InteropServices; -using System.Security; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information diff --git a/Greenshot/Configuration/EditorConfiguration.cs b/Greenshot/Configuration/EditorConfiguration.cs index 4c805e5ce..2a95136d3 100644 --- a/Greenshot/Configuration/EditorConfiguration.cs +++ b/Greenshot/Configuration/EditorConfiguration.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,8 @@ using System.Drawing; using Greenshot.Drawing.Fields; using GreenshotPlugin.UnmanagedHelpers; using Greenshot.IniFile; -using Greenshot.Core; +using GreenshotPlugin.Effects; +using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Configuration { /// @@ -34,35 +35,35 @@ namespace Greenshot.Configuration { [IniSection("Editor", Description="Greenshot editor configuration")] public class EditorConfiguration : IniSection { [IniProperty("RecentColors", Separator="|", Description="Last used colors")] - public List RecentColors; + public List RecentColors { get; set; } [IniProperty("LastFieldValue", Separator="|", Description="Field values, make sure the last used settings are re-used")] - public Dictionary LastUsedFieldValues; + public Dictionary LastUsedFieldValues { get; set; } [IniProperty("MatchSizeToCapture", Description="Match the editor window size to the capture", DefaultValue="True")] - public bool MatchSizeToCapture; + public bool MatchSizeToCapture { get; set; } [IniProperty("WindowPlacementFlags", Description="Placement flags", DefaultValue="0")] - public WindowPlacementFlags WindowPlacementFlags; + public WindowPlacementFlags WindowPlacementFlags { get; set; } [IniProperty("WindowShowCommand", Description="Show command", DefaultValue="Normal")] - public ShowWindowCommand ShowWindowCommand; + public ShowWindowCommand ShowWindowCommand { get; set; } [IniProperty("WindowMinPosition", Description="Position of minimized window", DefaultValue="-1,-1")] - public Point WindowMinPosition; + public Point WindowMinPosition { get; set; } [IniProperty("WindowMaxPosition", Description="Position of maximized window", DefaultValue="-1,-1")] - public Point WindowMaxPosition; + public Point WindowMaxPosition { get; set; } [IniProperty("WindowNormalPosition", Description="Position of normal window", DefaultValue="100,100,400,400")] - public Rectangle WindowNormalPosition; + public Rectangle WindowNormalPosition { get; set; } [IniProperty("ReuseEditor", Description = "Reuse already open editor", DefaultValue = "false")] - public bool ReuseEditor; + public bool ReuseEditor { get; set; } [IniProperty("FreehandSensitivity", Description = "The smaller this number, the less smoothing is used. Decrease for detailed drawing, e.g. when using a pen. Increase for smoother lines. e.g. when you want to draw a smooth line.", DefaultValue = "3")] - public int FreehandSensitivity; + public int FreehandSensitivity { get; set; } [IniProperty("SuppressSaveDialogAtClose", Description="Suppressed the 'do you want to save' dialog when closing the editor.", DefaultValue="False")] - public bool SuppressSaveDialogAtClose; + public bool SuppressSaveDialogAtClose { get; set; } [IniProperty("DropShadowEffectSettings", Description = "Settings for the drop shadow effect.")] - public DropShadowEffect DropShadowEffectSettings; + public DropShadowEffect DropShadowEffectSettings { get; set; } [IniProperty("TornEdgeEffectSettings", Description = "Settings for the torn edge effect.")] - public TornEdgeEffect TornEdgeEffectSettings; + public TornEdgeEffect TornEdgeEffectSettings { get; set; } public override void AfterLoad() { base.AfterLoad(); @@ -73,9 +74,10 @@ namespace Greenshot.Configuration { /// Type of the class for which to create the field /// FieldType of the field to construct - /// FieldType of the field to construct + /// /// a new Field of the given fieldType, with the scope of it's value being restricted to the Type scope - public Field CreateField(Type requestingType, FieldType fieldType, object preferredDefaultValue) { + public IField CreateField(Type requestingType, IFieldType fieldType, object preferredDefaultValue) + { string requestingTypeName = requestingType.Name; string requestedField = requestingTypeName + "." + fieldType.Name; object fieldValue = preferredDefaultValue; @@ -97,12 +99,14 @@ namespace Greenshot.Configuration { } else { LastUsedFieldValues.Add(requestedField, fieldValue); } - Field returnField = new Field(fieldType, requestingType); - returnField.Value = fieldValue; - return returnField; + return new Field(fieldType, requestingType) + { + Value = fieldValue + }; } - - public void UpdateLastFieldValue(Field field) { + + public void UpdateLastFieldValue(IField field) + { string requestedField = field.Scope + "." + field.FieldType.Name; // Check if the configuration exists if (LastUsedFieldValues == null) { @@ -110,12 +114,21 @@ namespace Greenshot.Configuration { } // check if settings for the requesting type exist, if not create! if (LastUsedFieldValues.ContainsKey(requestedField)) { - LastUsedFieldValues[requestedField] = field.myValue; + LastUsedFieldValues[requestedField] = field.Value; } else { - LastUsedFieldValues.Add(requestedField, field.myValue); + LastUsedFieldValues.Add(requestedField, field.Value); } } + public void ResetEditorPlacement() + { + WindowNormalPosition = new Rectangle(100, 100, 400, 400); + WindowMaxPosition = new Point(-1,-1); + WindowMinPosition = new Point(-1, -1); + WindowPlacementFlags = 0; + ShowWindowCommand = ShowWindowCommand.Normal; + } + public WindowPlacement GetEditorPlacement() { WindowPlacement placement = WindowPlacement.Default; placement.NormalPosition = new RECT(WindowNormalPosition); diff --git a/Greenshot/Configuration/LanguageKeys.cs b/Greenshot/Configuration/LanguageKeys.cs index 57b21f268..c2280f2f4 100644 --- a/Greenshot/Configuration/LanguageKeys.cs +++ b/Greenshot/Configuration/LanguageKeys.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,10 @@ * along with this program. If not, see . */ +using System.Diagnostics.CodeAnalysis; + namespace Greenshot.Configuration { + [SuppressMessage("ReSharper", "InconsistentNaming")] public enum LangKey { none, about_bugs, diff --git a/Greenshot/Controls/BindableToolStripButton.cs b/Greenshot/Controls/BindableToolStripButton.cs index 5641a9c27..7c1c50b85 100644 --- a/Greenshot/Controls/BindableToolStripButton.cs +++ b/Greenshot/Controls/BindableToolStripButton.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,12 +36,14 @@ namespace Greenshot.Controls { set; } - public BindableToolStripButton() :base() { + public BindableToolStripButton() + { CheckedChanged += BindableToolStripButton_CheckedChanged; } - void BindableToolStripButton_CheckedChanged(object sender, EventArgs e) { - if(PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Checked")); + private void BindableToolStripButton_CheckedChanged(object sender, EventArgs e) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Checked")); } } } diff --git a/Greenshot/Controls/BindableToolStripComboBox.cs b/Greenshot/Controls/BindableToolStripComboBox.cs index 192e25ecb..d0f706260 100644 --- a/Greenshot/Controls/BindableToolStripComboBox.cs +++ b/Greenshot/Controls/BindableToolStripComboBox.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -36,15 +36,14 @@ namespace Greenshot.Controls { set; } - public BindableToolStripComboBox() :base() { + public BindableToolStripComboBox() + { SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged; } - void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e) { - if(PropertyChanged != null) { - PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem")); - - } + private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedItem")); } } } diff --git a/Greenshot/Controls/BindableToolStripDropDownButton.cs b/Greenshot/Controls/BindableToolStripDropDownButton.cs index d32b2453d..da638d481 100644 --- a/Greenshot/Controls/BindableToolStripDropDownButton.cs +++ b/Greenshot/Controls/BindableToolStripDropDownButton.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,9 +38,6 @@ namespace Greenshot.Controls { set; } - public BindableToolStripDropDownButton() { - } - public object SelectedTag { get { if(Tag==null && DropDownItems.Count>0) Tag=DropDownItems[0].Tag; return Tag; } set { AdoptFromTag(value); } @@ -51,7 +48,7 @@ namespace Greenshot.Controls { if(Tag == null || !Tag.Equals(clickedItem.Tag)) { Tag = clickedItem.Tag; Image = clickedItem.Image; - if(PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("SelectedTag")); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedTag")); } base.OnDropDownItemClicked(e); } @@ -66,7 +63,7 @@ namespace Greenshot.Controls { } } Tag = tag; - if(PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("SelectedTag")); + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedTag")); } } } diff --git a/Greenshot/Controls/ColorButton.cs b/Greenshot/Controls/ColorButton.cs index 8eb49f13e..d37fbf1c9 100644 --- a/Greenshot/Controls/ColorButton.cs +++ b/Greenshot/Controls/ColorButton.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,7 +31,7 @@ namespace Greenshot.Controls { /// public class ColorButton : Button, IGreenshotLanguageBindable { public event PropertyChangedEventHandler PropertyChanged; - private Color selectedColor = Color.White; + private Color _selectedColor = Color.White; [Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")] public string LanguageKey { @@ -44,9 +44,9 @@ namespace Greenshot.Controls { } public Color SelectedColor { - get {return selectedColor;} + get {return _selectedColor;} set { - selectedColor = value; + _selectedColor = value; Brush brush; if(value != Color.Transparent) { @@ -67,19 +67,21 @@ namespace Greenshot.Controls { } } - void ColorButtonClick(object sender, EventArgs e) { + private void ColorButtonClick(object sender, EventArgs e) { ColorDialog colorDialog = ColorDialog.GetInstance(); colorDialog.Color = SelectedColor; // Using the parent to make sure the dialog doesn't show on another window colorDialog.ShowDialog(Parent.Parent); - if (colorDialog.DialogResult != DialogResult.Cancel) { - if (!colorDialog.Color.Equals(SelectedColor)) { - SelectedColor = colorDialog.Color; - if(PropertyChanged != null) { - PropertyChanged(this, new PropertyChangedEventArgs("SelectedColor")); - } - } + if (colorDialog.DialogResult == DialogResult.Cancel) + { + return; } + if (colorDialog.Color.Equals(SelectedColor)) + { + return; + } + SelectedColor = colorDialog.Color; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedColor")); } } } diff --git a/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs b/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs index 6c18554da..d3e8b5db2 100644 --- a/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs +++ b/Greenshot/Controls/ContextMenuToolStripProfessionalRenderer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,6 @@ using Greenshot.IniFile; using GreenshotPlugin.Core; using System.Drawing; -using System.Drawing.Drawing2D; using System.Windows.Forms; namespace Greenshot.Controls { @@ -30,18 +29,16 @@ namespace Greenshot.Controls { /// ToolStripProfessionalRenderer which draws the Check correctly when the icons are larger /// public class ContextMenuToolStripProfessionalRenderer : ToolStripProfessionalRenderer { - private static CoreConfiguration coreConfiguration = IniConfig.GetIniSection(); - private static Image scaledCheckbox; + private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); + private static Image _scaledCheckbox; protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e) { - if (scaledCheckbox == null || scaledCheckbox.Size != coreConfiguration.IconSize) { - if (scaledCheckbox != null) { - scaledCheckbox.Dispose(); - } - scaledCheckbox = ImageHelper.ResizeImage(e.Image, true, coreConfiguration.IconSize.Width, coreConfiguration.IconSize.Height, null); + if (_scaledCheckbox == null || _scaledCheckbox.Size != CoreConfig.IconSize) { + _scaledCheckbox?.Dispose(); + _scaledCheckbox = ImageHelper.ResizeImage(e.Image, true, CoreConfig.IconSize.Width, CoreConfig.IconSize.Height, null); } Rectangle old = e.ImageRectangle; - ToolStripItemImageRenderEventArgs clone = new ToolStripItemImageRenderEventArgs(e.Graphics, e.Item, scaledCheckbox, new Rectangle(old.X, 0, old.Width, old.Height)); + ToolStripItemImageRenderEventArgs clone = new ToolStripItemImageRenderEventArgs(e.Graphics, e.Item, _scaledCheckbox, new Rectangle(old.X, 0, old.Width, old.Height)); base.OnRenderItemCheck(clone); } } diff --git a/Greenshot/Controls/CustomToolStripProfessionalRenderer.cs b/Greenshot/Controls/CustomToolStripProfessionalRenderer.cs index 89260baf3..bbf59f368 100644 --- a/Greenshot/Controls/CustomToolStripProfessionalRenderer.cs +++ b/Greenshot/Controls/CustomToolStripProfessionalRenderer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Controls/FontFamilyComboBox.cs b/Greenshot/Controls/FontFamilyComboBox.cs index 410c87402..53a89111a 100644 --- a/Greenshot/Controls/FontFamilyComboBox.cs +++ b/Greenshot/Controls/FontFamilyComboBox.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,15 +41,19 @@ namespace Greenshot.Controls { } } - public FontFamilyComboBox() : base() { - ComboBox.DataSource = FontFamily.Families; - ComboBox.DisplayMember = "Name"; - SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged; - ComboBox.DrawMode = DrawMode.OwnerDrawFixed; - ComboBox.DrawItem += ComboBox_DrawItem; + public FontFamilyComboBox() + { + if (ComboBox != null) + { + ComboBox.DataSource = FontFamily.Families; + ComboBox.DisplayMember = "Name"; + SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged; + ComboBox.DrawMode = DrawMode.OwnerDrawFixed; + ComboBox.DrawItem += ComboBox_DrawItem; + } } - void ComboBox_DrawItem(object sender, DrawItemEventArgs e) { + private void ComboBox_DrawItem(object sender, DrawItemEventArgs e) { // DrawBackground handles drawing the background (i.e,. hot-tracked v. not) // It uses the system colors (Bluish, and and white, by default) // same as calling e.Graphics.FillRectangle ( SystemBrushes.Highlight, e.Bounds ); @@ -58,7 +62,7 @@ namespace Greenshot.Controls { if (e.Index > -1) { FontFamily fontFamily = Items[e.Index] as FontFamily; FontStyle fontStyle = FontStyle.Regular; - if (!fontFamily.IsStyleAvailable(FontStyle.Regular)) { + if (fontFamily != null && !fontFamily.IsStyleAvailable(FontStyle.Regular)) { if (fontFamily.IsStyleAvailable(FontStyle.Bold)) { fontStyle = FontStyle.Bold; } else if (fontFamily.IsStyleAvailable(FontStyle.Italic)) { @@ -70,10 +74,16 @@ namespace Greenshot.Controls { } } try { - DrawText(e.Graphics, fontFamily, fontStyle, e.Bounds, fontFamily.Name); + if (fontFamily != null) + { + DrawText(e.Graphics, fontFamily, fontStyle, e.Bounds, fontFamily.Name); + } } catch { // If the drawing failed, BUG-1770 seems to have a weird case that causes: Font 'Lucida Sans Typewriter' does not support style 'Regular' - DrawText(e.Graphics, FontFamily.GenericSansSerif, FontStyle.Regular, e.Bounds, fontFamily.Name); + if (fontFamily != null) + { + DrawText(e.Graphics, FontFamily.GenericSansSerif, FontStyle.Regular, e.Bounds, fontFamily.Name); + } } } // Uncomment this if you actually like the way the focus rectangle looks @@ -89,7 +99,7 @@ namespace Greenshot.Controls { /// /// private void DrawText(Graphics graphics, FontFamily fontFamily, FontStyle fontStyle, Rectangle bounds, string text) { - using (Font font = new Font(fontFamily, this.Font.Size + 5, fontStyle, GraphicsUnit.Pixel)) { + using (Font font = new Font(fontFamily, Font.Size + 5, fontStyle, GraphicsUnit.Pixel)) { // Make sure the text is visible by centering it in the line using (StringFormat stringFormat = new StringFormat()) { stringFormat.LineAlignment = StringAlignment.Center; @@ -98,7 +108,7 @@ namespace Greenshot.Controls { } } - void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e) { + private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Text")); PropertyChanged(this, new PropertyChangedEventArgs("FontFamily")); diff --git a/Greenshot/Controls/MenuStripEx.cs b/Greenshot/Controls/MenuStripEx.cs index aa880f06e..b8f1ab264 100644 --- a/Greenshot/Controls/MenuStripEx.cs +++ b/Greenshot/Controls/MenuStripEx.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,14 +29,12 @@ namespace Greenshot.Controls { public class MenuStripEx : MenuStrip { private const int WM_MOUSEACTIVATE = 0x21; - enum NativeConstants : uint { + private enum NativeConstants : uint { MA_ACTIVATE = 1, MA_ACTIVATEANDEAT = 2, - MA_NOACTIVATE = 3, - MA_NOACTIVATEANDEAT = 4, } - private bool clickThrough = false; + private bool _clickThrough; /// /// Gets or sets whether the ToolStripEx honors item clicks when its containing form does not have input focus. /// @@ -45,17 +43,17 @@ namespace Greenshot.Controls { /// public bool ClickThrough { get { - return clickThrough; + return _clickThrough; } set { - clickThrough = value; + _clickThrough = value; } } protected override void WndProc(ref Message m) { base.WndProc(ref m); - if (clickThrough && m.Msg == WM_MOUSEACTIVATE && m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT) { + if (_clickThrough && m.Msg == WM_MOUSEACTIVATE && m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT) { m.Result = (IntPtr)NativeConstants.MA_ACTIVATE; } } diff --git a/Greenshot/Controls/NonJumpingPanel.cs b/Greenshot/Controls/NonJumpingPanel.cs index 8392b9219..8a4747adf 100644 --- a/Greenshot/Controls/NonJumpingPanel.cs +++ b/Greenshot/Controls/NonJumpingPanel.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,19 +19,36 @@ * along with this program. If not, see . */ -/// -/// See: http://nickstips.wordpress.com/2010/03/03/c-panel-resets-scroll-position-after-focus-is-lost-and-regained/ -/// - using System.Drawing; using System.Windows.Forms; namespace GreenshotPlugin.Controls { + /// + /// See: http://nickstips.wordpress.com/2010/03/03/c-panel-resets-scroll-position-after-focus-is-lost-and-regained/ + /// public class NonJumpingPanel : Panel { protected override Point ScrollToControl(Control activeControl) { // Returning the current location prevents the panel from // scrolling to the active control when the panel loses and regains focus return DisplayRectangle.Location; } + + /// + /// Add horizontal scrolling to the panel, when using the wheel and the shift key is pressed + /// + /// MouseEventArgs + protected override void OnMouseWheel(MouseEventArgs e) + { + if (VScroll && (ModifierKeys & Keys.Shift) == Keys.Shift) + { + VScroll = false; + base.OnMouseWheel(e); + VScroll = true; + } + else + { + base.OnMouseWheel(e); + } + } } } diff --git a/Greenshot/Controls/Pipette.cs b/Greenshot/Controls/Pipette.cs index 6aeccf9b5..662b30931 100644 --- a/Greenshot/Controls/Pipette.cs +++ b/Greenshot/Controls/Pipette.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,22 +30,22 @@ namespace Greenshot.Controls { /// This code was supplied by Hi-Coder as a patch for Greenshot /// Needed some modifications to be stable. /// - public class Pipette : Label, IMessageFilter, IDisposable { - private MovableShowColorForm movableShowColorForm; - private bool dragging; + public sealed class Pipette : Label, IMessageFilter, IDisposable { + private MovableShowColorForm _movableShowColorForm; + private bool _dragging; private Cursor _cursor; - private Bitmap _image; - private const int VK_ESC = 27; + private readonly Bitmap _image; + private const int VkEsc = 27; public event EventHandler PipetteUsed; public Pipette() { BorderStyle = BorderStyle.FixedSingle; - dragging = false; + _dragging = false; _image = (Bitmap)new ComponentResourceManager(typeof(ColorDialog)).GetObject("pipette.Image"); Image = _image; - _cursor = CreateCursor((Bitmap)_image, 1, 14); - movableShowColorForm = new MovableShowColorForm(); + _cursor = CreateCursor(_image, 1, 14); + _movableShowColorForm = new MovableShowColorForm(); Application.AddMessageFilter(this); } @@ -58,13 +58,12 @@ namespace Greenshot.Controls { /// Cursor private static Cursor CreateCursor(Bitmap bitmap, int hotspotX, int hotspotY) { using (SafeIconHandle iconHandle = new SafeIconHandle( bitmap.GetHicon())) { - IntPtr icon; - IconInfo iconInfo = new IconInfo(); + IconInfo iconInfo; User32.GetIconInfo(iconHandle, out iconInfo); iconInfo.xHotspot = hotspotX; iconInfo.yHotspot = hotspotY; iconInfo.fIcon = false; - icon = User32.CreateIconIndirect(ref iconInfo); + var icon = User32.CreateIconIndirect(ref iconInfo); return new Cursor(icon); } } @@ -85,11 +84,9 @@ namespace Greenshot.Controls { if (_cursor != null) { _cursor.Dispose(); } - if (movableShowColorForm != null) { - movableShowColorForm.Dispose(); - } + _movableShowColorForm?.Dispose(); } - movableShowColorForm = null; + _movableShowColorForm = null; _cursor = null; base.Dispose(disposing); } @@ -101,7 +98,7 @@ namespace Greenshot.Controls { protected override void OnMouseDown(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { User32.SetCapture(Handle); - movableShowColorForm.MoveTo(PointToScreen(new Point(e.X, e.Y))); + _movableShowColorForm.MoveTo(PointToScreen(new Point(e.X, e.Y))); } base.OnMouseDown(e); } @@ -111,10 +108,11 @@ namespace Greenshot.Controls { /// /// MouseEventArgs protected override void OnMouseUp(MouseEventArgs e) { - if (e.Button == MouseButtons.Left) { + if (e.Button == MouseButtons.Left) + { //Release Capture should consume MouseUp when canceled with the escape key User32.ReleaseCapture(); - PipetteUsed(this, new PipetteUsedArgs(movableShowColorForm.color)); + PipetteUsed?.Invoke(this, new PipetteUsedArgs(_movableShowColorForm.color)); } base.OnMouseUp(e); } @@ -124,10 +122,10 @@ namespace Greenshot.Controls { /// /// MouseEventArgs protected override void OnMouseMove(MouseEventArgs e) { - if (dragging) { + if (_dragging) { //display the form on the right side of the cursor by default; Point zp = PointToScreen(new Point(e.X, e.Y)); - movableShowColorForm.MoveTo(zp); + _movableShowColorForm.MoveTo(zp); } base.OnMouseMove(e); } @@ -138,16 +136,16 @@ namespace Greenshot.Controls { /// protected override void OnMouseCaptureChanged(EventArgs e) { if (Capture) { - dragging = true; + _dragging = true; Image = null; Cursor c = _cursor; Cursor = c; - movableShowColorForm.Visible = true; + _movableShowColorForm.Visible = true; } else { - dragging = false; + _dragging = false; Image = _image; Cursor = Cursors.Arrow; - movableShowColorForm.Visible = false; + _movableShowColorForm.Visible = false; } Update(); base.OnMouseCaptureChanged(e); @@ -156,9 +154,9 @@ namespace Greenshot.Controls { #region IMessageFilter Members public bool PreFilterMessage(ref Message m) { - if (dragging) { + if (_dragging) { if (m.Msg == (int)WindowsMessages.WM_CHAR) { - if ((int)m.WParam == VK_ESC) { + if ((int)m.WParam == VkEsc) { User32.ReleaseCapture(); } } @@ -170,10 +168,10 @@ namespace Greenshot.Controls { } public class PipetteUsedArgs : EventArgs { - public Color color; + public Color Color; public PipetteUsedArgs(Color c) { - color = c; + Color = c; } } } diff --git a/Greenshot/Controls/ToolStripColorButton.cs b/Greenshot/Controls/ToolStripColorButton.cs index 915721248..ac4fcd736 100644 --- a/Greenshot/Controls/ToolStripColorButton.cs +++ b/Greenshot/Controls/ToolStripColorButton.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,16 +35,16 @@ namespace Greenshot.Controls { set; } - private Color selectedColor = Color.Transparent; + private Color _selectedColor = Color.Transparent; public ToolStripColorButton() { Click+= ColorButtonClick; } public Color SelectedColor { - get {return selectedColor;} + get {return _selectedColor;} set { - selectedColor = value; + _selectedColor = value; Brush brush; if(value != Color.Transparent) { @@ -65,19 +65,21 @@ namespace Greenshot.Controls { } } - void ColorButtonClick(object sender, EventArgs e) { + private void ColorButtonClick(object sender, EventArgs e) { ColorDialog colorDialog = ColorDialog.GetInstance(); colorDialog.Color = SelectedColor; // Using the parent to make sure the dialog doesn't show on another window colorDialog.ShowDialog(Parent.Parent); - if (colorDialog.DialogResult != DialogResult.Cancel) { - if (!colorDialog.Color.Equals(SelectedColor)) { - SelectedColor = colorDialog.Color; - if (PropertyChanged != null) { - PropertyChanged(this, new PropertyChangedEventArgs("SelectedColor")); - } - } + if (colorDialog.DialogResult == DialogResult.Cancel) + { + return; } + if (colorDialog.Color.Equals(SelectedColor)) + { + return; + } + SelectedColor = colorDialog.Color; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("SelectedColor")); } } } diff --git a/Greenshot/Controls/ToolStripEx.cs b/Greenshot/Controls/ToolStripEx.cs index 3a32224c3..1298db21f 100644 --- a/Greenshot/Controls/ToolStripEx.cs +++ b/Greenshot/Controls/ToolStripEx.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,17 +26,15 @@ namespace Greenshot.Controls { /// This is an extension of the default ToolStrip and allows us to click it even when the form doesn't have focus. /// See: http://blogs.msdn.com/b/rickbrew/archive/2006/01/09/511003.aspx /// - class ToolStripEx : ToolStrip { + internal class ToolStripEx : ToolStrip { private const int WM_MOUSEACTIVATE = 0x21; - enum NativeConstants : uint { + private enum NativeConstants : uint { MA_ACTIVATE = 1, MA_ACTIVATEANDEAT = 2, - MA_NOACTIVATE = 3, - MA_NOACTIVATEANDEAT = 4, } - private bool clickThrough = false; + private bool _clickThrough; /// /// Gets or sets whether the ToolStripEx honors item clicks when its containing form does not have input focus. /// @@ -46,17 +44,17 @@ namespace Greenshot.Controls { public bool ClickThrough { get { - return clickThrough; + return _clickThrough; } set { - clickThrough = value; + _clickThrough = value; } } protected override void WndProc(ref Message m) { base.WndProc(ref m); - if (clickThrough && m.Msg == WM_MOUSEACTIVATE && m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT) { + if (_clickThrough && m.Msg == WM_MOUSEACTIVATE && m.Result == (IntPtr)NativeConstants.MA_ACTIVATEANDEAT) { m.Result = (IntPtr)NativeConstants.MA_ACTIVATE; } } diff --git a/Greenshot/Controls/ToolStripNumericUpDown.cs b/Greenshot/Controls/ToolStripNumericUpDown.cs index 376c021d0..f683f7c9b 100644 --- a/Greenshot/Controls/ToolStripNumericUpDown.cs +++ b/Greenshot/Controls/ToolStripNumericUpDown.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,16 +34,13 @@ namespace Greenshot.Controls { { } - public NumericUpDown NumericUpDown - { - get {return Control as NumericUpDown;} - } - + public NumericUpDown NumericUpDown => Control as NumericUpDown; + public decimal Value - { - get { return NumericUpDown.Value; } - set { NumericUpDown.Value = value;} - } + { + get { return NumericUpDown.Value; } + set { NumericUpDown.Value = value;} + } public decimal Minimum { get { return NumericUpDown.Minimum; } set { NumericUpDown.Minimum = value; } @@ -74,8 +71,9 @@ namespace Greenshot.Controls { NumericUpDown.ValueChanged -= _valueChanged; } - private void _valueChanged(object sender, EventArgs e) { - if(PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Value")); + private void _valueChanged(object sender, EventArgs e) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value")); } } } diff --git a/Greenshot/Destinations/ClipboardDestination.cs b/Greenshot/Destinations/ClipboardDestination.cs index 25476f64e..147571e78 100644 --- a/Greenshot/Destinations/ClipboardDestination.cs +++ b/Greenshot/Destinations/ClipboardDestination.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,16 +25,12 @@ using System.Windows.Forms; using Greenshot.Configuration; using GreenshotPlugin.Core; using Greenshot.Plugin; -using Greenshot.IniFile; -using log4net; namespace Greenshot.Destinations { /// /// Description of ClipboardDestination. /// public class ClipboardDestination : AbstractDestination { - private static ILog LOG = LogManager.GetLogger(typeof(ClipboardDestination)); - private static CoreConfiguration conf = IniConfig.GetIniSection(); public const string DESIGNATION = "Clipboard"; public override string Designation { diff --git a/Greenshot/Destinations/EditorDestination.cs b/Greenshot/Destinations/EditorDestination.cs index 0aaed76a2..ab66cd04e 100644 --- a/Greenshot/Destinations/EditorDestination.cs +++ b/Greenshot/Destinations/EditorDestination.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,11 +32,11 @@ namespace Greenshot.Destinations { /// Description of EditorDestination. /// public class EditorDestination : AbstractDestination { - private static ILog LOG = LogManager.GetLogger(typeof(EditorDestination)); - private static EditorConfiguration editorConfiguration = IniConfig.GetIniSection(); + private static readonly ILog LOG = LogManager.GetLogger(typeof(EditorDestination)); + private static readonly EditorConfiguration editorConfiguration = IniConfig.GetIniSection(); public const string DESIGNATION = "Editor"; - private IImageEditor editor = null; - private static Image greenshotIcon = GreenshotResources.getGreenshotIcon().ToBitmap(); + private readonly IImageEditor editor; + private static readonly Image greenshotIcon = GreenshotResources.getGreenshotIcon().ToBitmap(); public EditorDestination() { } @@ -66,7 +66,7 @@ namespace Greenshot.Destinations { } } - public override bool isDynamic { + public override bool IsDynamic { get { return true; } @@ -79,8 +79,8 @@ namespace Greenshot.Destinations { } public override IEnumerable DynamicDestinations() { - foreach (IImageEditor editor in ImageEditorForm.Editors) { - yield return new EditorDestination(editor); + foreach (IImageEditor someEditor in ImageEditorForm.Editors) { + yield return new EditorDestination(someEditor); } } diff --git a/Greenshot/Destinations/EmailDestination.cs b/Greenshot/Destinations/EmailDestination.cs index b82b233b0..5c6b7e013 100644 --- a/Greenshot/Destinations/EmailDestination.cs +++ b/Greenshot/Destinations/EmailDestination.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,87 +26,63 @@ using Greenshot.Configuration; using Greenshot.Helpers; using Greenshot.Plugin; using GreenshotPlugin.Core; -using Greenshot.IniFile; -using log4net; namespace Greenshot.Destinations { /// /// Description of EmailDestination. /// public class EmailDestination : AbstractDestination { - private static ILog LOG = LogManager.GetLogger(typeof(EmailDestination)); - private static CoreConfiguration conf = IniConfig.GetIniSection(); - private static Image mailIcon = GreenshotResources.getImage("Email.Image"); - private static bool isActiveFlag = false; - private static string mapiClient = null; + private static readonly Image MailIcon = GreenshotResources.getImage("Email.Image"); + private static bool _isActiveFlag; + private static string _mapiClient; public const string DESIGNATION = "EMail"; static EmailDestination() { // Logic to decide what email implementation we use - if (EmailConfigHelper.HasMAPI()) { - isActiveFlag = true; - mapiClient = EmailConfigHelper.GetMapiClient(); - if (!string.IsNullOrEmpty(mapiClient)) { + if (EmailConfigHelper.HasMapi()) { + _isActiveFlag = true; + _mapiClient = EmailConfigHelper.GetMapiClient(); + if (!string.IsNullOrEmpty(_mapiClient)) { // Active as we have a mapi client, can be disabled later - isActiveFlag = true; + _isActiveFlag = true; } } } - public EmailDestination() { - - } - - public override string Designation { - get { - return DESIGNATION; - } - } + public override string Designation => DESIGNATION; public override string Description { get { // Make sure there is some kind of "mail" name - if (mapiClient == null) { - mapiClient = Language.GetString(LangKey.editor_email); + if (_mapiClient == null) { + _mapiClient = Language.GetString(LangKey.editor_email); } - return mapiClient; + return _mapiClient; } } - public override int Priority { - get { - return 3; - } - } + public override int Priority => 3; - public override bool isActive { + public override bool IsActive { get { - if (isActiveFlag) { + if (_isActiveFlag) { // Disable if the office plugin is installed and the client is outlook // TODO: Change this! It always creates an exception, as the plugin has not been loaded the type is not there :( Type outlookdestination = Type.GetType("GreenshotOfficePlugin.OutlookDestination,GreenshotOfficePlugin"); if (outlookdestination != null) { - if (mapiClient.ToLower().Contains("microsoft outlook")) { - isActiveFlag = false; + if (_mapiClient.ToLower().Contains("microsoft outlook")) { + _isActiveFlag = false; } } } - return base.isActive && isActiveFlag; + return base.IsActive && _isActiveFlag; } } - public override Keys EditorShortcutKeys { - get { - return Keys.Control | Keys.E; - } - } + public override Keys EditorShortcutKeys => Keys.Control | Keys.E; + + public override Image DisplayIcon => MailIcon; - public override Image DisplayIcon { - get { - return mailIcon; - } - } - public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { ExportInformation exportInformation = new ExportInformation(Designation, Description); MapiMailMessage.SendImage(surface, captureDetails); diff --git a/Greenshot/Destinations/FileDestination.cs b/Greenshot/Destinations/FileDestination.cs index 24af9bd1d..d3f1a2cb4 100644 --- a/Greenshot/Destinations/FileDestination.cs +++ b/Greenshot/Destinations/FileDestination.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,60 +35,40 @@ namespace Greenshot.Destinations { /// Description of FileSaveAsDestination. /// public class FileDestination : AbstractDestination { - private static ILog LOG = LogManager.GetLogger(typeof(FileDestination)); - private static CoreConfiguration conf = IniConfig.GetIniSection(); + private static readonly ILog Log = LogManager.GetLogger(typeof(FileDestination)); + private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection(); public const string DESIGNATION = "FileNoDialog"; - public override string Designation { - get { - return DESIGNATION; - } - } + public override string Designation => DESIGNATION; - public override string Description { - get { - return Language.GetString(LangKey.quicksettings_destination_file); - } - } + public override string Description => Language.GetString(LangKey.quicksettings_destination_file); - public override int Priority { - get { - return 0; - } - } + public override int Priority => 0; - public override Keys EditorShortcutKeys { - get { - return Keys.Control | Keys.S; - } - } - - public override Image DisplayIcon { - get { - return GreenshotResources.getImage("Save.Image"); - } - } + public override Keys EditorShortcutKeys => Keys.Control | Keys.S; + + public override Image DisplayIcon => GreenshotResources.getImage("Save.Image"); public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { ExportInformation exportInformation = new ExportInformation(Designation, Description); bool outputMade; - bool overwrite; - string fullPath; + bool overwrite; + string fullPath; // Get output settings from the configuration SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(); - if (captureDetails != null && captureDetails.Filename != null) { - // As we save a pre-selected file, allow to overwrite. - overwrite = true; - LOG.InfoFormat("Using previous filename"); - fullPath = captureDetails.Filename; + if (captureDetails?.Filename != null) { + // As we save a pre-selected file, allow to overwrite. + overwrite = true; + Log.InfoFormat("Using previous filename"); + fullPath = captureDetails.Filename; outputSettings.Format = ImageOutput.FormatForFilename(fullPath); - } else { - fullPath = CreateNewFilename(captureDetails); - // As we generate a file, the configuration tells us if we allow to overwrite - overwrite = conf.OutputFileAllowOverwrite; - } - if (conf.OutputFilePromptQuality) { + } else { + fullPath = CreateNewFilename(captureDetails); + // As we generate a file, the configuration tells us if we allow to overwrite + overwrite = CoreConfig.OutputFileAllowOverwrite; + } + if (CoreConfig.OutputFilePromptQuality) { QualityDialog qualityDialog = new QualityDialog(outputSettings); qualityDialog.ShowDialog(); } @@ -96,28 +76,31 @@ namespace Greenshot.Destinations { // Catching any exception to prevent that the user can't write in the directory. // This is done for e.g. bugs #2974608, #2963943, #2816163, #2795317, #2789218, #3004642 try { - ImageOutput.Save(surface, fullPath, overwrite, outputSettings, conf.OutputFileCopyPathToClipboard); + ImageOutput.Save(surface, fullPath, overwrite, outputSettings, CoreConfig.OutputFileCopyPathToClipboard); outputMade = true; } catch (ArgumentException ex1) { // Our generated filename exists, display 'save-as' - LOG.InfoFormat("Not overwriting: {0}", ex1.Message); + Log.InfoFormat("Not overwriting: {0}", ex1.Message); // when we don't allow to overwrite present a new SaveWithDialog fullPath = ImageOutput.SaveWithDialog(surface, captureDetails); - outputMade = (fullPath != null); + outputMade = fullPath != null; } catch (Exception ex2) { - LOG.Error("Error saving screenshot!", ex2); + Log.Error("Error saving screenshot!", ex2); // Show the problem MessageBox.Show(Language.GetString(LangKey.error_save), Language.GetString(LangKey.error)); // when save failed we present a SaveWithDialog fullPath = ImageOutput.SaveWithDialog(surface, captureDetails); - outputMade = (fullPath != null); + outputMade = fullPath != null; } // Don't overwrite filename if no output is made if (outputMade) { - exportInformation.ExportMade = outputMade; + exportInformation.ExportMade = true; exportInformation.Filepath = fullPath; - captureDetails.Filename = fullPath; - conf.OutputFileAsFullpath = fullPath; + if (captureDetails != null) + { + captureDetails.Filename = fullPath; + } + CoreConfig.OutputFileAsFullpath = fullPath; } ProcessExport(exportInformation, surface); @@ -126,18 +109,18 @@ namespace Greenshot.Destinations { private static string CreateNewFilename(ICaptureDetails captureDetails) { string fullPath; - LOG.InfoFormat("Creating new filename"); - string pattern = conf.OutputFileFilenamePattern; + Log.InfoFormat("Creating new filename"); + string pattern = CoreConfig.OutputFileFilenamePattern; if (string.IsNullOrEmpty(pattern)) { pattern = "greenshot ${capturetime}"; } - string filename = FilenameHelper.GetFilenameFromPattern(pattern, conf.OutputFileFormat, captureDetails); - string filepath = FilenameHelper.FillVariables(conf.OutputFilePath, false); + string filename = FilenameHelper.GetFilenameFromPattern(pattern, CoreConfig.OutputFileFormat, captureDetails); + string filepath = FilenameHelper.FillVariables(CoreConfig.OutputFilePath, false); try { fullPath = Path.Combine(filepath, filename); } catch (ArgumentException) { // configured filename or path not valid, show error message... - LOG.InfoFormat("Generated path or filename not valid: {0}, {1}", filepath, filename); + Log.InfoFormat("Generated path or filename not valid: {0}, {1}", filepath, filename); MessageBox.Show(Language.GetString(LangKey.error_save_invalid_chars), Language.GetString(LangKey.error)); // ... lets get the pattern fixed.... diff --git a/Greenshot/Destinations/FileWithDialogDestination.cs b/Greenshot/Destinations/FileWithDialogDestination.cs index e14b804b6..a33332cca 100644 --- a/Greenshot/Destinations/FileWithDialogDestination.cs +++ b/Greenshot/Destinations/FileWithDialogDestination.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,15 +26,13 @@ using Greenshot.Configuration; using GreenshotPlugin.Core; using Greenshot.Plugin; using Greenshot.IniFile; -using log4net; namespace Greenshot.Destinations { /// /// Description of FileWithDialog. /// public class FileWithDialogDestination : AbstractDestination { - private static ILog LOG = LogManager.GetLogger(typeof(FileWithDialogDestination)); - private static CoreConfiguration conf = IniConfig.GetIniSection(); + private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); public const string DESIGNATION = "FileDialog"; public override string Designation { @@ -69,9 +67,8 @@ namespace Greenshot.Destinations { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { ExportInformation exportInformation = new ExportInformation(Designation, Description); - string savedTo = null; // Bug #2918756 don't overwrite path if SaveWithDialog returns null! - savedTo = ImageOutput.SaveWithDialog(surface, captureDetails); + var savedTo = ImageOutput.SaveWithDialog(surface, captureDetails); if (savedTo != null) { exportInformation.ExportMade = true; exportInformation.Filepath = savedTo; diff --git a/Greenshot/Destinations/PickerDestination.cs b/Greenshot/Destinations/PickerDestination.cs index 7988dea71..6a7fc29be 100644 --- a/Greenshot/Destinations/PickerDestination.cs +++ b/Greenshot/Destinations/PickerDestination.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,36 +24,20 @@ using Greenshot.Configuration; using GreenshotPlugin.Core; using Greenshot.Plugin; using Greenshot.Helpers; -using Greenshot.IniFile; -using log4net; namespace Greenshot.Destinations { /// /// The PickerDestination shows a context menu with all possible destinations, so the user can "pick" one /// public class PickerDestination : AbstractDestination { - private static ILog LOG = LogManager.GetLogger(typeof(PickerDestination)); - private static CoreConfiguration conf = IniConfig.GetIniSection(); public const string DESIGNATION = "Picker"; - public override string Designation { - get { - return DESIGNATION; - } - } + public override string Designation => DESIGNATION; - public override string Description { - get { - return Language.GetString(LangKey.settings_destination_picker); - } - } + public override string Description => Language.GetString(LangKey.settings_destination_picker); + + public override int Priority => 1; - public override int Priority { - get { - return 1; - } - } - /// /// Export the capture with the destination picker @@ -68,7 +52,7 @@ namespace Greenshot.Destinations { if ("Picker".Equals(destination.Designation)) { continue; } - if (!destination.isActive) { + if (!destination.IsActive) { continue; } destinations.Add(destination); diff --git a/Greenshot/Destinations/PrinterDestination.cs b/Greenshot/Destinations/PrinterDestination.cs index bc4ce8af0..8fa0c5f2e 100644 --- a/Greenshot/Destinations/PrinterDestination.cs +++ b/Greenshot/Destinations/PrinterDestination.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,18 +28,14 @@ using Greenshot.Configuration; using GreenshotPlugin.Core; using Greenshot.Plugin; using Greenshot.Helpers; -using Greenshot.IniFile; -using log4net; namespace Greenshot.Destinations { /// /// Description of PrinterDestination. /// public class PrinterDestination : AbstractDestination { - private static ILog LOG = LogManager.GetLogger(typeof(PrinterDestination)); - private static CoreConfiguration conf = IniConfig.GetIniSection(); public const string DESIGNATION = "Printer"; - public string printerName = null; + public readonly string printerName; public PrinterDestination() { } @@ -80,7 +76,7 @@ namespace Greenshot.Destinations { } } - public override bool isDynamic { + public override bool IsDynamic { get { return true; } @@ -89,7 +85,7 @@ namespace Greenshot.Destinations { /// /// Create destinations for all the installed printers /// - /// IEnumerable + /// IEnumerable of IDestination public override IEnumerable DynamicDestinations() { PrinterSettings settings = new PrinterSettings(); string defaultPrinter = settings.PrinterName; @@ -121,7 +117,7 @@ namespace Greenshot.Destinations { /// ExportInformation public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { ExportInformation exportInformation = new ExportInformation(Designation, Description); - PrinterSettings printerSettings = null; + PrinterSettings printerSettings; if (!string.IsNullOrEmpty(printerName)) { using (PrintHelper printHelper = new PrintHelper(surface, captureDetails)) { printerSettings = printHelper.PrintTo(printerName); diff --git a/Greenshot/Drawing/Adorners/AbstractAdorner.cs b/Greenshot/Drawing/Adorners/AbstractAdorner.cs new file mode 100644 index 000000000..886abf937 --- /dev/null +++ b/Greenshot/Drawing/Adorners/AbstractAdorner.cs @@ -0,0 +1,146 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * + * This program 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 1 of the License, or + * (at your option) any later version. + * + * This program 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 . + */ + +using Greenshot.Plugin.Drawing; +using Greenshot.Plugin.Drawing.Adorners; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace Greenshot.Drawing.Adorners +{ + public class AbstractAdorner : IAdorner + { + public virtual EditStatus EditStatus { get; protected set; } = EditStatus.IDLE; + + protected Size _size = new Size(4, 4); + + public AbstractAdorner(IDrawableContainer owner) + { + Owner = owner; + } + + /// + /// Returns the cursor for when the mouse is over the adorner + /// + public virtual Cursor Cursor + { + get + { + return Cursors.SizeAll; + } + } + + public virtual IDrawableContainer Owner + { + get; + set; + } + + /// + /// Test if the point is inside the adorner + /// + /// + /// + public virtual bool HitTest(Point point) + { + Rectangle hitBounds = Bounds; + hitBounds.Inflate(3, 3); + return hitBounds.Contains(point); + } + + /// + /// Handle the mouse down + /// + /// + /// + public virtual void MouseDown(object sender, MouseEventArgs mouseEventArgs) + { + } + + /// + /// Handle the mouse move + /// + /// + /// + public virtual void MouseMove(object sender, MouseEventArgs mouseEventArgs) + { + } + + /// + /// Handle the mouse up + /// + /// + /// + public virtual void MouseUp(object sender, MouseEventArgs mouseEventArgs) + { + EditStatus = EditStatus.IDLE; + } + + /// + /// Return the location of the adorner + /// + public virtual Point Location + { + get; + set; + } + + /// + /// Return the bounds of the Adorner + /// + public virtual Rectangle Bounds + { + get + { + Point location = Location; + return new Rectangle(location.X - (_size.Width / 2), location.Y - (_size.Height / 2), _size.Width, _size.Height); + } + } + + /// + /// The adorner is active if the edit status is not idle or undrawn + /// + public virtual bool IsActive + { + get + { + return EditStatus != EditStatus.IDLE && EditStatus != EditStatus.UNDRAWN; + } + } + + /// + /// Draw the adorner + /// + /// PaintEventArgs + public virtual void Paint(PaintEventArgs paintEventArgs) + { + } + + /// + /// We ignore the Transform, as the coordinates are directly bound to those of the owner + /// + /// + public virtual void Transform(Matrix matrix) + { + } + } +} diff --git a/Greenshot/Drawing/Adorners/MoveAdorner.cs b/Greenshot/Drawing/Adorners/MoveAdorner.cs new file mode 100644 index 000000000..6e0aed9c7 --- /dev/null +++ b/Greenshot/Drawing/Adorners/MoveAdorner.cs @@ -0,0 +1,164 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * + * This program 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 1 of the License, or + * (at your option) any later version. + * + * This program 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 . + */ + +using Greenshot.Helpers; +using Greenshot.Plugin.Drawing; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace Greenshot.Drawing.Adorners +{ + /// + /// This is the adorner for the line based containers + /// + public class MoveAdorner : AbstractAdorner + { + private Rectangle _boundsBeforeResize = Rectangle.Empty; + private RectangleF _boundsAfterResize = RectangleF.Empty; + + public Positions Position { get; private set; } + + public MoveAdorner(IDrawableContainer owner, Positions position) : base(owner) + { + Position = position; + } + + /// + /// Returns the cursor for when the mouse is over the adorner + /// + public override Cursor Cursor => Cursors.SizeAll; + + /// + /// Handle the mouse down + /// + /// + /// + public override void MouseDown(object sender, MouseEventArgs mouseEventArgs) + { + EditStatus = EditStatus.RESIZING; + _boundsBeforeResize = new Rectangle(Owner.Left, Owner.Top, Owner.Width, Owner.Height); + _boundsAfterResize = _boundsBeforeResize; + } + + /// + /// Handle the mouse move + /// + /// + /// + public override void MouseMove(object sender, MouseEventArgs mouseEventArgs) + { + if (EditStatus != EditStatus.RESIZING) + { + return; + } + Owner.Invalidate(); + Owner.MakeBoundsChangeUndoable(false); + + // reset "workbench" rectangle to current bounds + _boundsAfterResize.X = _boundsBeforeResize.X; + _boundsAfterResize.Y = _boundsBeforeResize.Y; + _boundsAfterResize.Width = _boundsBeforeResize.Width; + _boundsAfterResize.Height = _boundsBeforeResize.Height; + + // calculate scaled rectangle + ScaleHelper.Scale(ref _boundsAfterResize, Position, new PointF(mouseEventArgs.X, mouseEventArgs.Y), ScaleHelper.GetScaleOptions()); + + // apply scaled bounds to this DrawableContainer + Owner.ApplyBounds(_boundsAfterResize); + + Owner.Invalidate(); + } + + /// + /// Return the location of the adorner + /// + public override Point Location { + get + { + int x = 0,y = 0; + switch (Position) + { + case Positions.TopLeft: + x = Owner.Left; + y = Owner.Top; + break; + case Positions.BottomLeft: + x = Owner.Left; + y = Owner.Top + Owner.Height; + break; + case Positions.MiddleLeft: + x = Owner.Left; + y = Owner.Top + (Owner.Height / 2); + break; + case Positions.TopCenter: + x = Owner.Left + (Owner.Width / 2); + y = Owner.Top; + break; + case Positions.BottomCenter: + x = Owner.Left + (Owner.Width / 2); + y = Owner.Top + Owner.Height; + break; + case Positions.TopRight: + x = Owner.Left + Owner.Width; + y = Owner.Top; + break; + case Positions.BottomRight: + x = Owner.Left + Owner.Width; + y = Owner.Top + Owner.Height; + break; + case Positions.MiddleRight: + x = Owner.Left + Owner.Width; + y = Owner.Top + (Owner.Height / 2); + break; + } + return new Point(x, y); + } + } + + /// + /// Draw the adorner + /// + /// PaintEventArgs + public override void Paint(PaintEventArgs paintEventArgs) + { + Graphics targetGraphics = paintEventArgs.Graphics; + + var bounds = Bounds; + GraphicsState state = targetGraphics.Save(); + + targetGraphics.SmoothingMode = SmoothingMode.None; + targetGraphics.CompositingMode = CompositingMode.SourceCopy; + targetGraphics.PixelOffsetMode = PixelOffsetMode.Half; + targetGraphics.InterpolationMode = InterpolationMode.NearestNeighbor; + + try + { + targetGraphics.FillRectangle(Brushes.Black, bounds.X, bounds.Y, bounds.Width, bounds.Height); + } + catch + { + // Ignore, BUG-2065 + } + targetGraphics.Restore(state); + } + } +} diff --git a/Greenshot/Drawing/Adorners/ResizeAdorner.cs b/Greenshot/Drawing/Adorners/ResizeAdorner.cs new file mode 100644 index 000000000..55635e098 --- /dev/null +++ b/Greenshot/Drawing/Adorners/ResizeAdorner.cs @@ -0,0 +1,184 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * + * This program 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 1 of the License, or + * (at your option) any later version. + * + * This program 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 . + */ + +using Greenshot.Helpers; +using Greenshot.Plugin.Drawing; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace Greenshot.Drawing.Adorners +{ + /// + /// This is the default "legacy" gripper adorner, not the one used for the tail in the speech-bubble + /// + public class ResizeAdorner : AbstractAdorner + { + private Rectangle _boundsBeforeResize = Rectangle.Empty; + private RectangleF _boundsAfterResize = RectangleF.Empty; + + public Positions Position { get; private set; } + + public ResizeAdorner(IDrawableContainer owner, Positions position) : base(owner) + { + Position = position; + } + + /// + /// Returns the cursor for when the mouse is over the adorner + /// + public override Cursor Cursor + { + get + { + bool isNotSwitched = Owner.Width >= 0; + if (Owner.Height < 0) + { + isNotSwitched = !isNotSwitched; + } + switch (Position) + { + case Positions.TopLeft: + case Positions.BottomRight: + return isNotSwitched ? Cursors.SizeNWSE : Cursors.SizeNESW; + case Positions.TopRight: + case Positions.BottomLeft: + return isNotSwitched ? Cursors.SizeNESW : Cursors.SizeNWSE; + case Positions.MiddleLeft: + case Positions.MiddleRight: + return Cursors.SizeWE; + case Positions.TopCenter: + case Positions.BottomCenter: + return Cursors.SizeNS; + default: + return Cursors.SizeAll; + } + } + } + + /// + /// Handle the mouse down + /// + /// + /// + public override void MouseDown(object sender, MouseEventArgs mouseEventArgs) + { + EditStatus = EditStatus.RESIZING; + _boundsBeforeResize = new Rectangle(Owner.Left, Owner.Top, Owner.Width, Owner.Height); + _boundsAfterResize = _boundsBeforeResize; + } + + /// + /// Handle the mouse move + /// + /// + /// + public override void MouseMove(object sender, MouseEventArgs mouseEventArgs) + { + if (EditStatus != EditStatus.RESIZING) + { + return; + } + Owner.Invalidate(); + Owner.MakeBoundsChangeUndoable(false); + + // reset "workbench" rectangle to current bounds + _boundsAfterResize.X = _boundsBeforeResize.X; + _boundsAfterResize.Y = _boundsBeforeResize.Y; + _boundsAfterResize.Width = _boundsBeforeResize.Width; + _boundsAfterResize.Height = _boundsBeforeResize.Height; + + // calculate scaled rectangle + ScaleHelper.Scale(ref _boundsAfterResize, Position, new PointF(mouseEventArgs.X, mouseEventArgs.Y), ScaleHelper.GetScaleOptions()); + + // apply scaled bounds to this DrawableContainer + Owner.ApplyBounds(_boundsAfterResize); + + Owner.Invalidate(); + } + + /// + /// Return the location of the adorner + /// + public override Point Location { + get + { + int x = 0,y = 0; + switch (Position) + { + case Positions.TopLeft: + x = Owner.Left; + y = Owner.Top; + break; + case Positions.BottomLeft: + x = Owner.Left; + y = Owner.Top + Owner.Height; + break; + case Positions.MiddleLeft: + x = Owner.Left; + y = Owner.Top + (Owner.Height / 2); + break; + case Positions.TopCenter: + x = Owner.Left + (Owner.Width / 2); + y = Owner.Top; + break; + case Positions.BottomCenter: + x = Owner.Left + (Owner.Width / 2); + y = Owner.Top + Owner.Height; + break; + case Positions.TopRight: + x = Owner.Left + Owner.Width; + y = Owner.Top; + break; + case Positions.BottomRight: + x = Owner.Left + Owner.Width; + y = Owner.Top + Owner.Height; + break; + case Positions.MiddleRight: + x = Owner.Left + Owner.Width; + y = Owner.Top + (Owner.Height / 2); + break; + } + return new Point(x, y); + } + } + + /// + /// Draw the adorner + /// + /// PaintEventArgs + public override void Paint(PaintEventArgs paintEventArgs) + { + Graphics targetGraphics = paintEventArgs.Graphics; + + var bounds = Bounds; + GraphicsState state = targetGraphics.Save(); + + targetGraphics.SmoothingMode = SmoothingMode.None; + targetGraphics.CompositingMode = CompositingMode.SourceCopy; + targetGraphics.PixelOffsetMode = PixelOffsetMode.Half; + targetGraphics.InterpolationMode = InterpolationMode.NearestNeighbor; + + targetGraphics.FillRectangle(Brushes.Black, bounds.X, bounds.Y, bounds.Width , bounds.Height); + targetGraphics.Restore(state); + } + } +} diff --git a/Greenshot/Drawing/Adorners/TargetAdorner.cs b/Greenshot/Drawing/Adorners/TargetAdorner.cs new file mode 100644 index 000000000..92c51b5b9 --- /dev/null +++ b/Greenshot/Drawing/Adorners/TargetAdorner.cs @@ -0,0 +1,118 @@ +/* + * Greenshot - a free and open source screenshot tool + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom + * + * For more information see: http://getgreenshot.org/ + * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * + * This program 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 1 of the License, or + * (at your option) any later version. + * + * This program 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 . + */ + +using Greenshot.Plugin.Drawing; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace Greenshot.Drawing.Adorners +{ + /// + /// This implements the special "gripper" for the Speech-Bubble tail + /// + public class TargetAdorner : AbstractAdorner + { + + public TargetAdorner(IDrawableContainer owner, Point location) : base(owner) + { + Location = location; + } + + /// + /// Handle the mouse down + /// + /// + /// + public override void MouseDown(object sender, MouseEventArgs mouseEventArgs) + { + EditStatus = EditStatus.MOVING; + } + + /// + /// Handle the mouse move + /// + /// + /// + public override void MouseMove(object sender, MouseEventArgs mouseEventArgs) + { + if (EditStatus != EditStatus.MOVING) + { + return; + } + + Owner.Invalidate(); + Point newGripperLocation = new Point(mouseEventArgs.X, mouseEventArgs.Y); + Rectangle surfaceBounds = new Rectangle(0, 0, Owner.Parent.Width, Owner.Parent.Height); + // Check if gripper inside the parent (surface), if not we need to move it inside + // This was made for BUG-1682 + if (!surfaceBounds.Contains(newGripperLocation)) + { + if (newGripperLocation.X > surfaceBounds.Right) + { + newGripperLocation.X = surfaceBounds.Right - 5; + } + if (newGripperLocation.X < surfaceBounds.Left) + { + newGripperLocation.X = surfaceBounds.Left; + } + if (newGripperLocation.Y > surfaceBounds.Bottom) + { + newGripperLocation.Y = surfaceBounds.Bottom - 5; + } + if (newGripperLocation.Y < surfaceBounds.Top) + { + newGripperLocation.Y = surfaceBounds.Top; + } + } + + Location = newGripperLocation; + Owner.Invalidate(); + } + + /// + /// Draw the adorner + /// + /// PaintEventArgs + public override void Paint(PaintEventArgs paintEventArgs) + { + Graphics targetGraphics = paintEventArgs.Graphics; + + var bounds = Bounds; + targetGraphics.FillRectangle(Brushes.Green, bounds.X, bounds.Y, bounds.Width, bounds.Height); + } + + /// + /// Made sure this adorner is transformed + /// + /// Matrix + public override void Transform(Matrix matrix) + { + if (matrix == null) + { + return; + } + Point[] points = new[] { Location }; + matrix.TransformPoints(points); + Location = points[0]; + } + } +} diff --git a/Greenshot/Drawing/ArrowContainer.cs b/Greenshot/Drawing/ArrowContainer.cs index f1c65ff53..e79475c6d 100644 --- a/Greenshot/Drawing/ArrowContainer.cs +++ b/Greenshot/Drawing/ArrowContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -79,7 +79,7 @@ namespace Greenshot.Drawing { Top + currentStep + Height); currentStep++; - alpha = alpha - (basealpha / steps); + alpha = alpha - basealpha / steps; } } diff --git a/Greenshot/Drawing/CropContainer.cs b/Greenshot/Drawing/CropContainer.cs index 676836f93..1eb22d151 100644 --- a/Greenshot/Drawing/CropContainer.cs +++ b/Greenshot/Drawing/CropContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,9 +20,11 @@ */ using System.Drawing; +using System.Runtime.Serialization; using Greenshot.Drawing.Fields; using Greenshot.Helpers; using Greenshot.Plugin.Drawing; +using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { /// @@ -30,27 +32,38 @@ namespace Greenshot.Drawing { /// public class CropContainer : DrawableContainer { public CropContainer(Surface parent) : base(parent) { + Init(); } + protected override void OnDeserialized(StreamingContext streamingContext) + { + base.OnDeserialized(streamingContext); + Init(); + } + + private void Init() + { + CreateDefaultAdorners(); + } protected override void InitializeFields() { - AddField(GetType(), FieldType.FLAGS, FieldType.Flag.CONFIRMABLE); + AddField(GetType(), FieldType.FLAGS, FieldFlag.CONFIRMABLE); } public override void Invalidate() { - _parent.Invalidate(); + _parent?.Invalidate(); } /// /// We need to override the DrawingBound, return a rectangle in the size of the image, to make sure this element is always draw /// (we create a transparent brown over the complete picture) /// - public override Rectangle DrawingBounds { - get { - return new Rectangle(0,0,_parent.Width, _parent.Height); - } - } + public override Rectangle DrawingBounds => new Rectangle(0,0,_parent?.Width??0, _parent?.Height ?? 0); public override void Draw(Graphics g, RenderMode rm) { + if (_parent == null) + { + return; + } using (Brush cropBrush = new SolidBrush(Color.FromArgb(100, 150, 150, 100))) { Rectangle cropRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); Rectangle selectionRect = new Rectangle(cropRectangle.Left - 1, cropRectangle.Top - 1, cropRectangle.Width + 1, cropRectangle.Height + 1); diff --git a/Greenshot/Drawing/CursorContainer.cs b/Greenshot/Drawing/CursorContainer.cs index 3911d5940..b1f67fd24 100644 --- a/Greenshot/Drawing/CursorContainer.cs +++ b/Greenshot/Drawing/CursorContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ using System.Windows.Forms; using Greenshot.Plugin.Drawing; using System.Drawing.Drawing2D; using log4net; +using System.Runtime.Serialization; namespace Greenshot.Drawing { /// @@ -33,14 +34,26 @@ namespace Greenshot.Drawing { /// [Serializable] public class CursorContainer : DrawableContainer, ICursorContainer { - private static ILog LOG = LogManager.GetLogger(typeof(CursorContainer)); + private static readonly ILog LOG = LogManager.GetLogger(typeof(CursorContainer)); protected Cursor cursor; public CursorContainer(Surface parent) : base(parent) { + Init(); } - public CursorContainer(Surface parent, string filename) : base(parent) { + protected override void OnDeserialized(StreamingContext streamingContext) + { + base.OnDeserialized(streamingContext); + Init(); + } + + private void Init() + { + CreateDefaultAdorners(); + } + + public CursorContainer(Surface parent, string filename) : this(parent) { Load(filename); } diff --git a/Greenshot/Drawing/DrawableContainer.cs b/Greenshot/Drawing/DrawableContainer.cs index aa4ffce43..92c3a92d7 100644 --- a/Greenshot/Drawing/DrawableContainer.cs +++ b/Greenshot/Drawing/DrawableContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ */ using Greenshot.Configuration; +using Greenshot.Drawing.Adorners; using Greenshot.Drawing.Fields; using Greenshot.Drawing.Filters; using Greenshot.Helpers; @@ -27,15 +28,19 @@ using Greenshot.IniFile; using Greenshot.Memento; using Greenshot.Plugin; using Greenshot.Plugin.Drawing; +using Greenshot.Plugin.Drawing.Adorners; +using GreenshotPlugin.Interfaces.Drawing; using log4net; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; +using System.Runtime.Serialization; using System.Windows.Forms; -namespace Greenshot.Drawing { +namespace Greenshot.Drawing +{ /// /// represents a rectangle, ellipse, label or whatever. Can contain filters, too. /// serializable for clipboard support @@ -46,12 +51,23 @@ namespace Greenshot.Drawing { public abstract class DrawableContainer : AbstractFieldHolderWithChildren, IDrawableContainer { private static readonly ILog LOG = LogManager.GetLogger(typeof(DrawableContainer)); protected static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection(); - private bool isMadeUndoable; private const int M11 = 0; - private const int M12 = 1; - private const int M21 = 2; private const int M22 = 3; + [OnDeserialized] + private void OnDeserializedInit(StreamingContext context) + { + _adorners = new List(); + OnDeserialized(context); + } + + /// + /// Override to implement your own deserialization logic, like initializing properties which are not serialized + /// + /// + protected virtual void OnDeserialized(StreamingContext streamingContext) + { + } protected EditStatus _defaultEditMode = EditStatus.DRAWING; public EditStatus DefaultEditMode { @@ -73,19 +89,7 @@ namespace Greenshot.Drawing { if (!disposing) { return; } - if (_grippers != null) { - for (int i = 0; i < _grippers.Length; i++) { - if (_grippers[i] == null) { - continue; - } - _grippers[i].Dispose(); - _grippers[i] = null; - } - _grippers = null; - } - - FieldAggregator aggProps = _parent.FieldAggregator; - aggProps.UnbindElement(this); + _parent?.FieldAggregator?.UnbindElement(this); } ~DrawableContainer() { @@ -99,7 +103,7 @@ namespace Greenshot.Drawing { remove{ _propertyChanged -= value; } } - public List Filters { + public IList Filters { get { List ret = new List(); foreach(IFieldHolder c in Children) { @@ -117,16 +121,12 @@ namespace Greenshot.Drawing { get { return _parent; } set { SwitchParent((Surface)value); } } - [NonSerialized] - protected Gripper[] _grippers; - private bool layoutSuspended; [NonSerialized] - private Gripper _targetGripper; - - public Gripper TargetGripper { + private TargetAdorner _targetAdorner; + public TargetAdorner TargetAdorner { get { - return _targetGripper; + return _targetAdorner; } } @@ -160,7 +160,6 @@ namespace Greenshot.Drawing { return; } left = value; - DoLayout(); } } @@ -172,7 +171,6 @@ namespace Greenshot.Drawing { return; } top = value; - DoLayout(); } } @@ -184,7 +182,6 @@ namespace Greenshot.Drawing { return; } width = value; - DoLayout(); } } @@ -196,7 +193,6 @@ namespace Greenshot.Drawing { return; } height = value; - DoLayout(); } } @@ -220,6 +216,19 @@ namespace Greenshot.Drawing { } } + /// + /// List of available Adorners + /// + [NonSerialized] + private IList _adorners = new List(); + public IList Adorners + { + get + { + return _adorners; + } + } + [NonSerialized] // will store current bounds of this DrawableContainer before starting a resize protected Rectangle _boundsBeforeResize = Rectangle.Empty; @@ -248,7 +257,6 @@ namespace Greenshot.Drawing { public DrawableContainer(Surface parent) { InitializeFields(); _parent = parent; - InitControls(); } public void Add(IFilter filter) { @@ -291,12 +299,15 @@ namespace Greenshot.Drawing { public virtual void Invalidate() { if (Status != EditStatus.UNDRAWN) { - _parent.Invalidate(DrawingBounds); + _parent?.Invalidate(DrawingBounds); } } public void AlignToParent(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) { - + if (_parent == null) + { + return; + } int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); if (horizontalAlignment == HorizontalAlignment.Left) { Left = lineThickness/2; @@ -322,188 +333,35 @@ namespace Greenshot.Drawing { public virtual bool InitContent() { return true; } public virtual void OnDoubleClick() {} - - private void InitControls() { - InitGrippers(); - - DoLayout(); - } - - /// - /// Move the TargetGripper around, confined to the surface to solve BUG-1682 - /// - /// - /// - protected virtual void TargetGripperMove(int newX, int newY) { - Point newGripperLocation = new Point(newX, newY); - Rectangle surfaceBounds = new Rectangle(0, 0, _parent.Width, _parent.Height); - // Check if gripper inside the parent (surface), if not we need to move it inside - // This was made for BUG-1682 - if (!surfaceBounds.Contains(newGripperLocation)) { - if (newGripperLocation.X > surfaceBounds.Right) { - newGripperLocation.X = surfaceBounds.Right - 5; - } - if (newGripperLocation.X < surfaceBounds.Left) { - newGripperLocation.X = surfaceBounds.Left; - } - if (newGripperLocation.Y > surfaceBounds.Bottom) { - newGripperLocation.Y = surfaceBounds.Bottom - 5; - } - if (newGripperLocation.Y < surfaceBounds.Top) { - newGripperLocation.Y = surfaceBounds.Top; - } - } - - _targetGripper.Left = newGripperLocation.X; - _targetGripper.Top = newGripperLocation.Y; - } /// /// Initialize a target gripper /// - protected void InitTargetGripper(Color gripperColor, Point location) { - _targetGripper = new Gripper { - Cursor = Cursors.SizeAll, - BackColor = gripperColor, - Visible = false, - Parent = _parent, - Location = location - }; - _targetGripper.MouseDown += GripperMouseDown; - _targetGripper.MouseUp += GripperMouseUp; - _targetGripper.MouseMove += GripperMouseMove; - if (_parent != null) { - _parent.Controls.Add(_targetGripper); // otherwise we'll attach them in switchParent - } + protected void InitAdorner(Color gripperColor, Point location) { + _targetAdorner = new TargetAdorner(this, location); + Adorners.Add(_targetAdorner); } - protected void InitGrippers() { - - _grippers = new Gripper[8]; - for(int i=0; i<_grippers.Length; i++) { - _grippers[i] = new Gripper(); - _grippers[i].Position = i; - _grippers[i].MouseDown += GripperMouseDown; - _grippers[i].MouseUp += GripperMouseUp; - _grippers[i].MouseMove += GripperMouseMove; - _grippers[i].Visible = false; - _grippers[i].Parent = _parent; - } - _grippers[Gripper.POSITION_TOP_CENTER].Cursor = Cursors.SizeNS; - _grippers[Gripper.POSITION_MIDDLE_RIGHT].Cursor = Cursors.SizeWE; - _grippers[Gripper.POSITION_BOTTOM_CENTER].Cursor = Cursors.SizeNS; - _grippers[Gripper.POSITION_MIDDLE_LEFT].Cursor = Cursors.SizeWE; - if (_parent != null) { - _parent.Controls.AddRange(_grippers); // otherwise we'll attach them in switchParent - } - } - - public void SuspendLayout() { - layoutSuspended = true; - } - - public void ResumeLayout() { - layoutSuspended = false; - DoLayout(); - } - - protected virtual void DoLayout() { - if (_grippers == null) { - return; - } - if (!layoutSuspended) { - int[] xChoords = {Left-2,Left+Width/2-2,Left+Width-2}; - int[] yChoords = {Top-2,Top+Height/2-2,Top+Height-2}; + /// + /// Create the default adorners for a rectangle based container + /// - _grippers[Gripper.POSITION_TOP_LEFT].Left = xChoords[0]; _grippers[Gripper.POSITION_TOP_LEFT].Top = yChoords[0]; - _grippers[Gripper.POSITION_TOP_CENTER].Left = xChoords[1]; _grippers[Gripper.POSITION_TOP_CENTER].Top = yChoords[0]; - _grippers[Gripper.POSITION_TOP_RIGHT].Left = xChoords[2]; _grippers[Gripper.POSITION_TOP_RIGHT].Top = yChoords[0]; - _grippers[Gripper.POSITION_MIDDLE_RIGHT].Left = xChoords[2]; _grippers[Gripper.POSITION_MIDDLE_RIGHT].Top = yChoords[1]; - _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left = xChoords[2]; _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top = yChoords[2]; - _grippers[Gripper.POSITION_BOTTOM_CENTER].Left = xChoords[1]; _grippers[Gripper.POSITION_BOTTOM_CENTER].Top = yChoords[2]; - _grippers[Gripper.POSITION_BOTTOM_LEFT].Left = xChoords[0]; _grippers[Gripper.POSITION_BOTTOM_LEFT].Top = yChoords[2]; - _grippers[Gripper.POSITION_MIDDLE_LEFT].Left = xChoords[0]; _grippers[Gripper.POSITION_MIDDLE_LEFT].Top = yChoords[1]; - - if((_grippers[Gripper.POSITION_TOP_LEFT].Left < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) || - _grippers[Gripper.POSITION_TOP_LEFT].Left > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) { - _grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeNWSE; - _grippers[Gripper.POSITION_TOP_RIGHT].Cursor = Cursors.SizeNESW; - _grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeNWSE; - _grippers[Gripper.POSITION_BOTTOM_LEFT].Cursor = Cursors.SizeNESW; - } else if((_grippers[Gripper.POSITION_TOP_LEFT].Left > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) || - _grippers[Gripper.POSITION_TOP_LEFT].Left < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) { - _grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeNESW; - _grippers[Gripper.POSITION_TOP_RIGHT].Cursor = Cursors.SizeNWSE; - _grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeNESW; - _grippers[Gripper.POSITION_BOTTOM_LEFT].Cursor = Cursors.SizeNWSE; - } else if (_grippers[Gripper.POSITION_TOP_LEFT].Left == _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left) { - _grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeNS; - _grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeNS; - } else if (_grippers[Gripper.POSITION_TOP_LEFT].Top == _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) { - _grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeWE; - _grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeWE; - } + protected void CreateDefaultAdorners() { + if (Adorners.Count > 0) + { + LOG.Warn("Adorners are already defined!"); } - } - - private void GripperMouseDown(object sender, MouseEventArgs e) { - Gripper originatingGripper = (Gripper)sender; - if (originatingGripper != _targetGripper) { - Status = EditStatus.RESIZING; - _boundsBeforeResize = new Rectangle(left, top, width, height); - _boundsAfterResize = new RectangleF(_boundsBeforeResize.Left, _boundsBeforeResize.Top, _boundsBeforeResize.Width, _boundsBeforeResize.Height); - } else { - Status = EditStatus.MOVING; - } - isMadeUndoable = false; + // Create the GripperAdorners + Adorners.Add(new ResizeAdorner(this, Positions.TopLeft)); + Adorners.Add(new ResizeAdorner(this, Positions.TopCenter)); + Adorners.Add(new ResizeAdorner(this, Positions.TopRight)); + Adorners.Add(new ResizeAdorner(this, Positions.BottomLeft)); + Adorners.Add(new ResizeAdorner(this, Positions.BottomCenter)); + Adorners.Add(new ResizeAdorner(this, Positions.BottomRight)); + Adorners.Add(new ResizeAdorner(this, Positions.MiddleLeft)); + Adorners.Add(new ResizeAdorner(this, Positions.MiddleRight)); } - private void GripperMouseUp(object sender, MouseEventArgs e) { - Gripper originatingGripper = (Gripper)sender; - if (originatingGripper != _targetGripper) { - _boundsBeforeResize = Rectangle.Empty; - _boundsAfterResize = RectangleF.Empty; - isMadeUndoable = false; - } - Status = EditStatus.IDLE; - Invalidate(); - } - - private void GripperMouseMove(object sender, MouseEventArgs e) { - Invalidate(); - Gripper originatingGripper = (Gripper)sender; - int absX = originatingGripper.Left + e.X; - int absY = originatingGripper.Top + e.Y; - if (originatingGripper == _targetGripper && Status.Equals(EditStatus.MOVING)) { - TargetGripperMove(absX, absY); - } else if (Status.Equals(EditStatus.RESIZING)) { - // check if we already made this undoable - if (!isMadeUndoable) { - // don't allow another undo until we are finished with this move - isMadeUndoable = true; - // Make undo-able - MakeBoundsChangeUndoable(false); - } - - SuspendLayout(); - - // reset "workbench" rectangle to current bounds - _boundsAfterResize.X = _boundsBeforeResize.X; - _boundsAfterResize.Y = _boundsBeforeResize.Y; - _boundsAfterResize.Width = _boundsBeforeResize.Width; - _boundsAfterResize.Height = _boundsBeforeResize.Height; - - // calculate scaled rectangle - ScaleHelper.Scale(ref _boundsAfterResize, originatingGripper.Position, new PointF(absX, absY), ScaleHelper.GetScaleOptions()); - - // apply scaled bounds to this DrawableContainer - ApplyBounds(_boundsAfterResize); - - ResumeLayout(); - } - Invalidate(); - } - public bool hasFilters { get { return Filters.Count > 0; @@ -525,12 +383,12 @@ namespace Greenshot.Drawing { Rectangle drawingRect = new Rectangle(Bounds.Location, Bounds.Size); drawingRect.Intersect(clipRectangle); if(filter is MagnifierFilter) { - // quick&dirty bugfix, because MagnifierFilter behaves differently when drawn only partially - // what we should actually do to resolve this is add a better magnifier which is not that special - filter.Apply(graphics, bmp, Bounds, renderMode); - } else { - filter.Apply(graphics, bmp, drawingRect, renderMode); - } + // quick&dirty bugfix, because MagnifierFilter behaves differently when drawn only partially + // what we should actually do to resolve this is add a better magnifier which is not that special + filter.Apply(graphics, bmp, Bounds, renderMode); + } else { + filter.Apply(graphics, bmp, drawingRect, renderMode); + } } } } @@ -558,43 +416,10 @@ namespace Greenshot.Drawing { } } - public virtual void ShowGrippers() { - if (_grippers != null) { - for (int i = 0; i < _grippers.Length; i++) { - if (_grippers[i].Enabled) { - _grippers[i].Show(); - } else { - _grippers[i].Hide(); - } - } - } - if (_targetGripper != null) { - if (_targetGripper.Enabled) { - _targetGripper.Show(); - } else { - _targetGripper.Hide(); - } - } - ResumeLayout(); - } - - public virtual void HideGrippers() { - SuspendLayout(); - if (_grippers != null) { - for (int i = 0; i < _grippers.Length; i++) { - _grippers[i].Hide(); - } - } - if (_targetGripper != null) { - _targetGripper.Hide(); - } - } - + public void ResizeTo(int width, int height, int anchorPosition) { - SuspendLayout(); Width = width; Height = height; - ResumeLayout(); } /// @@ -606,10 +431,8 @@ namespace Greenshot.Drawing { } public void MoveBy(int dx, int dy) { - SuspendLayout(); Left += dx; Top += dy; - ResumeLayout(); } /// @@ -632,7 +455,6 @@ namespace Greenshot.Drawing { /// true if the event is handled, false if the surface needs to handle it public virtual bool HandleMouseMove(int x, int y) { Invalidate(); - SuspendLayout(); // reset "workrbench" rectangle to current bounds _boundsAfterResize.X = _boundsBeforeResize.Left; @@ -645,7 +467,6 @@ namespace Greenshot.Drawing { // apply scaled bounds to this DrawableContainer ApplyBounds(_boundsAfterResize); - ResumeLayout(); Invalidate(); return true; } @@ -659,49 +480,18 @@ namespace Greenshot.Drawing { } protected virtual void SwitchParent(Surface newParent) { - // Target gripper - if (_parent != null && _targetGripper != null) { - _parent.Controls.Remove(_targetGripper); - } - // Normal grippers - if (_parent != null && _grippers != null) { - for (int i=0; i<_grippers.Length; i++) { - _parent.Controls.Remove(_grippers[i]); - } - } else if (_grippers == null) { - InitControls(); - } - _parent = newParent; - // Target gripper - if (_parent != null && _targetGripper != null) { - _parent.Controls.Add(_targetGripper); - } - // Normal grippers - if (_grippers != null) { - _parent.Controls.AddRange(_grippers); + if (newParent == Parent) + { + return; } + _parent?.FieldAggregator?.UnbindElement(this); + _parent = newParent; foreach(IFilter filter in Filters) { filter.Parent = this; } } - // drawablecontainers are regarded equal if they are of the same type and their bounds are equal. this should be sufficient. - public override bool Equals(object obj) { - bool ret = false; - if (obj != null && GetType() == obj.GetType()) { - DrawableContainer other = obj as DrawableContainer; - if (other != null && left==other.left && top==other.top && width==other.width && height==other.height) { - ret = true; - } - } - return ret; - } - - public override int GetHashCode() { - return left.GetHashCode() ^ top.GetHashCode() ^ width.GetHashCode() ^ height.GetHashCode() ^ GetFields().GetHashCode(); - } - protected void OnPropertyChanged(string propertyName) { if (_propertyChanged != null) { _propertyChanged(this, new PropertyChangedEventArgs(propertyName)); @@ -715,8 +505,8 @@ namespace Greenshot.Drawing { /// /// The field to be changed /// The new value - public virtual void BeforeFieldChange(Field fieldToBeChanged, object newValue) { - _parent.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true); + public virtual void BeforeFieldChange(IField fieldToBeChanged, object newValue) { + _parent?.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true); Invalidate(); } @@ -727,10 +517,9 @@ namespace Greenshot.Drawing { /// public void HandleFieldChanged(object sender, FieldChangedEventArgs e) { LOG.DebugFormat("Field {0} changed", e.Field.FieldType); - if (e.Field.FieldType == FieldType.SHADOW) { + if (Equals(e.Field.FieldType, FieldType.SHADOW)) { accountForShadowChange = true; } - Invalidate(); } /// @@ -775,26 +564,16 @@ namespace Greenshot.Drawing { if (matrix == null) { return; } - SuspendLayout(); Point topLeft = new Point(Left, Top); Point bottomRight = new Point(Left + Width, Top + Height); - Point[] points; - if (TargetGripper != null) { - points = new[] {topLeft, bottomRight, TargetGripper.Location}; - - } else { - points = new[] { topLeft, bottomRight }; - } + Point[] points = new[] { topLeft, bottomRight }; matrix.TransformPoints(points); Left = points[0].X; Top = points[0].Y; Width = points[1].X - points[0].X; Height = points[1].Y - points[0].Y; - if (TargetGripper != null) { - TargetGripper.Location = points[points.Length-1]; - } - ResumeLayout(); + } protected virtual ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() { diff --git a/Greenshot/Drawing/DrawableContainerList.cs b/Greenshot/Drawing/DrawableContainerList.cs index 570949a40..3b0808ad3 100644 --- a/Greenshot/Drawing/DrawableContainerList.cs +++ b/Greenshot/Drawing/DrawableContainerList.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,11 +20,11 @@ */ using Greenshot.Configuration; -using Greenshot.Drawing.Fields; using Greenshot.Memento; using Greenshot.Plugin; using Greenshot.Plugin.Drawing; using GreenshotPlugin.Core; +using GreenshotPlugin.Interfaces.Drawing; using System; using System.Collections.Generic; using System.ComponentModel; @@ -38,8 +38,9 @@ namespace Greenshot.Drawing { /// Dispatches most of a DrawableContainer's public properties and methods to a list of DrawableContainers. /// [Serializable] - public class DrawableContainerList : List { - private static readonly ComponentResourceManager editorFormResources = new ComponentResourceManager(typeof(ImageEditorForm)); + public class DrawableContainerList : List, IDrawableContainerList + { + private static readonly ComponentResourceManager EditorFormResources = new ComponentResourceManager(typeof(ImageEditorForm)); public Guid ParentID { get; @@ -49,8 +50,8 @@ namespace Greenshot.Drawing { public DrawableContainerList() { } - public DrawableContainerList(Guid parentID) { - ParentID = parentID; + public DrawableContainerList(Guid parentId) { + ParentID = parentId; } public EditStatus Status { @@ -116,14 +117,11 @@ namespace Greenshot.Drawing { /// /// true means allow the moves to be merged public void MakeBoundsChangeUndoable(bool allowMerge) { - List movingList = new List(); - Surface surface = null; - foreach(DrawableContainer dc in this) { - movingList.Add(dc); - surface = dc._parent; - } - if (movingList.Count > 0 && surface != null) { - surface.MakeUndoable(new DrawableContainerBoundsChangeMemento(movingList), allowMerge); + if (Count > 0 && Parent != null) + { + var clone = new DrawableContainerList(); + clone.AddRange(this); + Parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(clone), allowMerge); } } @@ -171,26 +169,6 @@ namespace Greenshot.Drawing { } } - /// - /// Hides the grippers of all elements in the list. - /// - public void HideGrippers() { - foreach(var dc in this) { - dc.HideGrippers(); - dc.Invalidate(); - } - } - - /// - /// Shows the grippers of all elements in the list. - /// - public void ShowGrippers() { - foreach(var dc in this) { - dc.ShowGrippers(); - dc.Invalidate(); - } - } - /// /// Indicates whether on of the elements is clickable at the given location /// @@ -266,9 +244,19 @@ namespace Greenshot.Drawing { /// the rendermode in which the element is to be drawn /// public void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle) { - foreach(var drawableContainer in this) { - var dc = (DrawableContainer) drawableContainer; - if (dc.DrawingBounds.IntersectsWith(clipRectangle)) { + if (Parent == null) + { + return; + } + foreach (var drawableContainer in this) + { + var dc = (DrawableContainer)drawableContainer; + if (dc.Parent == null) + { + continue; + } + if (dc.DrawingBounds.IntersectsWith(clipRectangle)) + { dc.DrawContent(g, bitmap, renderMode, clipRectangle); } } @@ -290,9 +278,16 @@ namespace Greenshot.Drawing { /// Invalidate the bounds of all the DC's in this list /// public void Invalidate() { - foreach(var dc in this) { - dc.Invalidate(); + if (Parent == null) + { + return; } + Rectangle region = Rectangle.Empty; + foreach (var dc in this) + { + region = Rectangle.Union(region, dc.DrawingBounds); + } + Parent.Invalidate(region); } /// /// Indicates whether the given list of elements can be pulled up, @@ -300,7 +295,7 @@ namespace Greenshot.Drawing { /// /// list of elements to pull up /// true if the elements could be pulled up - public bool CanPullUp(DrawableContainerList elements) { + public bool CanPullUp(IDrawableContainerList elements) { if (elements.Count == 0 || elements.Count == Count) { return false; } @@ -316,13 +311,13 @@ namespace Greenshot.Drawing { /// Pulls one or several elements up one level in hierarchy (z-index). /// /// list of elements to pull up - public void PullElementsUp(DrawableContainerList elements) { + public void PullElementsUp(IDrawableContainerList elements) { for(int i=Count-1; i>=0; i--) { var dc = this[i]; if (!elements.Contains(dc)) { continue; } - if (Count > (i+1) && !elements.Contains(this[i+1])) { + if (Count > i+1 && !elements.Contains(this[i+1])) { SwapElements(i,i+1); } } @@ -332,10 +327,11 @@ namespace Greenshot.Drawing { /// Pulls one or several elements up to the topmost level(s) in hierarchy (z-index). /// /// of elements to pull to top - public void PullElementsToTop(DrawableContainerList elements) { + public void PullElementsToTop(IDrawableContainerList elements) + { var dcs = ToArray(); - for(int i=0; i /// Indicates whether the given list of elements can be pushed down, /// i.e. whether there is at least one unselected element lower in hierarchy /// /// list of elements to push down /// true if the elements could be pushed down - public bool CanPushDown(DrawableContainerList elements) { + public bool CanPushDown(IDrawableContainerList elements) { if (elements.Count == 0 || elements.Count == Count) { return false; } @@ -367,7 +363,7 @@ namespace Greenshot.Drawing { /// Pushes one or several elements down one level in hierarchy (z-index). /// /// list of elements to push down - public void PushElementsDown(DrawableContainerList elements) { + public void PushElementsDown(IDrawableContainerList elements) { for(int i=0; i /// of elements to push to bottom - public void PushElementsToBottom(DrawableContainerList elements) { + public void PushElementsToBottom(IDrawableContainerList elements) { var dcs = ToArray(); for(int i=dcs.Length-1; i>=0; i--) { var dc = dcs[i]; @@ -417,7 +413,7 @@ namespace Greenshot.Drawing { /// /// /// - public virtual void AddContextMenuItems(ContextMenuStrip menu, Surface surface) { + public virtual void AddContextMenuItems(ContextMenuStrip menu, ISurface surface) { bool push = surface.Elements.CanPushDown(this); bool pull = surface.Elements.CanPullUp(this); @@ -457,7 +453,7 @@ namespace Greenshot.Drawing { // Duplicate item = new ToolStripMenuItem(Language.GetString(LangKey.editor_duplicate)); item.Click += delegate { - DrawableContainerList dcs = this.Clone(); + IDrawableContainerList dcs = this.Clone(); dcs.Parent = surface; dcs.MoveBy(10, 10); surface.AddElements(dcs); @@ -467,49 +463,41 @@ namespace Greenshot.Drawing { menu.Items.Add(item); // Copy - item = new ToolStripMenuItem(Language.GetString(LangKey.editor_copytoclipboard)); - item.Image = ((Image)(editorFormResources.GetObject("copyToolStripMenuItem.Image"))); + item = new ToolStripMenuItem(Language.GetString(LangKey.editor_copytoclipboard)) + { + Image = (Image) EditorFormResources.GetObject("copyToolStripMenuItem.Image") + }; item.Click += delegate { - ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), this); + ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), this); }; menu.Items.Add(item); // Cut - item = new ToolStripMenuItem(Language.GetString(LangKey.editor_cuttoclipboard)); - item.Image = ((Image)(editorFormResources.GetObject("btnCut.Image"))); + item = new ToolStripMenuItem(Language.GetString(LangKey.editor_cuttoclipboard)) + { + Image = (Image) EditorFormResources.GetObject("btnCut.Image") + }; item.Click += delegate { - ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), this); - List containersToDelete = new List(); - foreach (var drawableContainer in this) { - var container = (DrawableContainer) drawableContainer; - containersToDelete.Add(container); - } - foreach (var container in containersToDelete) { - surface.RemoveElement(container, true); - } + ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), this); + surface.RemoveElements(this); }; menu.Items.Add(item); // Delete item = new ToolStripMenuItem(Language.GetString(LangKey.editor_deleteelement)); - item.Image = ((Image)(editorFormResources.GetObject("removeObjectToolStripMenuItem.Image"))); + item.Image = (Image)EditorFormResources.GetObject("removeObjectToolStripMenuItem.Image"); item.Click += delegate { - List containersToDelete = new List(); - foreach(var drawableContainer in this) { - var container = (DrawableContainer) drawableContainer; - containersToDelete.Add(container); - } - foreach (DrawableContainer container in containersToDelete) { - surface.RemoveElement(container, true); - } + surface.RemoveElements(this); }; menu.Items.Add(item); // Reset bool canReset = false; - foreach (var drawableContainer in this) { - var container = (DrawableContainer) drawableContainer; - if (container.HasDefaultSize) { + foreach (var drawableContainer in this) + { + var container = (DrawableContainer)drawableContainer; + if (container.HasDefaultSize) + { canReset = true; } } @@ -517,24 +505,29 @@ namespace Greenshot.Drawing { item = new ToolStripMenuItem(Language.GetString(LangKey.editor_resetsize)); //item.Image = ((System.Drawing.Image)(editorFormResources.GetObject("removeObjectToolStripMenuItem.Image"))); item.Click += delegate { + MakeBoundsChangeUndoable(false); foreach (var drawableContainer in this) { var container = (DrawableContainer) drawableContainer; if (!container.HasDefaultSize) { continue; } Size defaultSize = container.DefaultSize; - container.Invalidate(); container.MakeBoundsChangeUndoable(false); container.Width = defaultSize.Width; container.Height = defaultSize.Height; - container.Invalidate(); } + surface.Invalidate(); }; menu.Items.Add(item); } } - public virtual void ShowContextMenu(MouseEventArgs e, Surface surface) { + public virtual void ShowContextMenu(MouseEventArgs e, ISurface surface) + { + if (!(surface is Surface)) + { + return; + } bool hasMenu = false; foreach (var drawableContainer in this) { var container = (DrawableContainer) drawableContainer; @@ -548,7 +541,8 @@ namespace Greenshot.Drawing { ContextMenuStrip menu = new ContextMenuStrip(); AddContextMenuItems(menu, surface); if (menu.Items.Count > 0) { - menu.Show(surface, e.Location); + // TODO: cast should be somehow avoided + menu.Show((Surface)surface, e.Location); while (true) { if (menu.Visible) { Application.DoEvents(); @@ -561,5 +555,32 @@ namespace Greenshot.Drawing { } } } + + #region IDisposable Support + private bool _disposedValue; // To detect redundant calls + + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + foreach (var drawableContainer in this) + { + drawableContainer.Dispose(); + } + } + + _disposedValue = true; + } + } + + // This code added to correctly implement the disposable pattern. + public void Dispose() + { + // Do not change this code. Put cleanup code in Dispose(bool disposing) above. + Dispose(true); + } + #endregion } } diff --git a/Greenshot/Drawing/EllipseContainer.cs b/Greenshot/Drawing/EllipseContainer.cs index caf41824b..a2bc4b6ee 100644 --- a/Greenshot/Drawing/EllipseContainer.cs +++ b/Greenshot/Drawing/EllipseContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,7 @@ namespace Greenshot.Drawing { [Serializable()] public class EllipseContainer : DrawableContainer { public EllipseContainer(Surface parent) : base(parent) { + CreateDefaultAdorners(); } protected override void InitializeFields() { @@ -59,12 +60,15 @@ namespace Greenshot.Drawing { /// /// This allows another container to draw an ellipse /// - /// + /// /// /// + /// + /// + /// + /// public static void DrawEllipse(Rectangle rect, Graphics graphics, RenderMode renderMode, int lineThickness, Color lineColor, Color fillColor, bool shadow) { - - bool lineVisible = (lineThickness > 0 && Colors.IsVisible(lineColor)); + bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor); // draw shadow before anything else if (shadow && (lineVisible || Colors.IsVisible(fillColor))) { int basealpha = 100; diff --git a/Greenshot/Drawing/Fields/AbstractFieldHolder.cs b/Greenshot/Drawing/Fields/AbstractFieldHolder.cs index 0f8df4937..1a31e073e 100644 --- a/Greenshot/Drawing/Fields/AbstractFieldHolder.cs +++ b/Greenshot/Drawing/Fields/AbstractFieldHolder.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,147 +20,183 @@ */ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Drawing; using System.Runtime.Serialization; using Greenshot.Configuration; using Greenshot.IniFile; using log4net; +using GreenshotPlugin.Interfaces.Drawing; -namespace Greenshot.Drawing.Fields { +namespace Greenshot.Drawing.Fields +{ /// /// Basic IFieldHolder implementation, providing access to a set of fields /// [Serializable] - public abstract class AbstractFieldHolder : IFieldHolder { + public abstract class AbstractFieldHolder : IFieldHolder + { private static readonly ILog LOG = LogManager.GetLogger(typeof(AbstractFieldHolder)); - private static EditorConfiguration editorConfiguration = IniConfig.GetIniSection(); + private static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection(); + [NonSerialized] + private readonly IDictionary _handlers = new Dictionary(); /// /// called when a field's value has changed /// [NonSerialized] - private FieldChangedEventHandler fieldChanged; - public event FieldChangedEventHandler FieldChanged { - add { fieldChanged += value; } - remove{ fieldChanged -= value; } + private FieldChangedEventHandler _fieldChanged; + + public event FieldChangedEventHandler FieldChanged + { + add { _fieldChanged += value; } + remove { _fieldChanged -= value; } } - + // we keep two Collections of our fields, dictionary for quick access, list for serialization // this allows us to use default serialization [NonSerialized] - private Dictionary fieldsByType = new Dictionary(); - private List fields = new List(); - - public AbstractFieldHolder() {} - + private IDictionary _fieldsByType = new Dictionary(); + private readonly IList fields = new List(); + [OnDeserialized] - private void OnDeserialized(StreamingContext context) { - fieldsByType = new Dictionary(); + private void OnDeserialized(StreamingContext context) + { + _fieldsByType = new Dictionary(); // listen to changing properties - foreach(Field field in fields) { + foreach (var field in fields) + { field.PropertyChanged += delegate { - if (fieldChanged != null) { - fieldChanged(this, new FieldChangedEventArgs(field)); - } + _fieldChanged?.Invoke(this, new FieldChangedEventArgs(field)); }; - fieldsByType[field.FieldType] = field; + _fieldsByType[field.FieldType] = field; } } - public void AddField(Type requestingType, FieldType fieldType, object fieldValue) { - AddField(editorConfiguration.CreateField(requestingType, fieldType, fieldValue)); + public void AddField(Type requestingType, IFieldType fieldType, object fieldValue) + { + AddField(EditorConfig.CreateField(requestingType, fieldType, fieldValue)); } - public virtual void AddField(Field field) { - if (fieldsByType != null && fieldsByType.ContainsKey(field.FieldType)) { - if (LOG.IsDebugEnabled) { + public virtual void AddField(IField field) + { + fields.Add(field); + if (_fieldsByType == null) + { + return; + } + + if (_fieldsByType.ContainsKey(field.FieldType)) + { + if (LOG.IsDebugEnabled) + { LOG.DebugFormat("A field with of type '{0}' already exists in this {1}, will overwrite.", field.FieldType, GetType()); } - } - - fields.Add(field); - fieldsByType[field.FieldType] = field; - field.PropertyChanged += delegate { if(fieldChanged != null) fieldChanged(this, new FieldChangedEventArgs(field)); }; - } - - public void RemoveField(Field field) { - fields.Remove(field); - fieldsByType.Remove(field.FieldType); - field.PropertyChanged -= delegate { - if (fieldChanged != null) { - fieldChanged(this, new FieldChangedEventArgs(field)); - } + } + + _fieldsByType[field.FieldType] = field; + + _handlers[field] = (sender, args) => + { + _fieldChanged?.Invoke(this, new FieldChangedEventArgs(field)); }; + field.PropertyChanged += _handlers[field]; } - - public List GetFields() { + + public void RemoveField(IField field) + { + fields.Remove(field); + _fieldsByType.Remove(field.FieldType); + field.PropertyChanged -= _handlers[field]; + _handlers.Remove(field); + } + + public IList GetFields() + { return fields; } - - public Field GetField(FieldType fieldType) { - try { - return fieldsByType[fieldType]; - } catch(KeyNotFoundException e) { + + public IField GetField(IFieldType fieldType) + { + try + { + return _fieldsByType[fieldType]; + } + catch (KeyNotFoundException e) + { throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e); } } - - public object GetFieldValue(FieldType fieldType) { + + public object GetFieldValue(IFieldType fieldType) + { return GetField(fieldType).Value; } - + #region convenience methods to save us some casts outside - public string GetFieldValueAsString(FieldType fieldType) { + public string GetFieldValueAsString(IFieldType fieldType) + { return Convert.ToString(GetFieldValue(fieldType)); } - - public int GetFieldValueAsInt(FieldType fieldType) { + + public int GetFieldValueAsInt(IFieldType fieldType) + { return Convert.ToInt32(GetFieldValue(fieldType)); } - - public decimal GetFieldValueAsDecimal(FieldType fieldType) { + + public decimal GetFieldValueAsDecimal(IFieldType fieldType) + { return Convert.ToDecimal(GetFieldValue(fieldType)); } - - public double GetFieldValueAsDouble(FieldType fieldType) { + + public double GetFieldValueAsDouble(IFieldType fieldType) + { return Convert.ToDouble(GetFieldValue(fieldType)); } - - public float GetFieldValueAsFloat(FieldType fieldType) { + + public float GetFieldValueAsFloat(IFieldType fieldType) + { return Convert.ToSingle(GetFieldValue(fieldType)); } - - public bool GetFieldValueAsBool(FieldType fieldType) { + + public bool GetFieldValueAsBool(IFieldType fieldType) + { return Convert.ToBoolean(GetFieldValue(fieldType)); } - - public Color GetFieldValueAsColor(FieldType fieldType) { + + public Color GetFieldValueAsColor(IFieldType fieldType) + { return (Color)GetFieldValue(fieldType); } #endregion - - public bool HasField(FieldType fieldType) { - return fieldsByType.ContainsKey(fieldType); + + public bool HasField(IFieldType fieldType) + { + return _fieldsByType.ContainsKey(fieldType); } - - public bool HasFieldValue(FieldType fieldType) { - return HasField(fieldType) && fieldsByType[fieldType].HasValue; + + public bool HasFieldValue(IFieldType fieldType) + { + return HasField(fieldType) && _fieldsByType[fieldType].HasValue; } - - public void SetFieldValue(FieldType fieldType, object value) { - try { - fieldsByType[fieldType].Value = value; - } catch(KeyNotFoundException e) { - throw new ArgumentException("Field '"+fieldType+"' does not exist in " + GetType(), e); + + public void SetFieldValue(IFieldType fieldType, object value) + { + try + { + _fieldsByType[fieldType].Value = value; + } + catch (KeyNotFoundException e) + { + throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e); } } - - protected void OnFieldChanged(object sender, FieldChangedEventArgs e){ - if (fieldChanged != null) { - fieldChanged(sender, e); - } + + protected void OnFieldChanged(object sender, FieldChangedEventArgs e) + { + _fieldChanged?.Invoke(sender, e); } } } diff --git a/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs b/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs index b919edd9b..e76626b2c 100644 --- a/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs +++ b/Greenshot/Drawing/Fields/AbstractFieldHolderWithChildren.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,87 +18,110 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using GreenshotPlugin.Interfaces.Drawing; using System; using System.Collections.Generic; using System.Runtime.Serialization; -namespace Greenshot.Drawing.Fields { +namespace Greenshot.Drawing.Fields +{ /// /// Basic IFieldHolderWithChildren implementation. Similar to IFieldHolder, - /// but has a List of children. + /// but has a List of IFieldHolder for children. /// Field values are passed to and from children as well. /// - [Serializable()] - public abstract class AbstractFieldHolderWithChildren : AbstractFieldHolder { - - FieldChangedEventHandler fieldChangedEventHandler; - + [Serializable] + public abstract class AbstractFieldHolderWithChildren : AbstractFieldHolder + { + [NonSerialized] + private readonly FieldChangedEventHandler _fieldChangedEventHandler; + [NonSerialized] private EventHandler childrenChanged; - public event EventHandler ChildrenChanged { + public event EventHandler ChildrenChanged + { add { childrenChanged += value; } remove { childrenChanged -= value; } } - + public List Children = new List(); - - public AbstractFieldHolderWithChildren() { - fieldChangedEventHandler = OnFieldChanged; + + public AbstractFieldHolderWithChildren() + { + _fieldChangedEventHandler = OnFieldChanged; } - + [OnDeserialized()] - private void OnDeserialized(StreamingContext context) { + private void OnDeserialized(StreamingContext context) + { // listen to changing properties - foreach(IFieldHolder fieldHolder in Children) { - fieldHolder.FieldChanged += fieldChangedEventHandler; + foreach (IFieldHolder fieldHolder in Children) + { + fieldHolder.FieldChanged += _fieldChangedEventHandler; } - if(childrenChanged != null) childrenChanged(this, EventArgs.Empty); + childrenChanged?.Invoke(this, EventArgs.Empty); } - - public void AddChild(IFieldHolder fieldHolder) { + + public void AddChild(IFieldHolder fieldHolder) + { Children.Add(fieldHolder); - fieldHolder.FieldChanged += fieldChangedEventHandler; - if(childrenChanged != null) childrenChanged(this, EventArgs.Empty); + fieldHolder.FieldChanged += _fieldChangedEventHandler; + childrenChanged?.Invoke(this, EventArgs.Empty); } - - public void RemoveChild(IFieldHolder fieldHolder) { + + public void RemoveChild(IFieldHolder fieldHolder) + { Children.Remove(fieldHolder); - fieldHolder.FieldChanged -= fieldChangedEventHandler; - if(childrenChanged != null) childrenChanged(this, EventArgs.Empty); + fieldHolder.FieldChanged -= _fieldChangedEventHandler; + childrenChanged?.Invoke(this, EventArgs.Empty); } - - public new List GetFields() { - List ret = new List(); + + public new IList GetFields() + { + var ret = new List(); ret.AddRange(base.GetFields()); - foreach(IFieldHolder fh in Children) { + foreach (IFieldHolder fh in Children) + { ret.AddRange(fh.GetFields()); } return ret; } - - public new Field GetField(FieldType fieldType) { - Field ret = null; - if(base.HasField(fieldType)) { + + public new IField GetField(IFieldType fieldType) + { + IField ret = null; + if (base.HasField(fieldType)) + { ret = base.GetField(fieldType); - } else { - foreach(IFieldHolder fh in Children) { - if(fh.HasField(fieldType)) { + } + else + { + foreach (IFieldHolder fh in Children) + { + if (fh.HasField(fieldType)) + { ret = fh.GetField(fieldType); break; } } } - if(ret == null) { - throw new ArgumentException("Field '"+fieldType+"' does not exist in " + GetType()); + if (ret == null) + { + throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType()); } return ret; } - - public new bool HasField(FieldType fieldType) { + + public new bool HasField(IFieldType fieldType) + { bool ret = base.HasField(fieldType); - if(!ret) { - foreach(IFieldHolder fh in Children) { - if(fh.HasField(fieldType)) { + if (!ret) + { + foreach (IFieldHolder fh in Children) + { + if (fh.HasField(fieldType)) + { ret = true; break; } @@ -106,16 +129,18 @@ namespace Greenshot.Drawing.Fields { } return ret; } - - public new bool HasFieldValue(FieldType fieldType) { - Field f = GetField(fieldType); + + public new bool HasFieldValue(IFieldType fieldType) + { + IField f = GetField(fieldType); return f != null && f.HasValue; } - - public new void SetFieldValue(FieldType fieldType, object value) { - Field f = GetField(fieldType); - if(f != null) f.Value = value; + + public new void SetFieldValue(IFieldType fieldType, object value) + { + IField f = GetField(fieldType); + if (f != null) f.Value = value; } - + } } diff --git a/Greenshot/Drawing/Fields/Binding/AbstractBindingConverter.cs b/Greenshot/Drawing/Fields/Binding/AbstractBindingConverter.cs index da43dd6f3..fd86f07b1 100644 --- a/Greenshot/Drawing/Fields/Binding/AbstractBindingConverter.cs +++ b/Greenshot/Drawing/Fields/Binding/AbstractBindingConverter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,8 +26,6 @@ namespace Greenshot.Drawing.Fields.Binding { /// public abstract class AbstractBindingConverter : IBindingConverter { - public AbstractBindingConverter() {} - public object convert(object o) { if(o == null) { return null; diff --git a/Greenshot/Drawing/Fields/Binding/BidirectionalBinding.cs b/Greenshot/Drawing/Fields/Binding/BidirectionalBinding.cs index 21ebeb1ef..69aa3feae 100644 --- a/Greenshot/Drawing/Fields/Binding/BidirectionalBinding.cs +++ b/Greenshot/Drawing/Fields/Binding/BidirectionalBinding.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,35 +29,35 @@ namespace Greenshot.Drawing.Fields.Binding { /// behavior (e.g. when binding to a /// public class BidirectionalBinding { - private INotifyPropertyChanged controlObject; - private INotifyPropertyChanged fieldObject; - private string controlPropertyName; - private string fieldPropertyName; - private bool updatingControl = false; - private bool updatingField = false; - private IBindingConverter converter; - private IBindingValidator validator; + private readonly INotifyPropertyChanged _controlObject; + private readonly INotifyPropertyChanged _fieldObject; + private readonly string _controlPropertyName; + private readonly string _fieldPropertyName; + private bool _updatingControl; + private bool _updatingField; + private IBindingConverter _converter; + private readonly IBindingValidator _validator; /// /// Whether or not null values are passed on to the other object. /// protected bool AllowSynchronizeNull = true; - + /// /// Bind properties of two objects bidirectionally /// - /// Object containing 1st property to bind - /// Property of 1st object to bind - /// Object containing 2nd property to bind - /// Property of 2nd object to bind + /// Object containing 1st property to bind + /// Property of 1st object to bind + /// Object containing 2nd property to bind + /// Property of 2nd object to bind public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName) { - this.controlObject = controlObject; - this.fieldObject = fieldObject; - this.controlPropertyName = controlPropertyName; - this.fieldPropertyName = fieldPropertyName; + _controlObject = controlObject; + _fieldObject = fieldObject; + _controlPropertyName = controlPropertyName; + _fieldPropertyName = fieldPropertyName; - this.controlObject.PropertyChanged += ControlPropertyChanged; - this.fieldObject.PropertyChanged += FieldPropertyChanged; + _controlObject.PropertyChanged += ControlPropertyChanged; + _fieldObject.PropertyChanged += FieldPropertyChanged; } /// @@ -69,7 +69,7 @@ namespace Greenshot.Drawing.Fields.Binding { /// Property of 2nd object to bind /// taking care of converting the synchronized value to the correct target format and back public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName) { - this.converter = converter; + _converter = converter; } /// @@ -82,7 +82,7 @@ namespace Greenshot.Drawing.Fields.Binding { /// Property of 2nd object to bind /// validator to intercept synchronization if the value does not match certain criteria public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingValidator validator) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName) { - this.validator = validator; + _validator = validator; } /// @@ -96,46 +96,46 @@ namespace Greenshot.Drawing.Fields.Binding { /// taking care of converting the synchronized value to the correct target format and back /// validator to intercept synchronization if the value does not match certain criteria public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter, IBindingValidator validator) : this(controlObject, controlPropertyName, fieldObject, fieldPropertyName, converter) { - this.validator = validator; + _validator = validator; } public void ControlPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (!updatingControl && e.PropertyName.Equals(controlPropertyName)) { - updatingField = true; - synchronize(controlObject, controlPropertyName, fieldObject, fieldPropertyName); - updatingField = false; + if (!_updatingControl && e.PropertyName.Equals(_controlPropertyName)) { + _updatingField = true; + Synchronize(_controlObject, _controlPropertyName, _fieldObject, _fieldPropertyName); + _updatingField = false; } } public void FieldPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (!updatingField && e.PropertyName.Equals(fieldPropertyName)) { - updatingControl = true; - synchronize(fieldObject, fieldPropertyName, controlObject, controlPropertyName); - updatingControl = false; + if (!_updatingField && e.PropertyName.Equals(_fieldPropertyName)) { + _updatingControl = true; + Synchronize(_fieldObject, _fieldPropertyName, _controlObject, _controlPropertyName); + _updatingControl = false; } } - private void synchronize(INotifyPropertyChanged sourceObject, string sourceProperty, INotifyPropertyChanged targetObject, string targetProperty) { - PropertyInfo targetPropertyInfo = resolvePropertyInfo(targetObject, targetProperty); - PropertyInfo sourcePropertyInfo = resolvePropertyInfo(sourceObject, sourceProperty); + private void Synchronize(INotifyPropertyChanged sourceObject, string sourceProperty, INotifyPropertyChanged targetObject, string targetProperty) { + PropertyInfo targetPropertyInfo = ResolvePropertyInfo(targetObject, targetProperty); + PropertyInfo sourcePropertyInfo = ResolvePropertyInfo(sourceObject, sourceProperty); if (sourcePropertyInfo != null && targetPropertyInfo != null && targetPropertyInfo.CanWrite) { object bValue = sourcePropertyInfo.GetValue(sourceObject, null); - if (converter != null && bValue != null) { - bValue = converter.convert(bValue); + if (_converter != null && bValue != null) { + bValue = _converter.convert(bValue); } try { - if (validator == null || validator.validate(bValue)) { + if (_validator == null || _validator.validate(bValue)) { targetPropertyInfo.SetValue(targetObject, bValue, null); } } catch (Exception e) { - throw new MemberAccessException("Could not set property '"+targetProperty+"' to '"+bValue+"' ["+((bValue!=null)?bValue.GetType().Name:"")+"] on "+targetObject+". Probably other type than expected, IBindingCoverter to the rescue.", e); + throw new MemberAccessException("Could not set property '"+targetProperty+"' to '"+bValue+"' ["+(bValue?.GetType().Name ?? "")+"] on "+targetObject+". Probably other type than expected, IBindingCoverter to the rescue.", e); } } } - private PropertyInfo resolvePropertyInfo(object obj, string property) { + private static PropertyInfo ResolvePropertyInfo(object obj, string property) { PropertyInfo ret = null; string[] properties = property.Split(".".ToCharArray()); for(int i=0; i - /// Converts decimal to double (%) and vice versa, e.g. 95f <---> 0.95d + /// Converts decimal to double (%) and vice versa, e.g. 95f to 0.95d /// public class DecimalDoublePercentageConverter : AbstractBindingConverter { diff --git a/Greenshot/Drawing/Fields/Binding/DecimalFloatConverter.cs b/Greenshot/Drawing/Fields/Binding/DecimalFloatConverter.cs index 0d53793ec..1a9ce5de4 100644 --- a/Greenshot/Drawing/Fields/Binding/DecimalFloatConverter.cs +++ b/Greenshot/Drawing/Fields/Binding/DecimalFloatConverter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Drawing/Fields/Binding/DecimalIntConverter.cs b/Greenshot/Drawing/Fields/Binding/DecimalIntConverter.cs index 9610e9759..07b131088 100644 --- a/Greenshot/Drawing/Fields/Binding/DecimalIntConverter.cs +++ b/Greenshot/Drawing/Fields/Binding/DecimalIntConverter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Drawing/Fields/Binding/IBindingConverter.cs b/Greenshot/Drawing/Fields/Binding/IBindingConverter.cs index 82a2129b3..0811d9550 100644 --- a/Greenshot/Drawing/Fields/Binding/IBindingConverter.cs +++ b/Greenshot/Drawing/Fields/Binding/IBindingConverter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Drawing/Fields/Binding/IBindingValidator.cs b/Greenshot/Drawing/Fields/Binding/IBindingValidator.cs index 6edc70f6e..ad0ac6215 100644 --- a/Greenshot/Drawing/Fields/Binding/IBindingValidator.cs +++ b/Greenshot/Drawing/Fields/Binding/IBindingValidator.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Drawing/Fields/Binding/NotNullValidator.cs b/Greenshot/Drawing/Fields/Binding/NotNullValidator.cs index 06254324f..971ae7b20 100644 --- a/Greenshot/Drawing/Fields/Binding/NotNullValidator.cs +++ b/Greenshot/Drawing/Fields/Binding/NotNullValidator.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Drawing/Fields/Field.cs b/Greenshot/Drawing/Fields/Field.cs index 28246a6cc..f6434b73a 100644 --- a/Greenshot/Drawing/Fields/Field.cs +++ b/Greenshot/Drawing/Fields/Field.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,36 +18,50 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + +using GreenshotPlugin.Interfaces.Drawing; using System; using System.ComponentModel; -namespace Greenshot.Drawing.Fields { +namespace Greenshot.Drawing.Fields +{ /// /// Represents a single field of a drawable element, i.e. /// line thickness of a rectangle. /// [Serializable] - public class Field : INotifyPropertyChanged { - [field:NonSerialized] + public class Field : IField + { + [field: NonSerialized] public event PropertyChangedEventHandler PropertyChanged; - - public object myValue; - public object Value { - get { - return myValue; + + private object _myValue; + public object Value + { + get + { + return _myValue; } - set { - if (!Equals(myValue,value)) { - myValue = value; - if (PropertyChanged!=null) { - PropertyChanged(this, new PropertyChangedEventArgs("Value")); - } + set + { + if (!Equals(_myValue, value)) + { + _myValue = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Value")); } } } - public FieldType FieldType; - public string Scope; - + public IFieldType FieldType + { + get; + set; + } + public string Scope + { + get; + set; + } + /// /// Constructs a new Field instance, usually you should be using FieldFactory /// to create Fields. @@ -59,70 +73,59 @@ namespace Greenshot.Drawing.Fields { /// When scope is set to a Type (e.g. typeof(RectangleContainer)), its value /// should not be reused for FieldHolders of another Type (e.g. typeof(EllipseContainer)) /// - public Field(FieldType fieldType, Type scope) { + public Field(IFieldType fieldType, Type scope) + { FieldType = fieldType; Scope = scope.Name; } - public Field(FieldType fieldType, string scope) { + public Field(IFieldType fieldType, string scope) + { FieldType = fieldType; Scope = scope; } - public Field(FieldType fieldType) { + public Field(IFieldType fieldType) + { FieldType = fieldType; } /// /// Returns true if this field holds a value other than null. /// - public bool HasValue { - get{ return Value != null; } - } - + public bool HasValue => Value != null; + /// /// Creates a flat clone of this Field. The fields value itself is not cloned. /// /// - public Field Clone() { - Field ret = new Field(FieldType, Scope); - ret.Value = Value; - return ret; + public Field Clone() + { + return new Field(FieldType, Scope) {Value = Value}; } - - public override int GetHashCode() { + + public override int GetHashCode() + { int hashCode = 0; - unchecked { + unchecked + { hashCode += 1000000009 * FieldType.GetHashCode(); if (Scope != null) hashCode += 1000000021 * Scope.GetHashCode(); } return hashCode; } - - public override bool Equals(object obj) { - Field other = obj as Field; - if (other == null) { + + public override bool Equals(object obj) + { + var other = obj as Field; + if (other == null) + { return false; } return FieldType == other.FieldType && Equals(Scope, other.Scope); } - - public override string ToString() { - return string.Format("[Field FieldType={1} Value={0} Scope={2}]", myValue, FieldType, Scope); - } - } - - - /// - /// EventHandler to be used when a field value changes - /// - public delegate void FieldChangedEventHandler(object sender, FieldChangedEventArgs e); - - /// - /// EventArgs to be used with FieldChangedEventHandler - /// - public class FieldChangedEventArgs : EventArgs { - public readonly Field Field; - public FieldChangedEventArgs(Field field) { - Field = field; + + public override string ToString() + { + return string.Format("[Field FieldType={1} Value={0} Scope={2}]", _myValue, FieldType, Scope); } } } diff --git a/Greenshot/Drawing/Fields/FieldAggregator.cs b/Greenshot/Drawing/Fields/FieldAggregator.cs index 1d9e8b6bf..cbf5377d7 100644 --- a/Greenshot/Drawing/Fields/FieldAggregator.cs +++ b/Greenshot/Drawing/Fields/FieldAggregator.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,15 +19,17 @@ * along with this program. If not, see . */ +using System; +using Greenshot.Configuration; +using Greenshot.IniFile; +using Greenshot.Plugin; +using Greenshot.Plugin.Drawing; +using GreenshotPlugin.Interfaces.Drawing; using System.Collections.Generic; using System.ComponentModel; -using Greenshot.Configuration; -using Greenshot.IniFile; -using Greenshot.Plugin.Drawing; -using log4net; - -namespace Greenshot.Drawing.Fields { +namespace Greenshot.Drawing.Fields +{ /// /// Represents the current set of properties for the editor. /// When one of EditorProperties' properties is updated, the change will be promoted @@ -39,150 +41,184 @@ namespace Greenshot.Drawing.Fields { /// Properties that do not apply for ALL selected elements are null (or 0 respectively) /// If the property values of the selected elements differ, the value of the last bound element wins. /// - public class FieldAggregator : AbstractFieldHolder { - - private List boundContainers; - private bool internalUpdateRunning = false; - - enum Status {IDLE, BINDING, UPDATING}; - - private static readonly ILog LOG = LogManager.GetLogger(typeof(FieldAggregator)); - private static EditorConfiguration editorConfiguration = IniConfig.GetIniSection(); + [Serializable] + public sealed class FieldAggregator : AbstractFieldHolder + { - public FieldAggregator() { - foreach(FieldType fieldType in FieldType.Values) { - Field field = new Field(fieldType, GetType()); + private readonly IDrawableContainerList _boundContainers; + private bool _internalUpdateRunning; + + private static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection(); + + public FieldAggregator(ISurface parent) + { + foreach (var fieldType in FieldType.Values) + { + var field = new Field(fieldType, GetType()); AddField(field); } - boundContainers = new List(); + _boundContainers = new DrawableContainerList + { + Parent = parent + }; } - - public override void AddField(Field field) { + + public override void AddField(IField field) + { base.AddField(field); field.PropertyChanged += OwnPropertyChanged; } - - public void BindElements(DrawableContainerList dcs) { - foreach(DrawableContainer dc in dcs) { + + public void BindElements(IDrawableContainerList dcs) + { + foreach (var dc in dcs) + { BindElement(dc); } } - public void BindElement(IDrawableContainer dc) { + public void BindElement(IDrawableContainer dc) + { DrawableContainer container = dc as DrawableContainer; - if (container != null && !boundContainers.Contains(container)) { - boundContainers.Add(container); - container.ChildrenChanged += delegate { - UpdateFromBoundElements(); - }; - UpdateFromBoundElements(); + if (container == null || _boundContainers.Contains(container)) + { + return; } + _boundContainers.Add(container); + container.ChildrenChanged += delegate { + UpdateFromBoundElements(); + }; + UpdateFromBoundElements(); } - - public void BindAndUpdateElement(IDrawableContainer dc) { + + public void BindAndUpdateElement(IDrawableContainer dc) + { UpdateElement(dc); BindElement(dc); } - - public void UpdateElement(IDrawableContainer dc) { + + public void UpdateElement(IDrawableContainer dc) + { DrawableContainer container = dc as DrawableContainer; - if (container == null) { + if (container == null) + { return; } - internalUpdateRunning = true; - foreach(Field field in GetFields()) { - if (container.HasField(field.FieldType) && field.HasValue) { + _internalUpdateRunning = true; + foreach (var field in GetFields()) + { + if (container.HasField(field.FieldType) && field.HasValue) + { //if(LOG.IsDebugEnabled) LOG.Debug(" "+field+ ": "+field.Value); container.SetFieldValue(field.FieldType, field.Value); } } - internalUpdateRunning = false; + _internalUpdateRunning = false; } - - public void UnbindElement(IDrawableContainer dc) { - if (boundContainers.Contains(dc)) { - boundContainers.Remove(dc); + + public void UnbindElement(IDrawableContainer dc) + { + if (_boundContainers.Contains(dc)) + { + _boundContainers.Remove(dc); UpdateFromBoundElements(); } } - - public void Clear() { + + public void Clear() + { ClearFields(); - boundContainers.Clear(); + _boundContainers.Clear(); UpdateFromBoundElements(); } - + /// /// sets all field values to null, however does not remove fields /// - private void ClearFields() { - internalUpdateRunning = true; - foreach(Field field in GetFields()) { + private void ClearFields() + { + _internalUpdateRunning = true; + foreach (var field in GetFields()) + { field.Value = null; } - internalUpdateRunning = false; + _internalUpdateRunning = false; } - + /// /// Updates this instance using the respective fields from the bound elements. /// Fields that do not apply to every bound element are set to null, or 0 respectively. /// All other fields will be set to the field value of the least bound element. /// - private void UpdateFromBoundElements() { + private void UpdateFromBoundElements() + { ClearFields(); - internalUpdateRunning = true; - foreach(Field field in FindCommonFields()) { + _internalUpdateRunning = true; + foreach (var field in FindCommonFields()) + { SetFieldValue(field.FieldType, field.Value); } - internalUpdateRunning = false; + _internalUpdateRunning = false; } - - private List FindCommonFields() { - List returnFields = null; - if (boundContainers.Count > 0) { + + private IList FindCommonFields() + { + IList returnFields = null; + if (_boundContainers.Count > 0) + { // take all fields from the least selected container... - DrawableContainer leastSelectedContainer = boundContainers[boundContainers.Count - 1] as DrawableContainer; - if (leastSelectedContainer != null) { + DrawableContainer leastSelectedContainer = _boundContainers[_boundContainers.Count - 1] as DrawableContainer; + if (leastSelectedContainer != null) + { returnFields = leastSelectedContainer.GetFields(); - for (int i = 0; i < boundContainers.Count - 1; i++) { - DrawableContainer dc = boundContainers[i] as DrawableContainer; - if (dc != null) { - List fieldsToRemove = new List(); - foreach (Field f in returnFields) { + for (int i = 0; i < _boundContainers.Count - 1; i++) + { + DrawableContainer dc = _boundContainers[i] as DrawableContainer; + if (dc != null) + { + IList fieldsToRemove = new List(); + foreach (IField field in returnFields) + { // ... throw out those that do not apply to one of the other containers - if (!dc.HasField(f.FieldType)) { - fieldsToRemove.Add(f); + if (!dc.HasField(field.FieldType)) + { + fieldsToRemove.Add(field); } } - foreach (Field f in fieldsToRemove) { - returnFields.Remove(f); + foreach (var field in fieldsToRemove) + { + returnFields.Remove(field); } } } } } - if (returnFields == null) { - returnFields = new List(); - } - return returnFields; + return returnFields ?? new List(); } - - public void OwnPropertyChanged(object sender, PropertyChangedEventArgs ea) { - Field field = (Field) sender; - if (!internalUpdateRunning && field.Value != null) { - foreach(DrawableContainer drawableContainer in boundContainers) { - if (drawableContainer.HasField(field.FieldType)) { - Field drawableContainerField = drawableContainer.GetField(field.FieldType); - // Notify before change, so we can e.g. invalidate the area - drawableContainer.BeforeFieldChange(drawableContainerField, field.Value); - drawableContainerField.Value = field.Value; - // update last used from DC field, so that scope is honored - editorConfiguration.UpdateLastFieldValue(drawableContainerField); - } + public void OwnPropertyChanged(object sender, PropertyChangedEventArgs ea) + { + IField field = (IField)sender; + if (_internalUpdateRunning || field.Value == null) + { + return; + } + foreach (var drawableContainer1 in _boundContainers) + { + var drawableContainer = (DrawableContainer) drawableContainer1; + if (!drawableContainer.HasField(field.FieldType)) + { + continue; } + IField drawableContainerField = drawableContainer.GetField(field.FieldType); + // Notify before change, so we can e.g. invalidate the area + drawableContainer.BeforeFieldChange(drawableContainerField, field.Value); + + drawableContainerField.Value = field.Value; + // update last used from DC field, so that scope is honored + EditorConfig.UpdateLastFieldValue(drawableContainerField); } } - } + } } diff --git a/Greenshot/Drawing/Fields/FieldType.cs b/Greenshot/Drawing/Fields/FieldType.cs index 4469f86cf..d99af3759 100644 --- a/Greenshot/Drawing/Fields/FieldType.cs +++ b/Greenshot/Drawing/Fields/FieldType.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,38 +18,41 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +using GreenshotPlugin.Interfaces.Drawing; using System; -namespace Greenshot.Drawing.Fields { +namespace Greenshot.Drawing.Fields +{ /// /// Defines all FieldTypes + their default value. /// (The additional value is why this is not an enum) /// [Serializable] - public class FieldType { + public class FieldType : IFieldType + { + + public static readonly IFieldType ARROWHEADS = new FieldType("ARROWHEADS"); + public static readonly IFieldType BLUR_RADIUS = new FieldType("BLUR_RADIUS"); + public static readonly IFieldType BRIGHTNESS = new FieldType("BRIGHTNESS"); + public static readonly IFieldType FILL_COLOR = new FieldType("FILL_COLOR"); + public static readonly IFieldType FONT_BOLD = new FieldType("FONT_BOLD"); + public static readonly IFieldType FONT_FAMILY = new FieldType("FONT_FAMILY"); + public static readonly IFieldType FONT_ITALIC = new FieldType("FONT_ITALIC"); + public static readonly IFieldType FONT_SIZE = new FieldType("FONT_SIZE"); + public static readonly IFieldType TEXT_HORIZONTAL_ALIGNMENT = new FieldType("TEXT_HORIZONTAL_ALIGNMENT"); + public static readonly IFieldType TEXT_VERTICAL_ALIGNMENT = new FieldType("TEXT_VERTICAL_ALIGNMENT"); + public static readonly IFieldType HIGHLIGHT_COLOR = new FieldType("HIGHLIGHT_COLOR"); + public static readonly IFieldType LINE_COLOR = new FieldType("LINE_COLOR"); + public static readonly IFieldType LINE_THICKNESS = new FieldType("LINE_THICKNESS"); + public static readonly IFieldType MAGNIFICATION_FACTOR = new FieldType("MAGNIFICATION_FACTOR"); + public static readonly IFieldType PIXEL_SIZE = new FieldType("PIXEL_SIZE"); + public static readonly IFieldType PREVIEW_QUALITY = new FieldType("PREVIEW_QUALITY"); + public static readonly IFieldType SHADOW = new FieldType("SHADOW"); + public static readonly IFieldType PREPARED_FILTER_OBFUSCATE = new FieldType("PREPARED_FILTER_OBFUSCATE"); + public static readonly IFieldType PREPARED_FILTER_HIGHLIGHT = new FieldType("PREPARED_FILTER_HIGHLIGHT"); + public static readonly IFieldType FLAGS = new FieldType("FLAGS"); - public static readonly FieldType ARROWHEADS = new FieldType("ARROWHEADS"); - public static readonly FieldType BLUR_RADIUS = new FieldType("BLUR_RADIUS"); - public static readonly FieldType BRIGHTNESS = new FieldType("BRIGHTNESS"); - public static readonly FieldType FILL_COLOR = new FieldType("FILL_COLOR"); - public static readonly FieldType FONT_BOLD = new FieldType("FONT_BOLD"); - public static readonly FieldType FONT_FAMILY = new FieldType("FONT_FAMILY"); - public static readonly FieldType FONT_ITALIC = new FieldType("FONT_ITALIC"); - public static readonly FieldType FONT_SIZE = new FieldType("FONT_SIZE"); - public static readonly FieldType TEXT_HORIZONTAL_ALIGNMENT = new FieldType("TEXT_HORIZONTAL_ALIGNMENT"); - public static readonly FieldType TEXT_VERTICAL_ALIGNMENT = new FieldType("TEXT_VERTICAL_ALIGNMENT"); - public static readonly FieldType HIGHLIGHT_COLOR = new FieldType("HIGHLIGHT_COLOR"); - public static readonly FieldType LINE_COLOR = new FieldType("LINE_COLOR"); - public static readonly FieldType LINE_THICKNESS = new FieldType("LINE_THICKNESS"); - public static readonly FieldType MAGNIFICATION_FACTOR = new FieldType("MAGNIFICATION_FACTOR"); - public static readonly FieldType PIXEL_SIZE = new FieldType("PIXEL_SIZE"); - public static readonly FieldType PREVIEW_QUALITY = new FieldType("PREVIEW_QUALITY"); - public static readonly FieldType SHADOW = new FieldType("SHADOW"); - public static readonly FieldType PREPARED_FILTER_OBFUSCATE = new FieldType("PREPARED_FILTER_OBFUSCATE"); - public static readonly FieldType PREPARED_FILTER_HIGHLIGHT = new FieldType("PREPARED_FILTER_HIGHLIGHT"); - public static readonly FieldType FLAGS = new FieldType("FLAGS"); - - public static FieldType[] Values = new FieldType[]{ + public static IFieldType[] Values = { ARROWHEADS, BLUR_RADIUS, BRIGHTNESS, @@ -66,53 +69,55 @@ namespace Greenshot.Drawing.Fields { MAGNIFICATION_FACTOR, PIXEL_SIZE, PREVIEW_QUALITY, - SHADOW, + SHADOW, PREPARED_FILTER_OBFUSCATE, - PREPARED_FILTER_HIGHLIGHT, + PREPARED_FILTER_HIGHLIGHT, FLAGS }; - - [Flags] - public enum Flag { - NONE = 0, - CONFIRMABLE = 1 + + public string Name + { + get; + set; } - - - public string Name; - private FieldType(string name) { + + private FieldType(string name) + { Name = name; } - public override string ToString() { + public override string ToString() + { return Name; } public override int GetHashCode() { int hashCode = 0; - unchecked { + unchecked + { if (Name != null) hashCode += 1000000009 * Name.GetHashCode(); } return hashCode; } - + public override bool Equals(object obj) { FieldType other = obj as FieldType; if (other == null) + { return false; - return Equals(Name,other.Name); + } + return Equals(Name, other.Name); } - - public static bool operator ==(FieldType a, FieldType b) { - return Equals(a,b); + + public static bool operator ==(FieldType a, FieldType b) + { + return Equals(a, b); } - - public static bool operator !=(FieldType a, FieldType b) { - return !Equals(a,b); + + public static bool operator !=(FieldType a, FieldType b) + { + return !Equals(a, b); } - } - - } diff --git a/Greenshot/Drawing/Fields/IFieldHolder.cs b/Greenshot/Drawing/Fields/IFieldHolder.cs index 1fd2952f3..063ca48d7 100644 --- a/Greenshot/Drawing/Fields/IFieldHolder.cs +++ b/Greenshot/Drawing/Fields/IFieldHolder.cs @@ -3,7 +3,7 @@ * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Drawing/FilterContainer.cs b/Greenshot/Drawing/FilterContainer.cs index 630c5c35d..b69af0a53 100644 --- a/Greenshot/Drawing/FilterContainer.cs +++ b/Greenshot/Drawing/FilterContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ using Greenshot.Drawing.Fields; using Greenshot.Helpers; using Greenshot.Plugin.Drawing; using System.Drawing.Drawing2D; +using System.Runtime.Serialization; namespace Greenshot.Drawing { /// @@ -40,6 +41,18 @@ namespace Greenshot.Drawing { } public FilterContainer(Surface parent) : base(parent) { + Init(); + } + + protected override void OnDeserialized(StreamingContext streamingContext) + { + base.OnDeserialized(streamingContext); + Init(); + } + + private void Init() + { + CreateDefaultAdorners(); } protected override void InitializeFields() { @@ -52,7 +65,7 @@ namespace Greenshot.Drawing { int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - bool lineVisible = (lineThickness > 0 && Colors.IsVisible(lineColor)); + bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor); if (lineVisible) { graphics.SmoothingMode = SmoothingMode.HighSpeed; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; @@ -69,7 +82,7 @@ namespace Greenshot.Drawing { Rectangle shadowRect = GuiRectangle.GetGuiRectangle(Left + currentStep, Top + currentStep, Width, Height); graphics.DrawRectangle(shadowPen, shadowRect); currentStep++; - alpha = alpha - (basealpha / steps); + alpha = alpha - basealpha / steps; } } } diff --git a/Greenshot/Drawing/Filters/AbstractFilter.cs b/Greenshot/Drawing/Filters/AbstractFilter.cs index cd1be85a2..d9e8806ac 100644 --- a/Greenshot/Drawing/Filters/AbstractFilter.cs +++ b/Greenshot/Drawing/Filters/AbstractFilter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,13 +25,13 @@ using System.Drawing; using Greenshot.Drawing.Fields; using Greenshot.Plugin.Drawing; -/// -/// Graphical filter which can be added to DrawableContainer. -/// Subclasses should fulfill INotifyPropertyChanged contract, i.e. call -/// OnPropertyChanged whenever a public property has been changed. -/// namespace Greenshot.Drawing.Filters { - [Serializable()] + /// + /// Graphical filter which can be added to DrawableContainer. + /// Subclasses should fulfill INotifyPropertyChanged contract, i.e. call + /// OnPropertyChanged whenever a public property has been changed. + /// + [Serializable] public abstract class AbstractFilter : AbstractFieldHolder, IFilter { [NonSerialized] @@ -41,7 +41,7 @@ namespace Greenshot.Drawing.Filters { remove{ propertyChanged -= value; } } - private bool invert = false; + private bool invert; public bool Invert { get { return invert; @@ -72,10 +72,9 @@ namespace Greenshot.Drawing.Filters { public abstract void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode); - protected void OnPropertyChanged(string propertyName) { - if (propertyChanged != null) { - propertyChanged(this, new PropertyChangedEventArgs(propertyName)); - } + protected void OnPropertyChanged(string propertyName) + { + propertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } diff --git a/Greenshot/Drawing/Filters/BlurFilter.cs b/Greenshot/Drawing/Filters/BlurFilter.cs index aca8ae47d..f9b2c843c 100644 --- a/Greenshot/Drawing/Filters/BlurFilter.cs +++ b/Greenshot/Drawing/Filters/BlurFilter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +18,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 Greenshot.Drawing.Fields; diff --git a/Greenshot/Drawing/Filters/BrightnessFilter.cs b/Greenshot/Drawing/Filters/BrightnessFilter.cs index f7d689d52..b5154f783 100644 --- a/Greenshot/Drawing/Filters/BrightnessFilter.cs +++ b/Greenshot/Drawing/Filters/BrightnessFilter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Drawing/Filters/GrayscaleFilter.cs b/Greenshot/Drawing/Filters/GrayscaleFilter.cs index a6d0ac83d..c6318dc22 100644 --- a/Greenshot/Drawing/Filters/GrayscaleFilter.cs +++ b/Greenshot/Drawing/Filters/GrayscaleFilter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Drawing/Filters/HighlightFilter.cs b/Greenshot/Drawing/Filters/HighlightFilter.cs index 896bbff5c..41248b01f 100644 --- a/Greenshot/Drawing/Filters/HighlightFilter.cs +++ b/Greenshot/Drawing/Filters/HighlightFilter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Drawing/Filters/IFilter.cs b/Greenshot/Drawing/Filters/IFilter.cs index 5840e9650..74895d582 100644 --- a/Greenshot/Drawing/Filters/IFilter.cs +++ b/Greenshot/Drawing/Filters/IFilter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,11 +21,11 @@ using System.ComponentModel; using System.Drawing; - -using Greenshot.Drawing.Fields; using Greenshot.Plugin.Drawing; +using GreenshotPlugin.Interfaces.Drawing; -namespace Greenshot.Drawing.Filters { +namespace Greenshot.Drawing.Filters +{ public interface IFilter : INotifyPropertyChanged, IFieldHolder { DrawableContainer Parent {get; set; } void Apply(Graphics graphics, Bitmap bmp, Rectangle rect, RenderMode renderMode); diff --git a/Greenshot/Drawing/Filters/MagnifierFilter.cs b/Greenshot/Drawing/Filters/MagnifierFilter.cs index 23359546e..e0b69c263 100644 --- a/Greenshot/Drawing/Filters/MagnifierFilter.cs +++ b/Greenshot/Drawing/Filters/MagnifierFilter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -53,7 +53,7 @@ namespace Greenshot.Drawing.Filters { int halfHeight = rect.Height / 2; int newWidth = rect.Width / magnificationFactor; int newHeight = rect.Height / magnificationFactor; - Rectangle source = new Rectangle(rect.X + halfWidth - (newWidth / 2), rect.Y + halfHeight - (newHeight / 2), newWidth, newHeight); + Rectangle source = new Rectangle(rect.X + halfWidth - newWidth / 2, rect.Y + halfHeight - newHeight / 2, newWidth, newHeight); graphics.DrawImage(applyBitmap, rect, source, GraphicsUnit.Pixel); graphics.Restore(state); } diff --git a/Greenshot/Drawing/Filters/PixelizationFilter.cs b/Greenshot/Drawing/Filters/PixelizationFilter.cs index a7f13c096..5e4727af8 100644 --- a/Greenshot/Drawing/Filters/PixelizationFilter.cs +++ b/Greenshot/Drawing/Filters/PixelizationFilter.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,7 +37,7 @@ namespace Greenshot.Drawing.Filters { public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode) { int pixelSize = GetFieldValueAsInt(FieldType.PIXEL_SIZE); - Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert); + ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert); if (pixelSize <= 1 || rect.Width == 0 || rect.Height == 0) { // Nothing to do return; diff --git a/Greenshot/Drawing/FreehandContainer.cs b/Greenshot/Drawing/FreehandContainer.cs index b30937c2b..e8654bc4e 100644 --- a/Greenshot/Drawing/FreehandContainer.cs +++ b/Greenshot/Drawing/FreehandContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,7 +22,6 @@ using Greenshot.Drawing.Fields; using Greenshot.Helpers; using Greenshot.Plugin.Drawing; -using log4net; using System; using System.Collections.Generic; using System.Drawing; @@ -35,21 +34,19 @@ namespace Greenshot.Drawing { /// [Serializable] public class FreehandContainer : DrawableContainer { - private static readonly ILog LOG = LogManager.GetLogger(typeof(FreehandContainer)); - private static readonly float [] POINT_OFFSET = new float[]{0.5f, 0.25f, 0.75f}; + private static readonly float [] PointOffset = {0.5f, 0.25f, 0.75f}; [NonSerialized] private GraphicsPath freehandPath = new GraphicsPath(); private Rectangle myBounds = Rectangle.Empty; private Point lastMouse = Point.Empty; - private List capturePoints = new List(); - private bool isRecalculated = false; + private readonly List capturePoints = new List(); + private bool isRecalculated; /// /// Constructor /// public FreehandContainer(Surface parent) : base(parent) { - Init(); Width = parent.Width; Height = parent.Height; Top = 0; @@ -61,16 +58,6 @@ namespace Greenshot.Drawing { AddField(GetType(), FieldType.LINE_COLOR, Color.Red); } - - protected void Init() { - if (_grippers != null) { - for (int i = 0; i < _grippers.Length; i++) { - _grippers[i].Enabled = false; - _grippers[i].Visible = false; - } - } - } - public override void Transform(Matrix matrix) { Point[] points = capturePoints.ToArray(); @@ -80,11 +67,7 @@ namespace Greenshot.Drawing { RecalculatePath(); } - [OnDeserialized] - private void OnDeserialized(StreamingContext context) { - InitGrippers(); - DoLayout(); - Init(); + protected override void OnDeserialized(StreamingContext context) { RecalculatePath(); } @@ -94,10 +77,9 @@ namespace Greenshot.Drawing { /// When disposing==true all non-managed resources should be freed too! protected override void Dispose(bool disposing) { base.Dispose(disposing); - if (disposing) { - if (freehandPath != null) { - freehandPath.Dispose(); - } + if (disposing) + { + freehandPath?.Dispose(); } freehandPath = null; } @@ -119,7 +101,7 @@ namespace Greenshot.Drawing { public override bool HandleMouseMove(int mouseX, int mouseY) { Point previousPoint = capturePoints[capturePoints.Count-1]; - if (GeometryHelper.Distance2D(previousPoint.X, previousPoint.Y, mouseX, mouseY) >= (2*EditorConfig.FreehandSensitivity)) { + if (GeometryHelper.Distance2D(previousPoint.X, previousPoint.Y, mouseX, mouseY) >= 2*EditorConfig.FreehandSensitivity) { capturePoints.Add(new Point(mouseX, mouseY)); } if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) >= EditorConfig.FreehandSensitivity) { @@ -150,9 +132,7 @@ namespace Greenshot.Drawing { private void RecalculatePath() { isRecalculated = true; // Dispose the previous path, if we have one - if (freehandPath != null) { - freehandPath.Dispose(); - } + freehandPath?.Dispose(); freehandPath = new GraphicsPath(); // Here we can put some cleanup... like losing all the uninteresting points. @@ -160,7 +140,7 @@ namespace Greenshot.Drawing { int index = 0; while ((capturePoints.Count - 1) % 3 != 0) { // duplicate points, first at 50% than 25% than 75% - capturePoints.Insert((int)(capturePoints.Count*POINT_OFFSET[index]), capturePoints[(int)(capturePoints.Count*POINT_OFFSET[index++])]); + capturePoints.Insert((int)(capturePoints.Count*PointOffset[index]), capturePoints[(int)(capturePoints.Count*PointOffset[index++])]); } freehandPath.AddBeziers(capturePoints.ToArray()); } else if (capturePoints.Count == 2) { @@ -232,9 +212,9 @@ namespace Greenshot.Drawing { if (!myBounds.IsEmpty) { int lineThickness = Math.Max(10, GetFieldValueAsInt(FieldType.LINE_THICKNESS)); int safetymargin = 10; - return new Rectangle((myBounds.Left + Left) - (safetymargin+lineThickness), (myBounds.Top + Top) - (safetymargin+lineThickness), myBounds.Width + (2*(lineThickness+safetymargin)), myBounds.Height + (2*(lineThickness+safetymargin))); + return new Rectangle(myBounds.Left + Left - (safetymargin+lineThickness), myBounds.Top + Top - (safetymargin+lineThickness), myBounds.Width + 2*(lineThickness+safetymargin), myBounds.Height + 2*(lineThickness+safetymargin)); } - return new Rectangle(0, 0, _parent.Width, _parent.Height); + return new Rectangle(0, 0, _parent?.Width??0, _parent?.Height?? 0); } } @@ -245,9 +225,9 @@ namespace Greenshot.Drawing { /// public override bool Equals(object obj) { bool ret = false; - if(obj != null && GetType().Equals(obj.GetType())) { + if(obj != null && GetType() == obj.GetType()) { FreehandContainer other = obj as FreehandContainer; - if(freehandPath.Equals(other.freehandPath)) { + if(other != null && freehandPath.Equals(other.freehandPath)) { ret = true; } } @@ -258,17 +238,6 @@ namespace Greenshot.Drawing { return freehandPath.GetHashCode(); } - /// - /// This is overriden to prevent the grippers to be modified. - /// Might not be the best way... - /// - protected override void DoLayout() { - } - - public override void ShowGrippers() { - ResumeLayout(); - } - public override bool ClickableAt(int x, int y) { bool returnValue = base.ClickableAt(x, y); if (returnValue) { diff --git a/Greenshot/Drawing/Gripper.cs b/Greenshot/Drawing/Gripper.cs deleted file mode 100644 index 7a65fc57a..000000000 --- a/Greenshot/Drawing/Gripper.cs +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom - * - * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ - * - * This program 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 1 of the License, or - * (at your option) any later version. - * - * This program 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 . - */ - -using System.Drawing; -using System.Windows.Forms; - -namespace Greenshot.Drawing { - /// - /// Grippers are the dragable edges of our containers - /// - public class Gripper : Label { - /// - /// Constants for anchor/gripper position: - /// 0 1 2 - /// 7 3 - /// 6 5 4 - /// - public const int POSITION_TOP_LEFT = 0; - public const int POSITION_TOP_CENTER = 1; - public const int POSITION_TOP_RIGHT = 2; - public const int POSITION_MIDDLE_RIGHT = 3; - public const int POSITION_BOTTOM_RIGHT = 4; - public const int POSITION_BOTTOM_CENTER = 5; - public const int POSITION_BOTTOM_LEFT = 6; - public const int POSITION_MIDDLE_LEFT = 7; - - public int Position { - get; - set; - } - - public Gripper() { - Width = 5; - Height = 5; - BackColor = Color.Black; - } - } -} diff --git a/Greenshot/Drawing/HighlightContainer.cs b/Greenshot/Drawing/HighlightContainer.cs index aec48208f..82a352469 100644 --- a/Greenshot/Drawing/HighlightContainer.cs +++ b/Greenshot/Drawing/HighlightContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,11 +19,11 @@ * along with this program. If not, see . */ using System; -using System.Drawing; using System.Runtime.Serialization; using Greenshot.Drawing.Fields; using Greenshot.Drawing.Filters; +using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { /// @@ -43,8 +43,8 @@ namespace Greenshot.Drawing { AddField(GetType(), FieldType.PREPARED_FILTER_HIGHLIGHT, PreparedFilter.TEXT_HIGHTLIGHT); } - [OnDeserialized] - private void OnDeserialized(StreamingContext context) { + protected override void OnDeserialized(StreamingContext context) + { Init(); } @@ -57,7 +57,7 @@ namespace Greenshot.Drawing { if (!sender.Equals(this)) { return; } - if (e.Field.FieldType == FieldType.PREPARED_FILTER_HIGHLIGHT) { + if (Equals(e.Field.FieldType, FieldType.PREPARED_FILTER_HIGHLIGHT)) { ConfigurePreparedFilters(); } } @@ -72,12 +72,16 @@ namespace Greenshot.Drawing { Add(new HighlightFilter(this)); break; case PreparedFilter.AREA_HIGHLIGHT: - AbstractFilter bf = new BrightnessFilter(this); - bf.Invert = true; - Add(bf); - bf = new BlurFilter(this); - bf.Invert = true; - Add(bf); + var brightnessFilter = new BrightnessFilter(this) + { + Invert = true + }; + Add(brightnessFilter); + var blurFilter = new BlurFilter(this) + { + Invert = true + }; + Add(blurFilter); break; case PreparedFilter.GRAYSCALE: AbstractFilter f = new GrayscaleFilter(this); diff --git a/Greenshot/Drawing/IconContainer.cs b/Greenshot/Drawing/IconContainer.cs index 86b82a46f..2277bd48a 100644 --- a/Greenshot/Drawing/IconContainer.cs +++ b/Greenshot/Drawing/IconContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,6 +24,7 @@ using System.IO; using Greenshot.Plugin.Drawing; using System.Drawing.Drawing2D; using log4net; +using System.Runtime.Serialization; namespace Greenshot.Drawing { /// @@ -31,11 +32,23 @@ namespace Greenshot.Drawing { /// [Serializable] public class IconContainer : DrawableContainer, IIconContainer { - private static ILog LOG = LogManager.GetLogger(typeof(IconContainer)); + private static readonly ILog Log = LogManager.GetLogger(typeof(IconContainer)); protected Icon icon; public IconContainer(Surface parent) : base(parent) { + Init(); + } + + protected override void OnDeserialized(StreamingContext streamingContext) + { + base.OnDeserialized(streamingContext); + Init(); + } + + private void Init() + { + CreateDefaultAdorners(); } public IconContainer(Surface parent, string filename) : base(parent) { @@ -44,9 +57,7 @@ namespace Greenshot.Drawing { public Icon Icon { set { - if (icon != null) { - icon.Dispose(); - } + icon?.Dispose(); icon = (Icon)value.Clone(); Width = value.Width; Height = value.Height; @@ -59,10 +70,9 @@ namespace Greenshot.Drawing { * When disposing==true all non-managed resources should be freed too! */ protected override void Dispose(bool disposing) { - if (disposing) { - if (icon != null) { - icon.Dispose(); - } + if (disposing) + { + icon?.Dispose(); } icon = null; base.Dispose(disposing); @@ -72,7 +82,7 @@ namespace Greenshot.Drawing { if (File.Exists(filename)) { using (Icon fileIcon = new Icon(filename)) { Icon = fileIcon; - LOG.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width); + Log.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width); } } } @@ -87,16 +97,8 @@ namespace Greenshot.Drawing { } } - public override bool HasDefaultSize { - get { - return true; - } - } + public override bool HasDefaultSize => true; - public override Size DefaultSize { - get { - return icon.Size; - } - } + public override Size DefaultSize => icon.Size; } } diff --git a/Greenshot/Drawing/ImageContainer.cs b/Greenshot/Drawing/ImageContainer.cs index b9f9c6dc3..ab8d4e541 100644 --- a/Greenshot/Drawing/ImageContainer.cs +++ b/Greenshot/Drawing/ImageContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,8 +25,10 @@ using Greenshot.Drawing.Fields; using Greenshot.Plugin.Drawing; using GreenshotPlugin.Core; using System.Drawing.Drawing2D; -using Greenshot.Core; using log4net; +using System.Runtime.Serialization; +using GreenshotPlugin.Effects; +using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { /// @@ -34,7 +36,7 @@ namespace Greenshot.Drawing { /// [Serializable] public class ImageContainer : DrawableContainer, IImageContainer { - private static ILog LOG = LogManager.GetLogger(typeof(ImageContainer)); + private static readonly ILog Log = LogManager.GetLogger(typeof(ImageContainer)); private Image image; @@ -58,6 +60,18 @@ namespace Greenshot.Drawing { public ImageContainer(Surface parent) : base(parent) { FieldChanged += BitmapContainer_OnFieldChanged; + Init(); + } + + protected override void OnDeserialized(StreamingContext streamingContext) + { + base.OnDeserialized(streamingContext); + Init(); + } + + private void Init() + { + CreateDefaultAdorners(); } protected override void InitializeFields() { @@ -66,7 +80,7 @@ namespace Greenshot.Drawing { protected void BitmapContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) { if (sender.Equals(this)) { - if (e.Field.FieldType == FieldType.SHADOW) { + if (FieldType.SHADOW.Equals(e.Field.FieldType)) { ChangeShadowField(); } } @@ -126,15 +140,11 @@ namespace Greenshot.Drawing { } private void DisposeImage() { - if (image != null) { - image.Dispose(); - } + image?.Dispose(); image = null; } private void DisposeShadow() { - if (_shadowBitmap != null) { - _shadowBitmap.Dispose(); - } + _shadowBitmap?.Dispose(); _shadowBitmap = null; } @@ -148,10 +158,11 @@ namespace Greenshot.Drawing { int rotateAngle = CalculateAngle(matrix); // we currently assume only one transformation has been made. if (rotateAngle != 0) { - LOG.DebugFormat("Rotating element with {0} degrees.", rotateAngle); + Log.DebugFormat("Rotating element with {0} degrees.", rotateAngle); DisposeShadow(); using (var tmpMatrix = new Matrix()) { - using (Image tmpImage = image) { + using (image) + { image = ImageHelper.ApplyEffect(image, new RotateEffect(rotateAngle), tmpMatrix); } } @@ -164,14 +175,16 @@ namespace Greenshot.Drawing { /// /// public void Load(string filename) { - if (File.Exists(filename)) { - // Always make sure ImageHelper.LoadBitmap results are disposed some time, - // as we close the bitmap internally, we need to do it afterwards - using (Image tmpImage = ImageHelper.LoadImage(filename)) { - Image = tmpImage; - } - LOG.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width); + if (!File.Exists(filename)) + { + return; } + // Always make sure ImageHelper.LoadBitmap results are disposed some time, + // as we close the bitmap internally, we need to do it afterwards + using (var tmpImage = ImageHelper.LoadImage(filename)) { + Image = tmpImage; + } + Log.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width); } /// @@ -208,16 +221,8 @@ namespace Greenshot.Drawing { } } - public override bool HasDefaultSize { - get { - return true; - } - } + public override bool HasDefaultSize => true; - public override Size DefaultSize { - get { - return image.Size; - } - } + public override Size DefaultSize => image.Size; } } diff --git a/Greenshot/Drawing/LineContainer.cs b/Greenshot/Drawing/LineContainer.cs index 4189134ac..c443f64fc 100644 --- a/Greenshot/Drawing/LineContainer.cs +++ b/Greenshot/Drawing/LineContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ using System.Runtime.Serialization; using Greenshot.Drawing.Fields; using Greenshot.Helpers; using Greenshot.Plugin.Drawing; +using Greenshot.Drawing.Adorners; namespace Greenshot.Drawing { /// @@ -45,19 +46,14 @@ namespace Greenshot.Drawing { AddField(GetType(), FieldType.SHADOW, true); } - [OnDeserialized()] - private void OnDeserialized(StreamingContext context) { - InitGrippers(); - DoLayout(); + protected override void OnDeserialized(StreamingContext context) + { Init(); } protected void Init() { - if (_grippers != null) { - foreach (int index in new[] { 1, 2, 3, 5, 6, 7 }) { - _grippers[index].Enabled = false; - } - } + Adorners.Add(new MoveAdorner(this, Positions.TopLeft)); + Adorners.Add(new MoveAdorner(this, Positions.BottomRight)); } public override void Draw(Graphics graphics, RenderMode rm) { @@ -86,7 +82,7 @@ namespace Greenshot.Drawing { Top + currentStep + Height); currentStep++; - alpha = alpha - (basealpha / steps); + alpha = alpha - basealpha / steps; } } } @@ -113,8 +109,6 @@ namespace Greenshot.Drawing { protected override ScaleHelper.IDoubleProcessor GetAngleRoundProcessor() { return ScaleHelper.LineAngleRoundBehavior.Instance; - } - - + } } } diff --git a/Greenshot/Drawing/ObfuscateContainer.cs b/Greenshot/Drawing/ObfuscateContainer.cs index 80f395c31..ec3b0d734 100644 --- a/Greenshot/Drawing/ObfuscateContainer.cs +++ b/Greenshot/Drawing/ObfuscateContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ using System; using System.Runtime.Serialization; using Greenshot.Drawing.Fields; using Greenshot.Drawing.Filters; +using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { /// @@ -37,20 +38,21 @@ namespace Greenshot.Drawing { base.InitializeFields(); AddField(GetType(), FieldType.PREPARED_FILTER_OBFUSCATE, PreparedFilter.PIXELIZE); } - - [OnDeserialized] - private void OnDeserialized(StreamingContext context) { + + protected override void OnDeserialized(StreamingContext context) + { Init(); } private void Init() { FieldChanged += ObfuscateContainer_OnFieldChanged; ConfigurePreparedFilters(); + CreateDefaultAdorners(); } protected void ObfuscateContainer_OnFieldChanged(object sender, FieldChangedEventArgs e) { if(sender.Equals(this)) { - if(e.Field.FieldType == FieldType.PREPARED_FILTER_OBFUSCATE) { + if(Equals(e.Field.FieldType, FieldType.PREPARED_FILTER_OBFUSCATE)) { ConfigurePreparedFilters(); } } diff --git a/PluginExample/ExampleForm.cs b/Greenshot/Drawing/Positions.cs similarity index 71% rename from PluginExample/ExampleForm.cs rename to Greenshot/Drawing/Positions.cs index 144f36a4b..8ed2611bf 100644 --- a/PluginExample/ExampleForm.cs +++ b/Greenshot/Drawing/Positions.cs @@ -1,6 +1,6 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2014 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ @@ -18,12 +18,21 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -using System; -using System.Collections.Generic; -using System.Text; -using GreenshotPlugin.Controls; -namespace PluginExample { - public class ExampleForm : GreenshotForm{ +namespace Greenshot.Drawing +{ + /// + /// Position + /// + public enum Positions : int + { + TopLeft = 0, + TopCenter = 1, + TopRight = 2, + MiddleRight = 3, + BottomRight = 4, + BottomCenter = 5, + BottomLeft = 6, + MiddleLeft = 7 } } diff --git a/Greenshot/Drawing/RectangleContainer.cs b/Greenshot/Drawing/RectangleContainer.cs index c235346c5..d7e2cb37e 100644 --- a/Greenshot/Drawing/RectangleContainer.cs +++ b/Greenshot/Drawing/RectangleContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ using System.Drawing.Drawing2D; using Greenshot.Drawing.Fields; using Greenshot.Helpers; using Greenshot.Plugin.Drawing; +using System.Runtime.Serialization; namespace Greenshot.Drawing { /// @@ -34,6 +35,22 @@ namespace Greenshot.Drawing { public class RectangleContainer : DrawableContainer { public RectangleContainer(Surface parent) : base(parent) { + Init(); + } + + /// + /// Do some logic to make sure all field are initiated correctly + /// + /// StreamingContext + protected override void OnDeserialized(StreamingContext streamingContext) + { + base.OnDeserialized(streamingContext); + Init(); + } + + private void Init() + { + CreateDefaultAdorners(); } protected override void InitializeFields() { @@ -69,7 +86,7 @@ namespace Greenshot.Drawing { graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.PixelOffsetMode = PixelOffsetMode.None; - bool lineVisible = (lineThickness > 0 && Colors.IsVisible(lineColor)); + bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor); if (shadow && (lineVisible || Colors.IsVisible(fillColor))) { //draw shadow first int basealpha = 100; @@ -86,7 +103,7 @@ namespace Greenshot.Drawing { rect.Height); graphics.DrawRectangle(shadowPen, shadowRect); currentStep++; - alpha = alpha - (basealpha / steps); + alpha = alpha - basealpha / steps; } } } diff --git a/Greenshot/Drawing/RoundedRectangle.cs b/Greenshot/Drawing/RoundedRectangle.cs index 51ea777ff..54553ac37 100644 --- a/Greenshot/Drawing/RoundedRectangle.cs +++ b/Greenshot/Drawing/RoundedRectangle.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,7 @@ * along with this program. If not, see . */ +using System; using System.Drawing; using System.Drawing.Drawing2D; @@ -27,6 +28,7 @@ namespace Greenshot.Drawing { /// TODO: currently this is only used in the capture form, we might move this code directly to there! /// public abstract class RoundedRectangle { + [Flags] public enum RectangleCorners { None = 0, TopLeft = 1, TopRight = 2, BottomLeft = 4, BottomRight = 8, @@ -35,13 +37,13 @@ namespace Greenshot.Drawing { public static GraphicsPath Create2(int x, int y, int width, int height, int radius) { GraphicsPath gp = new GraphicsPath(); - gp.AddLine(x + radius, y, x + width - (radius * 2), y); // Line - gp.AddArc(x + width - (radius * 2), y, radius * 2, radius * 2, 270, 90); // Corner - gp.AddLine(x + width, y + radius, x + width, y + height - (radius * 2)); // Line - gp.AddArc(x + width - (radius * 2), y + height - (radius * 2), radius * 2, radius * 2, 0, 90); // Corner - gp.AddLine(x + width - (radius * 2), y + height, x + radius, y + height); // Line - gp.AddArc(x, y + height - (radius * 2), radius * 2, radius * 2, 90, 90); // Corner - gp.AddLine(x, y + height - (radius * 2), x, y + radius); // Line + gp.AddLine(x + radius, y, x + width - radius * 2, y); // Line + gp.AddArc(x + width - radius * 2, y, radius * 2, radius * 2, 270, 90); // Corner + gp.AddLine(x + width, y + radius, x + width, y + height - radius * 2); // Line + gp.AddArc(x + width - radius * 2, y + height - radius * 2, radius * 2, radius * 2, 0, 90); // Corner + gp.AddLine(x + width - radius * 2, y + height, x + radius, y + height); // Line + gp.AddArc(x, y + height - radius * 2, radius * 2, radius * 2, 90, 90); // Corner + gp.AddLine(x, y + height - radius * 2, x, y + radius); // Line gp.AddArc(x, y, radius * 2, radius * 2, 180, 90); // Corner gp.CloseFigure(); diff --git a/Greenshot/Drawing/SpeechbubbleContainer.cs b/Greenshot/Drawing/SpeechbubbleContainer.cs index 64ede51e8..f90643ae9 100644 --- a/Greenshot/Drawing/SpeechbubbleContainer.cs +++ b/Greenshot/Drawing/SpeechbubbleContainer.cs @@ -3,7 +3,7 @@ * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,17 +21,15 @@ using Greenshot.Drawing.Fields; using Greenshot.Helpers; -using Greenshot.Plugin; using Greenshot.Plugin.Drawing; using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.Runtime.Serialization; -using System.Windows.Forms; -using log4net; -namespace Greenshot.Drawing { +namespace Greenshot.Drawing +{ /// /// Description of SpeechbubbleContainer. /// @@ -50,8 +48,8 @@ namespace Greenshot.Drawing { /// [OnSerializing] private void SetValuesOnSerializing(StreamingContext context) { - if (TargetGripper != null) { - _storedTargetGripperLocation = TargetGripper.Location; + if (TargetAdorner != null) { + _storedTargetGripperLocation = TargetAdorner.Location; } } @@ -59,9 +57,9 @@ namespace Greenshot.Drawing { /// Restore the target gripper /// /// - [OnDeserialized] - private void SetValuesOnDeserialized(StreamingContext context) { - InitTargetGripper(Color.Green, _storedTargetGripperLocation); + protected override void OnDeserialized(StreamingContext context) + { + InitAdorner(Color.Green, _storedTargetGripperLocation); } #endregion @@ -90,9 +88,9 @@ namespace Greenshot.Drawing { /// /// true if the surface doesn't need to handle the event public override bool HandleMouseDown(int mouseX, int mouseY) { - if (TargetGripper == null) { + if (TargetAdorner == null) { _initialGripperPoint = new Point(mouseX, mouseY); - InitTargetGripper(Color.Green, new Point(mouseX, mouseY)); + InitAdorner(Color.Green, new Point(mouseX, mouseY)); } return base.HandleMouseDown(mouseX, mouseY); } @@ -116,9 +114,9 @@ namespace Greenshot.Drawing { Point newGripperLocation = _initialGripperPoint; newGripperLocation.Offset(xOffset, yOffset); - if (TargetGripper.Location != newGripperLocation) { + if (TargetAdorner.Location != newGripperLocation) { Invalidate(); - TargetGripperMove(newGripperLocation.X, newGripperLocation.Y); + TargetAdorner.Location = newGripperLocation; Invalidate(); } return returnValue; @@ -180,7 +178,7 @@ namespace Greenshot.Drawing { private GraphicsPath CreateTail() { Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - int tailLength = GeometryHelper.Distance2D(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2), TargetGripper.Left, TargetGripper.Top); + int tailLength = GeometryHelper.Distance2D(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2), TargetAdorner.Location.X, TargetAdorner.Location.Y); int tailWidth = (Math.Abs(rect.Width) + Math.Abs(rect.Height)) / 20; // This should fix a problem with the tail being to wide @@ -192,10 +190,10 @@ namespace Greenshot.Drawing { tail.AddLine(tailWidth, 0, 0, -tailLength); tail.CloseFigure(); - int tailAngle = 90 + (int)GeometryHelper.Angle2D(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2), TargetGripper.Left, TargetGripper.Top); + int tailAngle = 90 + (int)GeometryHelper.Angle2D(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2, TargetAdorner.Location.X, TargetAdorner.Location.Y); using (Matrix tailMatrix = new Matrix()) { - tailMatrix.Translate(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2)); + tailMatrix.Translate(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2); tailMatrix.Rotate(tailAngle); tail.Transform(tailMatrix); } @@ -209,7 +207,7 @@ namespace Greenshot.Drawing { /// /// public override void Draw(Graphics graphics, RenderMode renderMode) { - if (TargetGripper == null) { + if (TargetAdorner == null) { return; } graphics.SmoothingMode = SmoothingMode.HighQuality; @@ -223,7 +221,7 @@ namespace Greenshot.Drawing { bool shadow = GetFieldValueAsBool(FieldType.SHADOW); int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); - bool lineVisible = (lineThickness > 0 && Colors.IsVisible(lineColor)); + bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor); Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); if (Selected && renderMode == RenderMode.EDIT) { @@ -253,7 +251,7 @@ namespace Greenshot.Drawing { graphics.DrawPath(shadowPen, bubbleClone); } currentStep++; - alpha = alpha - (basealpha / steps); + alpha = alpha - basealpha / steps; } } } diff --git a/Greenshot/Drawing/StepLabelContainer.cs b/Greenshot/Drawing/StepLabelContainer.cs index 79583c5ab..5994bf617 100644 --- a/Greenshot/Drawing/StepLabelContainer.cs +++ b/Greenshot/Drawing/StepLabelContainer.cs @@ -3,7 +3,7 @@ * Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.Runtime.Serialization; +using GreenshotPlugin.Interfaces.Drawing; namespace Greenshot.Drawing { /// @@ -34,7 +35,7 @@ namespace Greenshot.Drawing { /// To make sure that deleting recalculates, we check the location before every draw. /// [Serializable] - public class StepLabelContainer : DrawableContainer { + public sealed class StepLabelContainer : DrawableContainer { [NonSerialized] private StringFormat _stringFormat = new StringFormat(); @@ -45,11 +46,19 @@ namespace Greenshot.Drawing { public StepLabelContainer(Surface parent) : base(parent) { parent.AddStepLabel(this); InitContent(); + Init(); + } + + private void Init() + { + CreateDefaultAdorners(); } #region Number serializing // Used to store the number of this label, so when deserializing it can be placed back to the StepLabels list in the right location private int _number; + // Used to store the counter start of the Surface, as the surface is NOT stored. + private int _counterStart = 1; public int Number { get { return _number; @@ -67,6 +76,7 @@ namespace Greenshot.Drawing { private void SetValuesOnSerializing(StreamingContext context) { if (Parent != null) { Number = ((Surface)Parent).CountStepLabels(this); + _counterStart = ((Surface) Parent).CounterStart; } } #endregion @@ -75,11 +85,15 @@ namespace Greenshot.Drawing { /// Restore values that don't serialize /// /// - [OnDeserialized] - private void SetValuesOnDeserialized(StreamingContext context) { - _stringFormat = new StringFormat(); - _stringFormat.Alignment = StringAlignment.Center; - _stringFormat.LineAlignment = StringAlignment.Center; + protected override void OnDeserialized(StreamingContext context) + { + Init(); + _stringFormat = new StringFormat + { + Alignment = StringAlignment.Center, + LineAlignment = StringAlignment.Center + }; + } /// @@ -87,20 +101,22 @@ namespace Greenshot.Drawing { /// /// protected override void SwitchParent(Surface newParent) { - if (Parent != null) { - ((Surface)Parent).RemoveStepLabel(this); + if (newParent == Parent) + { + return; } + ((Surface) Parent)?.RemoveStepLabel(this); base.SwitchParent(newParent); - if (newParent != null) { - ((Surface)Parent).AddStepLabel(this); + if (newParent == null) + { + return; } + // Make sure the counter start is restored (this unfortunately happens multiple times... -> hack) + newParent.CounterStart = _counterStart; + newParent.AddStepLabel(this); } - public override Size DefaultSize { - get { - return new Size(30, 30); - } - } + public override Size DefaultSize => new Size(30, 30); public override bool InitContent() { _defaultEditMode = EditStatus.IDLE; @@ -118,7 +134,7 @@ namespace Greenshot.Drawing { /// This makes it possible for the label to be placed exactly in the middle of the pointer. /// public override bool HandleMouseDown(int mouseX, int mouseY) { - return base.HandleMouseDown(mouseX - (Width / 2), mouseY - (Height / 2)); + return base.HandleMouseDown(mouseX - Width / 2, mouseY - Height / 2); } /// @@ -127,6 +143,7 @@ namespace Greenshot.Drawing { protected override void InitializeFields() { AddField(GetType(), FieldType.FILL_COLOR, Color.DarkRed); AddField(GetType(), FieldType.LINE_COLOR, Color.White); + AddField(GetType(), FieldType.FLAGS, FieldFlag.COUNTER); } /// @@ -137,17 +154,19 @@ namespace Greenshot.Drawing { if (!disposing) { return; } - ((Surface)Parent).RemoveStepLabel(this); - if (_stringFormat != null) { - _stringFormat.Dispose(); - _stringFormat = null; + ((Surface) Parent)?.RemoveStepLabel(this); + if (_stringFormat == null) + { + return; } + _stringFormat.Dispose(); + _stringFormat = null; } public override bool HandleMouseMove(int x, int y) { Invalidate(); - Left = x - (Width / 2); - Top = y - (Height / 2); + Left = x - Width / 2; + Top = y - Height / 2; Invalidate(); return true; } @@ -167,7 +186,7 @@ namespace Greenshot.Drawing { int widthAfter = rect.Width; int heightAfter = rect.Height; - float factor = (((float)widthAfter / widthBefore) + ((float)heightAfter / heightBefore)) / 2; + float factor = ((float)widthAfter / widthBefore + (float)heightAfter / heightBefore) / 2; fontSize *= factor; } @@ -193,8 +212,8 @@ namespace Greenshot.Drawing { EllipseContainer.DrawEllipse(rect, graphics, rm, 0, Color.Transparent, fillColor, false); } using (FontFamily fam = new FontFamily(FontFamily.GenericSansSerif.Name)) { - using (Font _font = new Font(fam, fontSize, FontStyle.Bold, GraphicsUnit.Pixel)) { - TextContainer.DrawText(graphics, rect, 0, lineColor, false, _stringFormat, text, _font); + using (Font font = new Font(fam, fontSize, FontStyle.Bold, GraphicsUnit.Pixel)) { + TextContainer.DrawText(graphics, rect, 0, lineColor, false, _stringFormat, text, font); } } } diff --git a/Greenshot/Drawing/Surface.cs b/Greenshot/Drawing/Surface.cs index b28e2a86f..e8b90026d 100644 --- a/Greenshot/Drawing/Surface.cs +++ b/Greenshot/Drawing/Surface.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,15 +20,16 @@ */ using Greenshot.Configuration; -using Greenshot.Core; using Greenshot.Drawing.Fields; using Greenshot.Helpers; using Greenshot.IniFile; using Greenshot.Memento; using Greenshot.Plugin; using Greenshot.Plugin.Drawing; +using Greenshot.Plugin.Drawing.Adorners; using GreenshotPlugin.Controls; using GreenshotPlugin.Core; +using GreenshotPlugin.Interfaces.Drawing; using log4net; using System; using System.Collections.Generic; @@ -39,28 +40,38 @@ using System.Drawing.Imaging; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Windows.Forms; +using GreenshotPlugin.Effects; -namespace Greenshot.Drawing { - +namespace Greenshot.Drawing +{ /// /// Description of Surface. /// - public class Surface : Control, ISurface { - private static ILog LOG = LogManager.GetLogger(typeof(Surface)); - public static int Count = 0; - private static CoreConfiguration conf = IniConfig.GetIniSection(); + public sealed class Surface : Control, ISurface, INotifyPropertyChanged + { + private static readonly ILog LOG = LogManager.GetLogger(typeof(Surface)); + public static int Count; + private static readonly CoreConfiguration conf = IniConfig.GetIniSection(); // Property to identify the Surface ID private Guid _uniqueId = Guid.NewGuid(); + /// + /// This value is used to start counting the step labels + /// + private int _counterStart = 1; + /// /// The GUID of the surface /// - public Guid ID { - get { + public Guid ID + { + get + { return _uniqueId; } - set { + set + { _uniqueId = value; } } @@ -68,43 +79,70 @@ namespace Greenshot.Drawing { /// /// Event handlers (do not serialize!) /// + [NonSerialized] + private PropertyChangedEventHandler _propertyChanged; + public event PropertyChangedEventHandler PropertyChanged + { + add + { + _propertyChanged += value; + } + remove + { + _propertyChanged -= value; + } + } + [NonSerialized] private SurfaceElementEventHandler _movingElementChanged; - public event SurfaceElementEventHandler MovingElementChanged { - add { + public event SurfaceElementEventHandler MovingElementChanged + { + add + { _movingElementChanged += value; } - remove { + remove + { _movingElementChanged -= value; } } + [NonSerialized] private SurfaceDrawingModeEventHandler _drawingModeChanged; - public event SurfaceDrawingModeEventHandler DrawingModeChanged { - add { + public event SurfaceDrawingModeEventHandler DrawingModeChanged + { + add + { _drawingModeChanged += value; } - remove { + remove + { _drawingModeChanged -= value; } } [NonSerialized] private SurfaceSizeChangeEventHandler _surfaceSizeChanged; - public event SurfaceSizeChangeEventHandler SurfaceSizeChanged { - add { + public event SurfaceSizeChangeEventHandler SurfaceSizeChanged + { + add + { _surfaceSizeChanged += value; } - remove { + remove + { _surfaceSizeChanged -= value; } } [NonSerialized] private SurfaceMessageEventHandler _surfaceMessage; - public event SurfaceMessageEventHandler SurfaceMessage { - add { + public event SurfaceMessageEventHandler SurfaceMessage + { + add + { _surfaceMessage += value; } - remove { + remove + { _surfaceMessage -= value; } } @@ -169,7 +207,7 @@ namespace Greenshot.Drawing { /// all selected elements, do not serialize /// [NonSerialized] - private DrawableContainerList selectedElements; + private readonly IDrawableContainerList selectedElements; /// /// the element we are drawing with, do not serialize @@ -208,27 +246,56 @@ namespace Greenshot.Drawing { /// /// all stepLabels for the surface, needed with serialization /// - private List _stepLabels = new List(); + private readonly List _stepLabels = new List(); - public void AddStepLabel(StepLabelContainer stepLabel) { - _stepLabels.Add(stepLabel); + public void AddStepLabel(StepLabelContainer stepLabel) + { + if (!_stepLabels.Contains(stepLabel)) + { + _stepLabels.Add(stepLabel); + } } - public void RemoveStepLabel(StepLabelContainer stepLabel) { + + public void RemoveStepLabel(StepLabelContainer stepLabel) + { _stepLabels.Remove(stepLabel); } + /// + /// The start value of the counter objects + /// + public int CounterStart + { + get { return _counterStart; } + set + { + if (_counterStart == value) + { + return; + } + + _counterStart = value; + Invalidate(); + _propertyChanged?.Invoke(this, new PropertyChangedEventArgs("CounterStart")); + } + } + /// /// Count all the VISIBLE steplabels in the surface, up to the supplied one /// /// can be null, if not the counting stops here /// number of steplabels before the supplied container - public int CountStepLabels(IDrawableContainer stopAtContainer) { - int number = 1; - foreach (var possibleThis in _stepLabels) { - if (possibleThis == stopAtContainer) { + public int CountStepLabels(IDrawableContainer stopAtContainer) + { + int number = CounterStart; + foreach (var possibleThis in _stepLabels) + { + if (possibleThis.Equals(stopAtContainer)) + { break; } - if (IsOnSurface(possibleThis)) { + if (IsOnSurface(possibleThis)) + { number++; } } @@ -238,23 +305,18 @@ namespace Greenshot.Drawing { /// /// all elements on the surface, needed with serialization /// - private readonly DrawableContainerList _elements; + private readonly IDrawableContainerList _elements; /// /// all elements on the surface, needed with serialization /// - private FieldAggregator _fieldAggregator = new FieldAggregator(); + private FieldAggregator _fieldAggregator; /// /// the cursor container, needed with serialization as we need a direct acces to it. /// private IDrawableContainer _cursorContainer; - /// - /// the capture details, needed with serialization - /// - private ICaptureDetails _captureDetails; - /// /// the modified flag specifies if the surface has had modifications after the last export. /// Initial state is modified, as "it's not saved" @@ -267,11 +329,14 @@ namespace Greenshot.Drawing { /// The image is the actual captured image, needed with serialization /// private Image _image; - public Image Image { - get { + public Image Image + { + get + { return _image; } - set { + set + { _image = value; Size = _image.Size; } @@ -281,11 +346,14 @@ namespace Greenshot.Drawing { /// The field aggregator is that which is used to have access to all the fields inside the currently selected elements. /// e.g. used to decided if and which line thickness is shown when multiple elements are selected. /// - public FieldAggregator FieldAggregator { - get { + public FieldAggregator FieldAggregator + { + get + { return _fieldAggregator; } - set { + set + { _fieldAggregator = value; } } @@ -293,37 +361,33 @@ namespace Greenshot.Drawing { /// /// The cursor container has it's own accessor so we can find and remove this (when needed) /// - public IDrawableContainer CursorContainer { - get { - return _cursorContainer; - } - } + public IDrawableContainer CursorContainer => _cursorContainer; /// /// A simple getter to ask if this surface has a cursor /// - public bool HasCursor { - get { - return _cursorContainer != null; - } - } + public bool HasCursor => _cursorContainer != null; /// /// A simple helper method to remove the cursor from the surface /// - public void RemoveCursor() { - RemoveElement(_cursorContainer, true); + public void RemoveCursor() + { + RemoveElement(_cursorContainer); _cursorContainer = null; } /// /// The brush which is used to draw the transparent background /// - public Brush TransparencyBackgroundBrush { - get { + public Brush TransparencyBackgroundBrush + { + get + { return _transparencyBackgroundBrush; } - set { + set + { _transparencyBackgroundBrush = value; } } @@ -331,11 +395,14 @@ namespace Greenshot.Drawing { /// /// Are the keys on this surface locked? /// - public bool KeysLocked { - get { + public bool KeysLocked + { + get + { return _keysLocked; } - set { + set + { _keysLocked = value; } } @@ -343,11 +410,14 @@ namespace Greenshot.Drawing { /// /// Is this surface modified? This is only true if the surface has not been exported. /// - public bool Modified { - get { + public bool Modified + { + get + { return _modified; } - set { + set + { _modified = value; } } @@ -355,13 +425,18 @@ namespace Greenshot.Drawing { /// /// The DrawingMode property specifies the mode for drawing, more or less the element type. /// - public DrawingModes DrawingMode { - get {return _drawingMode;} - set { + public DrawingModes DrawingMode + { + get { return _drawingMode; } + set + { _drawingMode = value; - if (_drawingModeChanged != null) { - SurfaceDrawingModeEventArgs eventArgs = new SurfaceDrawingModeEventArgs(); - eventArgs.DrawingMode = _drawingMode; + if (_drawingModeChanged != null) + { + SurfaceDrawingModeEventArgs eventArgs = new SurfaceDrawingModeEventArgs + { + DrawingMode = _drawingMode + }; _drawingModeChanged.Invoke(this, eventArgs); } DeselectAllElements(); @@ -372,11 +447,14 @@ namespace Greenshot.Drawing { /// /// Property for accessing the last save "full" path /// - public string LastSaveFullPath { - get { + public string LastSaveFullPath + { + get + { return _lastSaveFullPath; } - set { + set + { _lastSaveFullPath = value; } } @@ -384,7 +462,8 @@ namespace Greenshot.Drawing { /// /// Property for accessing the URL to which the surface was recently uploaded /// - public string UploadURL { + public string UploadUrl + { get; set; } @@ -392,19 +471,14 @@ namespace Greenshot.Drawing { /// /// Property for accessing the capture details /// - public ICaptureDetails CaptureDetails { - get { - return _captureDetails; - } - set { - _captureDetails = value; - } - } + public ICaptureDetails CaptureDetails { get; set; } /// /// Base Surface constructor /// - public Surface() : base(){ + public Surface() + { + _fieldAggregator = new FieldAggregator(this); Count++; _elements = new DrawableContainerList(_uniqueId); selectedElements = new DrawableContainerList(_uniqueId); @@ -427,15 +501,17 @@ namespace Greenshot.Drawing { DoubleBuffered = true; SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.ContainerControl | ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor, true); } - + /// /// Private method, the current image is disposed the new one will stay. /// /// The new image /// true if the old image needs to be disposed, when using undo this should not be true!! - private void SetImage(Image newImage, bool dispose) { + private void SetImage(Image newImage, bool dispose) + { // Dispose - if (_image != null && dispose) { + if (_image != null && dispose) + { _image.Dispose(); } @@ -450,7 +526,8 @@ namespace Greenshot.Drawing { /// Surface constructor with an image /// /// - public Surface(Image newImage) : this() { + public Surface(Image newImage) : this() + { LOG.DebugFormat("Got image with dimensions {0} and format {1}", newImage.Size, newImage.PixelFormat); SetImage(newImage, true); } @@ -459,13 +536,16 @@ namespace Greenshot.Drawing { /// Surface contructor with a capture /// /// - public Surface(ICapture capture) : this(capture.Image) { + public Surface(ICapture capture) : this(capture.Image) + { // check if cursor is captured, and visible - if (capture.Cursor != null && capture.CursorVisible) { + if (capture.Cursor != null && capture.CursorVisible) + { Rectangle cursorRect = new Rectangle(capture.CursorLocation, capture.Cursor.Size); Rectangle captureRect = new Rectangle(Point.Empty, capture.Image.Size); // check if cursor is on the capture, otherwise we leave it out. - if (cursorRect.IntersectsWith(captureRect)) { + if (cursorRect.IntersectsWith(captureRect)) + { _cursorContainer = AddIconContainer(capture.Cursor, capture.CursorLocation.X, capture.CursorLocation.Y); SelectElement(_cursorContainer); } @@ -473,37 +553,46 @@ namespace Greenshot.Drawing { // Make sure the image is NOT disposed, we took the reference directly into ourselves ((Capture)capture).NullImage(); - _captureDetails = capture.CaptureDetails; + CaptureDetails = capture.CaptureDetails; } - protected override void Dispose(bool disposing) { - if (disposing) { + protected override void Dispose(bool disposing) + { + if (disposing) + { Count--; LOG.Debug("Disposing surface!"); - if (_buffer != null) { + if (_buffer != null) + { _buffer.Dispose(); _buffer = null; } - if (_transparencyBackgroundBrush != null) { + if (_transparencyBackgroundBrush != null) + { _transparencyBackgroundBrush.Dispose(); _transparencyBackgroundBrush = null; } // Cleanup undo/redo stacks - while (_undoStack != null && _undoStack.Count > 0) { + while (_undoStack != null && _undoStack.Count > 0) + { _undoStack.Pop().Dispose(); } - while (_redoStack != null && _redoStack.Count > 0) { + while (_redoStack != null && _redoStack.Count > 0) + { _redoStack.Pop().Dispose(); } - foreach (IDrawableContainer container in _elements) { + foreach (IDrawableContainer container in _elements) + { container.Dispose(); } - if (_undrawnElement != null) { + if (_undrawnElement != null) + { _undrawnElement.Dispose(); _undrawnElement = null; } - if (_cropContainer != null) { + if (_cropContainer != null) + { _cropContainer.Dispose(); _cropContainer = null; } @@ -514,87 +603,75 @@ namespace Greenshot.Drawing { /// /// Undo the last action /// - public void Undo() { - if (_undoStack.Count > 0) { + public void Undo() + { + if (_undoStack.Count > 0) + { _inUndoRedo = true; IMemento top = _undoStack.Pop(); _redoStack.Push(top.Restore()); _inUndoRedo = false; } - } + } /// /// Undo an undo (=redo) /// - public void Redo() { - if (_redoStack.Count > 0) { + public void Redo() + { + if (_redoStack.Count > 0) + { _inUndoRedo = true; IMemento top = _redoStack.Pop(); _undoStack.Push(top.Restore()); _inUndoRedo = false; } } - + /// /// Returns if the surface can do a undo /// - public bool CanUndo { - get { - return _undoStack.Count > 0; - } - } + public bool CanUndo => _undoStack.Count > 0; /// /// Returns if the surface can do a redo /// - public bool CanRedo { - get { - return _redoStack.Count > 0; - } - } + public bool CanRedo => _redoStack.Count > 0; /// /// Get the language key for the undo action /// - public LangKey UndoActionLanguageKey { - get { - if (CanUndo) { - return _undoStack.Peek().ActionLanguageKey; - } - return LangKey.none; - } - } + public LangKey UndoActionLanguageKey => LangKey.none; /// /// Get the language key for redo action /// - public LangKey RedoActionLanguageKey { - get { - if (CanRedo) { - return _redoStack.Peek().ActionLanguageKey; - } - return LangKey.none; - } - } + public LangKey RedoActionLanguageKey => LangKey.none; /// /// Make an action undo-able /// /// The memento implementing the undo /// Allow changes to be merged - public void MakeUndoable(IMemento memento, bool allowMerge) { - if (_inUndoRedo) { + public void MakeUndoable(IMemento memento, bool allowMerge) + { + if (_inUndoRedo) + { throw new InvalidOperationException("Invoking do within an undo/redo action."); } - if (memento != null) { + if (memento != null) + { bool allowPush = true; - if (_undoStack.Count > 0 && allowMerge) { + if (_undoStack.Count > 0 && allowMerge) + { // Check if merge is possible allowPush = !_undoStack.Peek().Merge(memento); } - if (allowPush) { + if (allowPush) + { // Clear the redo-stack and dispose - while(_redoStack.Count > 0) { + while (_redoStack.Count > 0) + { _redoStack.Pop().Dispose(); } _undoStack.Push(memento); @@ -608,14 +685,18 @@ namespace Greenshot.Drawing { /// /// /// - public long SaveElementsToStream(Stream streamWrite) { + public long SaveElementsToStream(Stream streamWrite) + { long bytesWritten = 0; - try { + try + { long lengtBefore = streamWrite.Length; BinaryFormatter binaryWrite = new BinaryFormatter(); binaryWrite.Serialize(streamWrite, _elements); bytesWritten = streamWrite.Length - lengtBefore; - } catch (Exception e) { + } + catch (Exception e) + { LOG.Error("Error serializing elements to stream.", e); } return bytesWritten; @@ -625,20 +706,22 @@ namespace Greenshot.Drawing { /// This loads elements from a stream, among others this is used to load a surface. /// /// - public void LoadElementsFromStream(Stream streamRead) { - try { + public void LoadElementsFromStream(Stream streamRead) + { + try + { BinaryFormatter binaryRead = new BinaryFormatter(); - DrawableContainerList loadedElements = (DrawableContainerList) binaryRead.Deserialize(streamRead); + IDrawableContainerList loadedElements = (IDrawableContainerList)binaryRead.Deserialize(streamRead); loadedElements.Parent = this; // Make sure the steplabels are sorted accoring to their number - _stepLabels.Sort(delegate(StepLabelContainer p1, StepLabelContainer p2) { - return p1.Number.CompareTo(p2.Number); - }); + _stepLabels.Sort((p1, p2) => p1.Number.CompareTo(p2.Number)); DeselectAllElements(); AddElements(loadedElements); SelectElements(loadedElements); FieldAggregator.BindElements(loadedElements); - } catch (Exception e) { + } + catch (Exception e) + { LOG.Error("Error serializing elements from stream.", e); } } @@ -648,11 +731,14 @@ namespace Greenshot.Drawing { /// But here an element is created which is not yet draw, thus "undrawnElement". /// The element is than used while drawing on the surface. /// - private void CreateUndrawnElement() { - if(_undrawnElement != null) { + private void CreateUndrawnElement() + { + if (_undrawnElement != null) + { FieldAggregator.UnbindElement(_undrawnElement); } - switch (DrawingMode) { + switch (DrawingMode) + { case DrawingModes.Rect: _undrawnElement = new RectangleContainer(this); break; @@ -694,22 +780,27 @@ namespace Greenshot.Drawing { _undrawnElement = null; break; } - if (_undrawnElement != null) { + if (_undrawnElement != null) + { FieldAggregator.BindElement(_undrawnElement); } } #region Plugin interface implementations - public IImageContainer AddImageContainer(Image image, int x, int y) { - ImageContainer bitmapContainer = new ImageContainer(this); - bitmapContainer.Image = image; - bitmapContainer.Left = x; - bitmapContainer.Top = y; + public IImageContainer AddImageContainer(Image image, int x, int y) + { + ImageContainer bitmapContainer = new ImageContainer(this) + { + Image = image, + Left = x, + Top = y + }; AddElement(bitmapContainer); return bitmapContainer; } - public IImageContainer AddImageContainer(string filename, int x, int y) { + public IImageContainer AddImageContainer(string filename, int x, int y) + { ImageContainer bitmapContainer = new ImageContainer(this); bitmapContainer.Load(filename); bitmapContainer.Left = x; @@ -717,15 +808,19 @@ namespace Greenshot.Drawing { AddElement(bitmapContainer); return bitmapContainer; } - public IIconContainer AddIconContainer(Icon icon, int x, int y) { - IconContainer iconContainer = new IconContainer(this); - iconContainer.Icon = icon; - iconContainer.Left = x; - iconContainer.Top = y; + public IIconContainer AddIconContainer(Icon icon, int x, int y) + { + IconContainer iconContainer = new IconContainer(this) + { + Icon = icon, + Left = x, + Top = y + }; AddElement(iconContainer); return iconContainer; } - public IIconContainer AddIconContainer(string filename, int x, int y) { + public IIconContainer AddIconContainer(string filename, int x, int y) + { IconContainer iconContainer = new IconContainer(this); iconContainer.Load(filename); iconContainer.Left = x; @@ -733,15 +828,19 @@ namespace Greenshot.Drawing { AddElement(iconContainer); return iconContainer; } - public ICursorContainer AddCursorContainer(Cursor cursor, int x, int y) { - CursorContainer cursorContainer = new CursorContainer(this); - cursorContainer.Cursor = cursor; - cursorContainer.Left = x; - cursorContainer.Top = y; + public ICursorContainer AddCursorContainer(Cursor cursor, int x, int y) + { + CursorContainer cursorContainer = new CursorContainer(this) + { + Cursor = cursor, + Left = x, + Top = y + }; AddElement(cursorContainer); return cursorContainer; } - public ICursorContainer AddCursorContainer(string filename, int x, int y) { + public ICursorContainer AddCursorContainer(string filename, int x, int y) + { CursorContainer cursorContainer = new CursorContainer(this); cursorContainer.Load(filename); cursorContainer.Left = x; @@ -750,9 +849,9 @@ namespace Greenshot.Drawing { return cursorContainer; } - public ITextContainer AddTextContainer(string text, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, FontFamily family, float size, bool italic, bool bold, bool shadow, int borderSize, Color color, Color fillColor) { - TextContainer textContainer = new TextContainer(this); - textContainer.Text = text; + public ITextContainer AddTextContainer(string text, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, FontFamily family, float size, bool italic, bool bold, bool shadow, int borderSize, Color color, Color fillColor) + { + TextContainer textContainer = new TextContainer(this) {Text = text}; textContainer.SetFieldValue(FieldType.FONT_FAMILY, family.Name); textContainer.SetFieldValue(FieldType.FONT_BOLD, bold); textContainer.SetFieldValue(FieldType.FONT_ITALIC, italic); @@ -774,19 +873,28 @@ namespace Greenshot.Drawing { #region DragDrop - private void OnDragEnter(object sender, DragEventArgs e) { - if(LOG.IsDebugEnabled) { + private void OnDragEnter(object sender, DragEventArgs e) + { + if (LOG.IsDebugEnabled) + { LOG.Debug("DragEnter got following formats: "); - foreach(string format in ClipboardHelper.GetFormats(e.Data)) { + foreach (string format in ClipboardHelper.GetFormats(e.Data)) + { LOG.Debug(format); } } - if ((e.AllowedEffect & DragDropEffects.Copy) != DragDropEffects.Copy) { - e.Effect=DragDropEffects.None; - } else { - if (ClipboardHelper.ContainsImage(e.Data) || ClipboardHelper.ContainsFormat(e.Data, "DragImageBits")) { + if ((e.AllowedEffect & DragDropEffects.Copy) != DragDropEffects.Copy) + { + e.Effect = DragDropEffects.None; + } + else + { + if (ClipboardHelper.ContainsImage(e.Data) || ClipboardHelper.ContainsFormat(e.Data, "DragImageBits")) + { e.Effect = DragDropEffects.Copy; - } else { + } + else + { e.Effect = DragDropEffects.None; } } @@ -797,14 +905,19 @@ namespace Greenshot.Drawing { /// /// /// - private void OnDragDrop(object sender, DragEventArgs e) { + private void OnDragDrop(object sender, DragEventArgs e) + { Point mouse = PointToClient(new Point(e.X, e.Y)); - if (e.Data.GetDataPresent("Text")) { + if (e.Data.GetDataPresent("Text")) + { string possibleUrl = ClipboardHelper.GetText(e.Data); // Test if it's an url and try to download the image so we have it in the original form - if (possibleUrl != null && possibleUrl.StartsWith("http")) { - using (Image image = NetworkHelper.DownloadImage(possibleUrl)) { - if (image != null) { + if (possibleUrl != null && possibleUrl.StartsWith("http")) + { + using (Image image = NetworkHelper.DownloadImage(possibleUrl)) + { + if (image != null) + { AddImageContainer(image, mouse.X, mouse.Y); return; } @@ -812,25 +925,29 @@ namespace Greenshot.Drawing { } } - foreach (Image image in ClipboardHelper.GetImages(e.Data)) { + foreach (Image image in ClipboardHelper.GetImages(e.Data)) + { AddImageContainer(image, mouse.X, mouse.Y); mouse.Offset(10, 10); image.Dispose(); } } - + #endregion /// /// Auto crop the image /// /// true if cropped - public bool AutoCrop() { + public bool AutoCrop() + { Rectangle cropRectangle; - using (Image tmpImage = GetImageForExport()) { + using (Image tmpImage = GetImageForExport()) + { cropRectangle = ImageHelper.FindAutoCropRectangle(tmpImage, conf.AutoCropDifference); } - if (!IsCropPossible(ref cropRectangle)) { + if (!IsCropPossible(ref cropRectangle)) + { return false; } DeselectAllElements(); @@ -853,10 +970,12 @@ namespace Greenshot.Drawing { /// A simple clear /// /// The color for the background - public void Clear(Color newColor) { + public void Clear(Color newColor) + { //create a blank bitmap the same size as original Bitmap newBitmap = ImageHelper.CreateEmptyLike(Image, Color.Empty); - if (newBitmap != null) { + if (newBitmap != null) + { // Make undoable MakeUndoable(new SurfaceBackgroundChangeMemento(this, null), false); SetImage(newBitmap, false); @@ -868,29 +987,37 @@ namespace Greenshot.Drawing { /// Apply a bitmap effect to the surface /// /// - public void ApplyBitmapEffect(IEffect effect) { + public void ApplyBitmapEffect(IEffect effect) + { BackgroundForm backgroundForm = new BackgroundForm("Effect", "Please wait"); backgroundForm.Show(); Application.DoEvents(); - try { + try + { Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size); Matrix matrix = new Matrix(); Image newImage = ImageHelper.ApplyEffect(Image, effect, matrix); - if (newImage != null) { + if (newImage != null) + { // Make sure the elements move according to the offset the effect made the bitmap move _elements.Transform(matrix); // Make undoable MakeUndoable(new SurfaceBackgroundChangeMemento(this, matrix), false); SetImage(newImage, false); Invalidate(); - if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, newImage.Size))) { + if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, newImage.Size))) + { _surfaceSizeChanged(this, null); } - } else { + } + else + { // clean up matrix, as it hasn't been used in the undo stack. matrix.Dispose(); } - } finally { + } + finally + { // Always close the background form backgroundForm.CloseDialog(); } @@ -901,38 +1028,48 @@ namespace Greenshot.Drawing { /// /// /// true if this is possible - public bool IsCropPossible(ref Rectangle cropRectangle) { + public bool IsCropPossible(ref Rectangle cropRectangle) + { cropRectangle = GuiRectangle.GetGuiRectangle(cropRectangle.Left, cropRectangle.Top, cropRectangle.Width, cropRectangle.Height); - if (cropRectangle.Left < 0) { + if (cropRectangle.Left < 0) + { cropRectangle = new Rectangle(0, cropRectangle.Top, cropRectangle.Width + cropRectangle.Left, cropRectangle.Height); } - if (cropRectangle.Top < 0) { + if (cropRectangle.Top < 0) + { cropRectangle = new Rectangle(cropRectangle.Left, 0, cropRectangle.Width, cropRectangle.Height + cropRectangle.Top); } - if (cropRectangle.Left + cropRectangle.Width > Width) { + if (cropRectangle.Left + cropRectangle.Width > Width) + { cropRectangle = new Rectangle(cropRectangle.Left, cropRectangle.Top, Width - cropRectangle.Left, cropRectangle.Height); } - if (cropRectangle.Top + cropRectangle.Height > Height) { + if (cropRectangle.Top + cropRectangle.Height > Height) + { cropRectangle = new Rectangle(cropRectangle.Left, cropRectangle.Top, cropRectangle.Width, Height - cropRectangle.Top); } - if (cropRectangle.Height > 0 && cropRectangle.Width > 0) { + if (cropRectangle.Height > 0 && cropRectangle.Width > 0) + { return true; } return false; } - + /// /// Use to send any registered SurfaceMessageEventHandler a message, e.g. used for the notification area /// /// Who send /// Type of message /// Message itself - public void SendMessageEvent(object source, SurfaceMessageTyp messageType, string message) { - if (_surfaceMessage != null) { - SurfaceMessageEventArgs eventArgs = new SurfaceMessageEventArgs(); - eventArgs.Message = message; - eventArgs.MessageType = messageType; - eventArgs.Surface = this; + public void SendMessageEvent(object source, SurfaceMessageTyp messageType, string message) + { + if (_surfaceMessage != null) + { + var eventArgs = new SurfaceMessageEventArgs + { + Message = message, + MessageType = messageType, + Surface = this + }; _surfaceMessage(source, eventArgs); } } @@ -942,14 +1079,19 @@ namespace Greenshot.Drawing { /// /// /// - public bool ApplyCrop(Rectangle cropRectangle) { - if (IsCropPossible(ref cropRectangle)) { + public bool ApplyCrop(Rectangle cropRectangle) + { + if (IsCropPossible(ref cropRectangle)) + { Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size); Bitmap tmpImage; // Make sure we have information, this this fails - try { + try + { tmpImage = ImageHelper.CloneArea(Image, cropRectangle, PixelFormat.DontCare); - } catch (Exception ex) { + } + catch (Exception ex) + { ex.Data.Add("CropRectangle", cropRectangle); ex.Data.Add("Width", Image.Width); ex.Data.Add("Height", Image.Height); @@ -965,7 +1107,8 @@ namespace Greenshot.Drawing { // Do not dispose otherwise we can't undo the image! SetImage(tmpImage, false); _elements.Transform(matrix); - if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, tmpImage.Size))) { + if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, tmpImage.Size))) + { _surfaceSizeChanged(this, null); } Invalidate(); @@ -980,39 +1123,78 @@ namespace Greenshot.Drawing { /// /// /// - public void UndoBackgroundChange(Image previous, Matrix matrix) { + public void UndoBackgroundChange(Image previous, Matrix matrix) + { SetImage(previous, false); - if (matrix != null) { + if (matrix != null) + { _elements.Transform(matrix); } - if (_surfaceSizeChanged != null) { - _surfaceSizeChanged(this, null); - } + _surfaceSizeChanged?.Invoke(this, null); Invalidate(); } + /// + /// Check if an adorner was "hit", and change the cursor if so + /// + /// MouseEventArgs + /// IAdorner + private IAdorner FindActiveAdorner(MouseEventArgs mouseEventArgs) + { + foreach (IDrawableContainer drawableContainer in selectedElements) + { + foreach (IAdorner adorner in drawableContainer.Adorners) + { + + if (adorner.IsActive || adorner.HitTest(mouseEventArgs.Location)) + { + if (adorner.Cursor != null) + { + Cursor = adorner.Cursor; + } + return adorner; + } + } + } + return null; + } /// /// This event handler is called when someone presses the mouse on a surface. /// /// /// - void SurfaceMouseDown(object sender, MouseEventArgs e) { + private void SurfaceMouseDown(object sender, MouseEventArgs e) + { + + // Handle Adorners + var adorner = FindActiveAdorner(e); + if (adorner != null) + { + adorner.MouseDown(sender, e); + return; + } + _mouseStart = e.Location; - + // check contextmenu - if (e.Button == MouseButtons.Right) { - DrawableContainerList selectedList = null; - if (selectedElements != null && selectedElements.Count > 0) { + if (e.Button == MouseButtons.Right) + { + IDrawableContainerList selectedList = null; + if (selectedElements != null && selectedElements.Count > 0) + { selectedList = selectedElements; - } else { + } + else + { // Single element IDrawableContainer rightClickedContainer = _elements.ClickableElementAt(_mouseStart.X, _mouseStart.Y); - if (rightClickedContainer != null) { - selectedList = new DrawableContainerList(ID); - selectedList.Add(rightClickedContainer); + if (rightClickedContainer != null) + { + selectedList = new DrawableContainerList(ID) {rightClickedContainer}; } } - if (selectedList != null && selectedList.Count > 0) { + if (selectedList != null && selectedList.Count > 0) + { selectedList.ShowContextMenu(e, this); } return; @@ -1021,25 +1203,33 @@ namespace Greenshot.Drawing { _mouseDown = true; _isSurfaceMoveMadeUndoable = false; - if (_cropContainer != null && ((_undrawnElement == null) || (_undrawnElement != null && DrawingMode != DrawingModes.Crop))) { + if (_cropContainer != null && ((_undrawnElement == null) || (_undrawnElement != null && DrawingMode != DrawingModes.Crop))) + { RemoveElement(_cropContainer, false); _cropContainer = null; _drawingElement = null; } - if (_drawingElement == null && DrawingMode != DrawingModes.None) { - if (_undrawnElement == null) { + if (_drawingElement == null && DrawingMode != DrawingModes.None) + { + if (_undrawnElement == null) + { DeselectAllElements(); - if (_undrawnElement == null) { + if (_undrawnElement == null) + { CreateUndrawnElement(); } } _drawingElement = _undrawnElement; // if a new element has been drawn, set location and register it - if (_drawingElement != null) { - _drawingElement.Status = _undrawnElement.DefaultEditMode; - _drawingElement.PropertyChanged += ElementPropertyChanged; - if (!_drawingElement.HandleMouseDown(_mouseStart.X, _mouseStart.Y)) { + if (_drawingElement != null) + { + if (_undrawnElement != null) + { + _drawingElement.Status = _undrawnElement.DefaultEditMode; + } + if (!_drawingElement.HandleMouseDown(_mouseStart.X, _mouseStart.Y)) + { _drawingElement.Left = _mouseStart.X; _drawingElement.Top = _mouseStart.Y; } @@ -1047,13 +1237,16 @@ namespace Greenshot.Drawing { _drawingElement.Selected = true; } _undrawnElement = null; - } else { + } + else + { // check whether an existing element was clicked // we save mouse down element separately from selectedElements (checked on mouse up), // since it could be moved around before it is actually selected _mouseDownElement = _elements.ClickableElementAt(_mouseStart.X, _mouseStart.Y); - if (_mouseDownElement != null) { + if (_mouseDownElement != null) + { _mouseDownElement.Status = EditStatus.MOVING; } } @@ -1064,52 +1257,80 @@ namespace Greenshot.Drawing { /// /// /// - void SurfaceMouseUp(object sender, MouseEventArgs e) { + private void SurfaceMouseUp(object sender, MouseEventArgs e) + { + + // Handle Adorners + var adorner = FindActiveAdorner(e); + if (adorner != null) + { + adorner.MouseUp(sender, e); + return; + } + Point currentMouse = new Point(e.X, e.Y); _elements.Status = EditStatus.IDLE; - if (_mouseDownElement != null) { + if (_mouseDownElement != null) + { _mouseDownElement.Status = EditStatus.IDLE; } _mouseDown = false; _mouseDownElement = null; - if (DrawingMode == DrawingModes.None) { + if (DrawingMode == DrawingModes.None) + { // check whether an existing element was clicked IDrawableContainer element = _elements.ClickableElementAt(currentMouse.X, currentMouse.Y); bool shiftModifier = (ModifierKeys & Keys.Shift) == Keys.Shift; - if (element != null) { + if (element != null) + { element.Invalidate(); bool alreadySelected = selectedElements.Contains(element); - if (shiftModifier) { - if (alreadySelected) { + if (shiftModifier) + { + if (alreadySelected) + { DeselectElement(element); - } else { + } + else + { SelectElement(element); } - } else { - if (!alreadySelected) { + } + else + { + if (!alreadySelected) + { DeselectAllElements(); SelectElement(element); } } - } else if(!shiftModifier) { + } + else if (!shiftModifier) + { DeselectAllElements(); } } - - if (selectedElements.Count > 0) { - selectedElements.ShowGrippers(); + + if (selectedElements.Count > 0) + { + selectedElements.Invalidate(); selectedElements.Selected = true; } - if (_drawingElement != null) { - if (!_drawingElement.InitContent()) { + if (_drawingElement != null) + { + if (!_drawingElement.InitContent()) + { _elements.Remove(_drawingElement); _drawingElement.Invalidate(); - } else { + } + else + { _drawingElement.HandleMouseUp(currentMouse.X, currentMouse.Y); _drawingElement.Invalidate(); - if (Math.Abs(_drawingElement.Width) < 5 && Math.Abs(_drawingElement.Height) < 5) { + if (Math.Abs(_drawingElement.Width) < 5 && Math.Abs(_drawingElement.Height) < 5) + { _drawingElement.Width = 25; _drawingElement.Height = 25; } @@ -1125,30 +1346,42 @@ namespace Greenshot.Drawing { /// /// /// - void SurfaceMouseMove(object sender, MouseEventArgs e) { - Point currentMouse = e.Location; - - if (DrawingMode != DrawingModes.None) { - Cursor = Cursors.Cross; - } else { - Cursor = Cursors.Default; + private void SurfaceMouseMove(object sender, MouseEventArgs e) + { + // Handle Adorners + var adorner = FindActiveAdorner(e); + if (adorner != null) + { + adorner.MouseMove(sender, e); + return; } - if (_mouseDown) { - if (_mouseDownElement != null) { // an element is currently dragged + Point currentMouse = e.Location; + + Cursor = DrawingMode != DrawingModes.None ? Cursors.Cross : Cursors.Default; + + if (_mouseDown) + { + if (_mouseDownElement != null) + { // an element is currently dragged _mouseDownElement.Invalidate(); - selectedElements.HideGrippers(); + selectedElements.Invalidate(); // Move the element - if (_mouseDownElement.Selected) { - if (!_isSurfaceMoveMadeUndoable) { + if (_mouseDownElement.Selected) + { + if (!_isSurfaceMoveMadeUndoable) + { // Only allow one undoable per mouse-down/move/up "cycle" _isSurfaceMoveMadeUndoable = true; selectedElements.MakeBoundsChangeUndoable(false); } // dragged element has been selected before -> move all selectedElements.MoveBy(currentMouse.X - _mouseStart.X, currentMouse.Y - _mouseStart.Y); - } else { - if (!_isSurfaceMoveMadeUndoable) { + } + else + { + if (!_isSurfaceMoveMadeUndoable) + { // Only allow one undoable per mouse-down/move/up "cycle" _isSurfaceMoveMadeUndoable = true; _mouseDownElement.MakeBoundsChangeUndoable(false); @@ -1159,19 +1392,22 @@ namespace Greenshot.Drawing { _mouseStart = currentMouse; _mouseDownElement.Invalidate(); _modified = true; - } else if (_drawingElement != null) { + } + else if (_drawingElement != null) + { _drawingElement.HandleMouseMove(currentMouse.X, currentMouse.Y); _modified = true; } } } - + /// /// This event handler is called when the surface is double clicked. /// /// /// - void SurfaceDoubleClick(object sender, MouseEventArgs e) { + private void SurfaceDoubleClick(object sender, MouseEventArgs e) + { selectedElements.OnDoubleClick(); selectedElements.Invalidate(); } @@ -1181,11 +1417,13 @@ namespace Greenshot.Drawing { /// /// /// - private Image GetImage(RenderMode renderMode) { + private Image GetImage(RenderMode renderMode) + { // Generate a copy of the original image with a dpi equal to the default... Bitmap clone = ImageHelper.Clone(_image, PixelFormat.DontCare); // otherwise we would have a problem drawing the image to the surface... :( - using (Graphics graphics = Graphics.FromImage(clone)) { + using (Graphics graphics = Graphics.FromImage(clone)) + { // Do not set the following, the containers need to decide themselves //graphics.SmoothingMode = SmoothingMode.HighQuality; //graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; @@ -1200,36 +1438,44 @@ namespace Greenshot.Drawing { /// This returns the image "result" of this surface, with all the elements rendered on it. /// /// - public Image GetImageForExport() { + public Image GetImageForExport() + { return GetImage(RenderMode.EXPORT); } - + /// /// This is the event handler for the Paint Event, try to draw as little as possible! /// /// - /// - void SurfacePaint(object sender, PaintEventArgs e) { - Graphics targetGraphics = e.Graphics; - Rectangle clipRectangle = e.ClipRectangle; - if (Rectangle.Empty.Equals(clipRectangle)) { + /// PaintEventArgs + private void SurfacePaint(object sender, PaintEventArgs paintEventArgs) + { + Graphics targetGraphics = paintEventArgs.Graphics; + Rectangle clipRectangle = paintEventArgs.ClipRectangle; + if (Rectangle.Empty.Equals(clipRectangle)) + { LOG.Debug("Empty cliprectangle??"); return; } - if (_elements.HasIntersectingFilters(clipRectangle)) { - if (_buffer != null) { - if (_buffer.Width != Image.Width || _buffer.Height != Image.Height || _buffer.PixelFormat != Image.PixelFormat) { + if (_elements.HasIntersectingFilters(clipRectangle)) + { + if (_buffer != null) + { + if (_buffer.Width != Image.Width || _buffer.Height != Image.Height || _buffer.PixelFormat != Image.PixelFormat) + { _buffer.Dispose(); _buffer = null; } } - if (_buffer == null) { + if (_buffer == null) + { _buffer = ImageHelper.CreateEmpty(Image.Width, Image.Height, Image.PixelFormat, Color.Empty, Image.HorizontalResolution, Image.VerticalResolution); LOG.DebugFormat("Created buffer with size: {0}x{1}", Image.Width, Image.Height); } // Elements might need the bitmap, so we copy the part we need - using (Graphics graphics = Graphics.FromImage(_buffer)) { + using (Graphics graphics = Graphics.FromImage(_buffer)) + { // do not set the following, the containers need to decide this themselves! //graphics.SmoothingMode = SmoothingMode.HighQuality; //graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; @@ -1241,35 +1487,45 @@ namespace Greenshot.Drawing { _elements.Draw(graphics, _buffer, RenderMode.EDIT, clipRectangle); } targetGraphics.DrawImage(_buffer, clipRectangle, clipRectangle, GraphicsUnit.Pixel); - } else { + } + else + { DrawBackground(targetGraphics, clipRectangle); targetGraphics.DrawImage(Image, clipRectangle, clipRectangle, GraphicsUnit.Pixel); _elements.Draw(targetGraphics, null, RenderMode.EDIT, clipRectangle); } + + // No clipping for the adorners + targetGraphics.ResetClip(); + // Draw adorners last + foreach (var drawableContainer in selectedElements) + { + foreach (var adorner in drawableContainer.Adorners) + { + adorner.Paint(paintEventArgs); + } + } } - private void DrawBackground(Graphics targetGraphics, Rectangle clipRectangle) { + private void DrawBackground(Graphics targetGraphics, Rectangle clipRectangle) + { // check if we need to draw the checkerboard - if (Image.IsAlphaPixelFormat(Image.PixelFormat) && _transparencyBackgroundBrush != null) { + if (Image.IsAlphaPixelFormat(Image.PixelFormat) && _transparencyBackgroundBrush != null) + { targetGraphics.FillRectangle(_transparencyBackgroundBrush, clipRectangle); - } else { + } + else + { targetGraphics.Clear(BackColor); } } - + /// /// Draw a checkboard when capturing with transparency /// /// PaintEventArgs - protected override void OnPaintBackground(PaintEventArgs e) { - } - - /// - /// Wrapper for makeUndoable flag which was introduced later, will call AddElement with makeundoable set to true - /// - /// the new element - public void AddElement(IDrawableContainer element) { - AddElement(element, true); + protected override void OnPaintBackground(PaintEventArgs e) + { } /// @@ -1277,39 +1533,91 @@ namespace Greenshot.Drawing { /// /// the new element /// true if the adding should be undoable - public void AddElement(IDrawableContainer element, bool makeUndoable) { + /// true if invalidate needs to be called + public void AddElement(IDrawableContainer element, bool makeUndoable = true, bool invalidate = true) + { _elements.Add(element); DrawableContainer container = element as DrawableContainer; - if (container != null) { + if (container != null) + { container.FieldChanged += element_FieldChanged; } - element.PropertyChanged += ElementPropertyChanged; - if (element.Status == EditStatus.UNDRAWN) { + element.Parent = this; + if (element.Status == EditStatus.UNDRAWN) + { element.Status = EditStatus.IDLE; } - element.Invalidate(); - if (makeUndoable) { + if (element.Selected) + { + // Use false, as the element is invalidated when invalidate == true anyway + SelectElement(element, false); + } + if (invalidate) + { + element.Invalidate(); + } + if (makeUndoable) + { MakeUndoable(new AddElementMemento(this, element), false); } _modified = true; } + /// + /// Remove the list of elements + /// + /// IDrawableContainerList + /// flag specifying if the remove needs to be undoable + public void RemoveElements(IDrawableContainerList elementsToRemove, bool makeUndoable = true) + { + // fix potential issues with iterating a changing list + DrawableContainerList cloned = new DrawableContainerList(); + cloned.AddRange(elementsToRemove); + if (makeUndoable) + { + MakeUndoable(new DeleteElementsMemento(this, cloned), false); + } + SuspendLayout(); + foreach (var drawableContainer in cloned) + { + RemoveElement(drawableContainer, false, false, false); + } + ResumeLayout(); + Invalidate(); + if (_movingElementChanged != null) + { + SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs {Elements = cloned}; + _movingElementChanged(this, eventArgs); + } + } + /// /// Remove an element of the elements list /// /// Element to remove /// flag specifying if the remove needs to be undoable - public void RemoveElement(IDrawableContainer elementToRemove, bool makeUndoable) { - DeselectElement(elementToRemove); + /// flag specifying if an surface invalidate needs to be called + /// false to skip event generation + public void RemoveElement(IDrawableContainer elementToRemove, bool makeUndoable = true, bool invalidate = true, bool generateEvents = true) + { + DeselectElement(elementToRemove, generateEvents); _elements.Remove(elementToRemove); DrawableContainer element = elementToRemove as DrawableContainer; - if (element != null) { + if (element != null) + { element.FieldChanged -= element_FieldChanged; } - elementToRemove.PropertyChanged -= ElementPropertyChanged; + if (elementToRemove != null) + { + elementToRemove.Parent = null; + } // Do not dispose, the memento should!! element.Dispose(); - Invalidate(); - if (makeUndoable) { + if (invalidate) + { + Invalidate(); + } + if (makeUndoable) + { MakeUndoable(new DeleteElementMemento(this, elementToRemove), false); } _modified = true; @@ -1318,43 +1626,45 @@ namespace Greenshot.Drawing { /// /// Add the supplied elements to the surface /// - /// - public void AddElements(DrawableContainerList elementsToAdd) { - foreach(IDrawableContainer element in elementsToAdd) { - AddElement(element, true); + /// DrawableContainerList + /// true if the adding should be undoable + public void AddElements(IDrawableContainerList elementsToAdd, bool makeUndoable = true) + { + // fix potential issues with iterating a changing list + DrawableContainerList cloned = new DrawableContainerList(); + cloned.AddRange(elementsToAdd); + if (makeUndoable) + { + MakeUndoable(new AddElementsMemento(this, cloned), false); } + SuspendLayout(); + foreach (var element in cloned) + { + element.Selected = true; + AddElement(element, false, false); + } + ResumeLayout(); + Invalidate(); } /// /// Returns if this surface has selected elements /// /// - public bool HasSelectedElements { - get { - return (selectedElements != null && selectedElements.Count > 0); - } - } + public bool HasSelectedElements => (selectedElements != null && selectedElements.Count > 0); /// /// Remove all the selected elements /// - public void RemoveSelectedElements() { - if (HasSelectedElements) { - // As RemoveElement will remove the element from the selectedElements list we need to copy the element - // to another list. - List elementsToRemove = new List(); - foreach (DrawableContainer element in selectedElements) { - // Collect to remove later - elementsToRemove.Add(element); - } - // Remove now - foreach(DrawableContainer element in elementsToRemove) { - RemoveElement(element, true); - } - selectedElements.Clear(); - if (_movingElementChanged != null) { + public void RemoveSelectedElements() + { + if (HasSelectedElements) + { + // As RemoveElement will remove the element from the selectedElements list we need to copy the element to another list. + RemoveElements(selectedElements); + if (_movingElementChanged != null) + { SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs(); - eventArgs.Elements = selectedElements; _movingElementChanged(this, eventArgs); } } @@ -1363,9 +1673,11 @@ namespace Greenshot.Drawing { /// /// Cut the selected elements from the surface to the clipboard /// - public void CutSelectedElements() { - if (HasSelectedElements) { - ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), selectedElements); + public void CutSelectedElements() + { + if (HasSelectedElements) + { + ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), selectedElements); RemoveSelectedElements(); } } @@ -1373,9 +1685,11 @@ namespace Greenshot.Drawing { /// /// Copy the selected elements to the clipboard /// - public void CopySelectedElements() { - if (HasSelectedElements) { - ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), selectedElements); + public void CopySelectedElements() + { + if (HasSelectedElements) + { + ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), selectedElements); } } @@ -1384,19 +1698,24 @@ namespace Greenshot.Drawing { /// Called when pressing enter or using the "check" in the editor. /// /// - public void ConfirmSelectedConfirmableElements(bool confirm){ + public void ConfirmSelectedConfirmableElements(bool confirm) + { // create new collection so that we can iterate safely (selectedElements might change due with confirm/cancel) List selectedDCs = new List(selectedElements); - foreach (IDrawableContainer dc in selectedDCs){ - if (dc.Equals(_cropContainer)){ + foreach (IDrawableContainer dc in selectedDCs) + { + if (dc.Equals(_cropContainer)) + { DrawingMode = DrawingModes.None; // No undo memento for the cropcontainer itself, only for the effect RemoveElement(_cropContainer, false); - if (confirm) { + if (confirm) + { ApplyCrop(_cropContainer.Bounds); } _cropContainer.Dispose(); _cropContainer = null; + break; } } } @@ -1404,78 +1723,83 @@ namespace Greenshot.Drawing { /// /// Paste all the elements that are on the clipboard /// - public void PasteElementFromClipboard() { + public void PasteElementFromClipboard() + { IDataObject clipboard = ClipboardHelper.GetDataObject(); - List formats = ClipboardHelper.GetFormats(clipboard); - if (formats == null || formats.Count == 0) { + var formats = ClipboardHelper.GetFormats(clipboard); + if (formats == null || formats.Count == 0) + { return; } - if (LOG.IsDebugEnabled) { + if (LOG.IsDebugEnabled) + { LOG.Debug("List of clipboard formats available for pasting:"); - foreach(string format in formats) { + foreach (string format in formats) + { LOG.Debug("\tgot format: " + format); } } - if (formats.Contains(typeof(DrawableContainerList).FullName)) { - DrawableContainerList dcs = (DrawableContainerList)ClipboardHelper.GetFromDataObject(clipboard, typeof(DrawableContainerList)); - if (dcs != null) { + if (formats.Contains(typeof(IDrawableContainerList).FullName)) + { + IDrawableContainerList dcs = (IDrawableContainerList)ClipboardHelper.GetFromDataObject(clipboard, typeof(IDrawableContainerList)); + if (dcs != null) + { // Make element(s) only move 10,10 if the surface is the same - Point moveOffset; bool isSameSurface = (dcs.ParentID == _uniqueId); dcs.Parent = this; - if (isSameSurface) { - moveOffset = new Point(10, 10); - } else { - moveOffset = Point.Empty; - } - // Here a fix for bug #1475, first calculate the bounds of the complete DrawableContainerList + var moveOffset = isSameSurface ? new Point(10, 10) : Point.Empty; + // Here a fix for bug #1475, first calculate the bounds of the complete IDrawableContainerList Rectangle drawableContainerListBounds = Rectangle.Empty; - foreach (IDrawableContainer element in dcs) { - if (drawableContainerListBounds == Rectangle.Empty) { - drawableContainerListBounds = element.DrawingBounds; - } else { - drawableContainerListBounds = Rectangle.Union(drawableContainerListBounds, element.DrawingBounds); - } + foreach (var element in dcs) + { + drawableContainerListBounds = drawableContainerListBounds == Rectangle.Empty ? element.DrawingBounds : Rectangle.Union(drawableContainerListBounds, element.DrawingBounds); } // And find a location inside the target surface to paste to bool containersCanFit = drawableContainerListBounds.Width < Bounds.Width && drawableContainerListBounds.Height < Bounds.Height; - if (!containersCanFit) { + if (!containersCanFit) + { Point containersLocation = drawableContainerListBounds.Location; containersLocation.Offset(moveOffset); - if (!Bounds.Contains(containersLocation)) { + if (!Bounds.Contains(containersLocation)) + { // Easy fix for same surface - if (isSameSurface) { - moveOffset = new Point(-10, -10); - } else { - // For different surface, which is most likely smaller, we move to "10,10" - moveOffset = new Point(-drawableContainerListBounds.Location.X + 10, -drawableContainerListBounds.Location.Y + 10); - } + moveOffset = isSameSurface ? new Point(-10, -10) : new Point(-drawableContainerListBounds.Location.X + 10, -drawableContainerListBounds.Location.Y + 10); } - } else { + } + else + { Rectangle moveContainerListBounds = drawableContainerListBounds; moveContainerListBounds.Offset(moveOffset); // check if the element is inside - if (!Bounds.Contains(moveContainerListBounds)) { + if (!Bounds.Contains(moveContainerListBounds)) + { // Easy fix for same surface - if (isSameSurface) { + if (isSameSurface) + { moveOffset = new Point(-10, -10); - } else { + } + else + { // For different surface, which is most likely smaller int offsetX = 0; int offsetY = 0; - if (drawableContainerListBounds.Right > Bounds.Right) { + if (drawableContainerListBounds.Right > Bounds.Right) + { offsetX = Bounds.Right - drawableContainerListBounds.Right; // Correction for the correction - if (drawableContainerListBounds.Left + offsetX < 0) { + if (drawableContainerListBounds.Left + offsetX < 0) + { offsetX += Math.Abs(drawableContainerListBounds.Left + offsetX); } } - if (drawableContainerListBounds.Bottom > Bounds.Bottom) { + if (drawableContainerListBounds.Bottom > Bounds.Bottom) + { offsetY = Bounds.Bottom - drawableContainerListBounds.Bottom; // Correction for the correction - if (drawableContainerListBounds.Top + offsetY < 0) { + if (drawableContainerListBounds.Top + offsetY < 0) + { offsetY += Math.Abs(drawableContainerListBounds.Top + offsetY); } } @@ -1489,11 +1813,24 @@ namespace Greenshot.Drawing { DeselectAllElements(); SelectElements(dcs); } - } else if (ClipboardHelper.ContainsImage(clipboard)) { + } + else if (ClipboardHelper.ContainsImage(clipboard)) + { int x = 10; int y = 10; - foreach (Image clipboardImage in ClipboardHelper.GetImages(clipboard)) { - if (clipboardImage != null) { + + // FEATURE-995: Added a check for the current mouse cursor location, to paste the image on that location. + var mousePositionOnControl = PointToClient(MousePosition); + if (ClientRectangle.Contains(mousePositionOnControl)) + { + x = mousePositionOnControl.X; + y = mousePositionOnControl.Y; + } + + foreach (Image clipboardImage in ClipboardHelper.GetImages(clipboard)) + { + if (clipboardImage != null) + { DeselectAllElements(); IImageContainer container = AddImageContainer(clipboardImage as Bitmap, x, y); SelectElement(container); @@ -1502,9 +1839,12 @@ namespace Greenshot.Drawing { y += 10; } } - } else if (ClipboardHelper.ContainsText(clipboard)) { + } + else if (ClipboardHelper.ContainsText(clipboard)) + { string text = ClipboardHelper.GetText(clipboard); - if (text != null) { + if (text != null) + { DeselectAllElements(); ITextContainer textContainer = AddTextContainer(text, HorizontalAlignment.Center, VerticalAlignment.CENTER, FontFamily.GenericSansSerif, 12f, false, false, false, 2, Color.Black, Color.Transparent); @@ -1512,80 +1852,105 @@ namespace Greenshot.Drawing { } } } - + /// /// Duplicate all the selecteded elements /// - public void DuplicateSelectedElements() { + public void DuplicateSelectedElements() + { LOG.DebugFormat("Duplicating {0} selected elements", selectedElements.Count); - DrawableContainerList dcs = selectedElements.Clone(); + IDrawableContainerList dcs = selectedElements.Clone(); dcs.Parent = this; - dcs.MoveBy(10,10); + dcs.MoveBy(10, 10); AddElements(dcs); DeselectAllElements(); SelectElements(dcs); } - + /// /// Deselect the specified element /// - /// - public void DeselectElement(IDrawableContainer container) { - container.HideGrippers(); + /// IDrawableContainerList + /// false to skip event generation + public void DeselectElement(IDrawableContainer container, bool generateEvents = true) + { container.Selected = false; selectedElements.Remove(container); FieldAggregator.UnbindElement(container); - if (_movingElementChanged != null) { - SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs(); - eventArgs.Elements = selectedElements; + if (generateEvents && _movingElementChanged != null) + { + var eventArgs = new SurfaceElementEventArgs {Elements = selectedElements}; _movingElementChanged(this, eventArgs); } } + /// + /// Deselect the specified elements + /// + /// IDrawableContainerList + public void DeselectElements(IDrawableContainerList elements) + { + if (elements.Count == 0) + { + return; + } + while (elements.Count > 0) + { + var element = elements[0]; + DeselectElement(element, false); + } + if (_movingElementChanged != null) + { + SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs + { + Elements = selectedElements + }; + _movingElementChanged(this, eventArgs); + } + Invalidate(); + } + /// /// Deselect all the selected elements /// - public void DeselectAllElements() { - if (HasSelectedElements) { - while(selectedElements.Count > 0) { - IDrawableContainer element = selectedElements[0]; - element.Invalidate(); - element.HideGrippers(); - element.Selected = false; - selectedElements.Remove(element); - FieldAggregator.UnbindElement(element); - } - if (_movingElementChanged != null) { - SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs(); - eventArgs.Elements = selectedElements; - _movingElementChanged(this, eventArgs); - } - } + public void DeselectAllElements() + { + DeselectElements(selectedElements); } /// /// Select the supplied element /// /// - public void SelectElement(IDrawableContainer container) { - if (!selectedElements.Contains(container)) { + /// false to skip invalidation + /// false to skip event generation + public void SelectElement(IDrawableContainer container, bool invalidate = true, bool generateEvents = true) + { + if (!selectedElements.Contains(container)) + { selectedElements.Add(container); - container.ShowGrippers(); container.Selected = true; FieldAggregator.BindElement(container); - if (_movingElementChanged != null) { - SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs(); - eventArgs.Elements = selectedElements; + if (generateEvents && _movingElementChanged != null) + { + SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs + { + Elements = selectedElements + }; _movingElementChanged(this, eventArgs); } - container.Invalidate(); + if (invalidate) + { + container.Invalidate(); + } } } /// /// Select all elements, this is called when Ctrl+A is pressed /// - public void SelectAllElements() { + public void SelectAllElements() + { SelectElements(_elements); } @@ -1593,10 +1958,21 @@ namespace Greenshot.Drawing { /// Select the supplied elements /// /// - public void SelectElements(DrawableContainerList elements) { - foreach(DrawableContainer element in elements) { - SelectElement(element); + public void SelectElements(IDrawableContainerList elements) + { + SuspendLayout(); + foreach (var drawableContainer in elements) + { + var element = (DrawableContainer) drawableContainer; + SelectElement(element, false, false); } + if (_movingElementChanged != null) + { + SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs {Elements = selectedElements}; + _movingElementChanged(this, eventArgs); + } + ResumeLayout(); + Invalidate(); } /// @@ -1604,13 +1980,16 @@ namespace Greenshot.Drawing { /// /// Keys /// false if no keys were processed - public bool ProcessCmdKey(Keys k) { - if (selectedElements.Count > 0) { + public bool ProcessCmdKey(Keys k) + { + if (selectedElements.Count > 0) + { bool shiftModifier = (ModifierKeys & Keys.Shift) == Keys.Shift; int px = shiftModifier ? 10 : 1; Point moveBy = Point.Empty; - - switch (k) { + + switch (k) + { case Keys.Left: case Keys.Left | Keys.Shift: moveBy = new Point(-px, 0); @@ -1651,7 +2030,8 @@ namespace Greenshot.Drawing { default: return false; } - if (!Point.Empty.Equals(moveBy)) { + if (!Point.Empty.Equals(moveBy)) + { selectedElements.MakeBoundsChangeUndoable(true); selectedElements.MoveBy(moveBy.X, moveBy.Y); } @@ -1663,69 +2043,69 @@ namespace Greenshot.Drawing { /// /// Property for accessing the elements on the surface /// - public DrawableContainerList Elements { - get { - return _elements; - } - } + public IDrawableContainerList Elements => _elements; /// /// pulls selected elements up one level in hierarchy /// - public void PullElementsUp() { + public void PullElementsUp() + { _elements.PullElementsUp(selectedElements); _elements.Invalidate(); } - + /// /// pushes selected elements up to top in hierarchy /// - public void PullElementsToTop() { + public void PullElementsToTop() + { _elements.PullElementsToTop(selectedElements); _elements.Invalidate(); } - + /// /// pushes selected elements down one level in hierarchy /// - public void PushElementsDown() { + public void PushElementsDown() + { _elements.PushElementsDown(selectedElements); _elements.Invalidate(); } - + /// /// pushes selected elements down to bottom in hierarchy /// - public void PushElementsToBottom() { + public void PushElementsToBottom() + { _elements.PushElementsToBottom(selectedElements); _elements.Invalidate(); } - + /// /// indicates whether the selected elements could be pulled up in hierarchy /// /// true if selected elements could be pulled up, false otherwise - public bool CanPullSelectionUp() { + public bool CanPullSelectionUp() + { return _elements.CanPullUp(selectedElements); } - + /// /// indicates whether the selected elements could be pushed down in hierarchy /// /// true if selected elements could be pushed down, false otherwise - public bool CanPushSelectionDown() { + public bool CanPushSelectionDown() + { return _elements.CanPushDown(selectedElements); } - - public void ElementPropertyChanged(object sender, PropertyChangedEventArgs e) { - //Invalidate(); - } - - public void element_FieldChanged(object sender, FieldChangedEventArgs e) { + + public void element_FieldChanged(object sender, FieldChangedEventArgs e) + { selectedElements.HandleFieldChangedEvent(sender, e); } - public bool IsOnSurface(IDrawableContainer container) { + public bool IsOnSurface(IDrawableContainer container) + { return _elements.Contains(container); } } diff --git a/Greenshot/Drawing/TextContainer.cs b/Greenshot/Drawing/TextContainer.cs index 110c40775..2761bfe9c 100644 --- a/Greenshot/Drawing/TextContainer.cs +++ b/Greenshot/Drawing/TextContainer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,32 +22,33 @@ using Greenshot.Drawing.Fields; using Greenshot.Helpers; using Greenshot.Memento; -using Greenshot.Plugin; using Greenshot.Plugin.Drawing; +using GreenshotPlugin.Interfaces.Drawing; using System; using System.ComponentModel; +using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; using System.Runtime.Serialization; using System.Windows.Forms; -namespace Greenshot.Drawing { +namespace Greenshot.Drawing +{ /// /// Represents a textbox (extends RectangleContainer for border/background support /// - [Serializable] - public class TextContainer : RectangleContainer, ITextContainer { + [Serializable] + public class TextContainer : RectangleContainer, ITextContainer + { // If makeUndoable is true the next text-change will make the change undoable. // This is set to true AFTER the first change is made, as there is already a "add element" on the undo stack + // Although the name is wrong, we can't change it due to file serialization + // ReSharper disable once InconsistentNaming private bool makeUndoable; [NonSerialized] private Font _font; - public Font Font { - get { - return _font; - } - } + public Font Font => _font; [NonSerialized] private TextBox _textBox; @@ -56,37 +57,44 @@ namespace Greenshot.Drawing { /// The StringFormat object is not serializable!! /// [NonSerialized] - StringFormat _stringFormat = new StringFormat(); - public StringFormat StringFormat { - get { - return _stringFormat; - } - } + private StringFormat _stringFormat = new StringFormat(); + + public StringFormat StringFormat => _stringFormat; + + // Although the name is wrong, we can't change it due to file serialization + // ReSharper disable once InconsistentNaming private string text; // there is a binding on the following property! - public string Text { + public string Text + { get { return text; } - set { + set + { ChangeText(value, true); } } - - internal void ChangeText(string newText, bool allowUndoable) { - if ((text == null && newText != null) || !text.Equals(newText)) { - if (makeUndoable && allowUndoable) { + + internal void ChangeText(string newText, bool allowUndoable) + { + if ((text == null && newText != null) || !string.Equals(text, newText)) + { + if (makeUndoable && allowUndoable) + { makeUndoable = false; _parent.MakeUndoable(new TextChangeMemento(this), false); } - text = newText; - OnPropertyChanged("Text"); + text = newText; + OnPropertyChanged("Text"); } } - - public TextContainer(Surface parent) : base(parent) { + + public TextContainer(Surface parent) : base(parent) + { Init(); } - protected override void InitializeFields() { + protected override void InitializeFields() + { AddField(GetType(), FieldType.LINE_THICKNESS, 2); AddField(GetType(), FieldType.LINE_COLOR, Color.Red); AddField(GetType(), FieldType.SHADOW, true); @@ -98,33 +106,46 @@ namespace Greenshot.Drawing { AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, StringAlignment.Center); AddField(GetType(), FieldType.TEXT_VERTICAL_ALIGNMENT, StringAlignment.Center); } - - [OnDeserialized] - private void OnDeserialized(StreamingContext context) { + + /// + /// Do some logic to make sure all field are initiated correctly + /// + /// StreamingContext + protected override void OnDeserialized(StreamingContext streamingContext) + { + base.OnDeserialized(streamingContext); Init(); } - protected override void Dispose(bool disposing) { - if (disposing) { - if (_font != null) { + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (_font != null) + { _font.Dispose(); _font = null; } - if (_stringFormat != null) { + if (_stringFormat != null) + { _stringFormat.Dispose(); _stringFormat = null; } - if (_textBox != null) { + if (_textBox != null) + { _textBox.Dispose(); _textBox = null; } } base.Dispose(disposing); } - - private void Init() { - _stringFormat = new StringFormat(); - _stringFormat.Trimming = StringTrimming.EllipsisWord; + + private void Init() + { + _stringFormat = new StringFormat + { + Trimming = StringTrimming.EllipsisWord + }; CreateTextBox(); @@ -136,82 +157,120 @@ namespace Greenshot.Drawing { } - public override void Invalidate() { + public override void Invalidate() + { base.Invalidate(); - if (_textBox != null && _textBox.Visible) { + if (_textBox != null && _textBox.Visible) + { _textBox.Invalidate(); } } - - public void FitToText() { + + public void FitToText() + { Size textSize = TextRenderer.MeasureText(text, _font); int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); Width = textSize.Width + lineThickness; Height = textSize.Height + lineThickness; } - void TextContainer_PropertyChanged(object sender, PropertyChangedEventArgs e) { - if (_textBox.Visible) { + private void TextContainer_PropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (_textBox == null) + { + return; + } + + if (_textBox.Visible) + { _textBox.Invalidate(); } UpdateTextBoxPosition(); UpdateTextBoxFormat(); - if (e.PropertyName.Equals("Selected")) { - if (!Selected && _textBox.Visible) { + if (e.PropertyName.Equals("Selected")) + { + if (!Selected && _textBox.Visible) + { HideTextBox(); - } else if (Selected && Status == EditStatus.DRAWING) { + } + else if (Selected && Status == EditStatus.DRAWING) + { ShowTextBox(); - } else if (Selected && Status == EditStatus.IDLE && _textBox.Visible) { + } + else if (_parent != null && Selected && Status == EditStatus.IDLE && _textBox.Visible) + { // Fix (workaround) for BUG-1698 _parent.KeysLocked = true; } } - if (_textBox.Visible) { + if (_textBox.Visible) + { _textBox.Invalidate(); } } - - void TextContainer_FieldChanged(object sender, FieldChangedEventArgs e) { - if (_textBox.Visible) { + + private void TextContainer_FieldChanged(object sender, FieldChangedEventArgs e) + { + if (_textBox == null) + { + return; + } + if (_textBox.Visible) + { _textBox.Invalidate(); } // Only dispose the font, and re-create it, when a font field has changed. - if (e.Field.FieldType.Name.StartsWith("FONT")) { - _font.Dispose(); - _font = null; + if (e.Field.FieldType.Name.StartsWith("FONT")) + { + if (_font != null) + { + _font.Dispose(); + _font = null; + } UpdateFormat(); - } else { + } + else + { UpdateAlignment(); } UpdateTextBoxFormat(); - - if (_textBox.Visible) { + + if (_textBox.Visible) + { _textBox.Invalidate(); } } - - public override void OnDoubleClick() { + + public override void OnDoubleClick() + { ShowTextBox(); } - - private void CreateTextBox() { - _textBox = new TextBox(); - _textBox.ImeMode = ImeMode.On; - _textBox.Multiline = true; - _textBox.AcceptsTab = true; - _textBox.AcceptsReturn = true; + private void CreateTextBox() + { + _textBox = new TextBox + { + ImeMode = ImeMode.On, + Multiline = true, + AcceptsTab = true, + AcceptsReturn = true, + BorderStyle = BorderStyle.None, + Visible = false + }; + _textBox.DataBindings.Add("Text", this, "Text", false, DataSourceUpdateMode.OnPropertyChanged); _textBox.LostFocus += textBox_LostFocus; _textBox.KeyDown += textBox_KeyDown; - _textBox.BorderStyle = BorderStyle.None; - _textBox.Visible = false; } - private void ShowTextBox() { - _parent.KeysLocked = true; - _parent.Controls.Add(_textBox); + private void ShowTextBox() + { + if (_parent != null) + { + _parent.KeysLocked = true; + _parent.Controls.Add(_textBox); + } EnsureTextBoxContrast(); _textBox.Show(); _textBox.Focus(); @@ -220,16 +279,21 @@ namespace Greenshot.Drawing { /// /// Makes textbox background dark if text color is very bright /// - private void EnsureTextBoxContrast() { + private void EnsureTextBoxContrast() + { Color lc = GetFieldValueAsColor(FieldType.LINE_COLOR); - if (lc.R > 203 && lc.G > 203 && lc.B > 203) { + if (lc.R > 203 && lc.G > 203 && lc.B > 203) + { _textBox.BackColor = Color.FromArgb(51, 51, 51); - } else { + } + else + { _textBox.BackColor = Color.White; } } - - private void HideTextBox() { + + private void HideTextBox() + { _parent.Focus(); _textBox.Hide(); _parent.KeysLocked = false; @@ -240,7 +304,8 @@ namespace Greenshot.Drawing { /// Make sure the size of the font is scaled /// /// - public override void Transform(Matrix matrix) { + public override void Transform(Matrix matrix) + { Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); int pixelsBefore = rect.Width * rect.Height; @@ -257,58 +322,98 @@ namespace Greenshot.Drawing { UpdateFormat(); } + private Font CreateFont(string fontFamilyName, bool fontBold, bool fontItalic, float fontSize) + { + FontStyle fontStyle = FontStyle.Regular; + + bool hasStyle = false; + using (var fontFamily = new FontFamily(fontFamilyName)) + { + bool boldAvailable = fontFamily.IsStyleAvailable(FontStyle.Bold); + if (fontBold && boldAvailable) + { + fontStyle |= FontStyle.Bold; + hasStyle = true; + } + + bool italicAvailable = fontFamily.IsStyleAvailable(FontStyle.Italic); + if (fontItalic && italicAvailable) + { + fontStyle |= FontStyle.Italic; + hasStyle = true; + } + + if (!hasStyle) + { + bool regularAvailable = fontFamily.IsStyleAvailable(FontStyle.Regular); + if (regularAvailable) + { + fontStyle = FontStyle.Regular; + } + else + { + if (boldAvailable) + { + fontStyle = FontStyle.Bold; + } + else if (italicAvailable) + { + fontStyle = FontStyle.Italic; + } + } + } + return new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel); + } + } + /// /// Generate the Font-Formal so we can draw correctly /// - protected void UpdateFormat() { + protected void UpdateFormat() + { + if (_textBox == null) + { + return; + } string fontFamily = GetFieldValueAsString(FieldType.FONT_FAMILY); bool fontBold = GetFieldValueAsBool(FieldType.FONT_BOLD); bool fontItalic = GetFieldValueAsBool(FieldType.FONT_ITALIC); float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE); - try { - FontStyle fs = FontStyle.Regular; - - bool hasStyle = false; - using(FontFamily fam = new FontFamily(fontFamily)) { - bool boldAvailable = fam.IsStyleAvailable(FontStyle.Bold); - if (fontBold && boldAvailable) { - fs |= FontStyle.Bold; - hasStyle = true; - } - - bool italicAvailable = fam.IsStyleAvailable(FontStyle.Italic); - if (fontItalic && italicAvailable) { - fs |= FontStyle.Italic; - hasStyle = true; - } - - if (!hasStyle) { - bool regularAvailable = fam.IsStyleAvailable(FontStyle.Regular); - if (regularAvailable) { - fs = FontStyle.Regular; - } else { - if (boldAvailable) { - fs = FontStyle.Bold; - } else if(italicAvailable) { - fs = FontStyle.Italic; - } - } - } - _font = new Font(fam, fontSize, fs, GraphicsUnit.Pixel); + try + { + var newFont = CreateFont(fontFamily, fontBold, fontItalic, fontSize); + _font?.Dispose(); + _font = newFont; + _textBox.Font = _font; + } + catch (Exception ex) + { + // Problem, try again with the default + try + { + fontFamily = FontFamily.GenericSansSerif.Name; + SetFieldValue(FieldType.FONT_FAMILY, fontFamily); + var newFont = CreateFont(fontFamily, fontBold, fontItalic, fontSize); + _font?.Dispose(); + _font = newFont; _textBox.Font = _font; } - } catch (Exception ex) { - ex.Data.Add("fontFamily", fontFamily); - ex.Data.Add("fontBold", fontBold); - ex.Data.Add("fontItalic", fontItalic); - ex.Data.Add("fontSize", fontSize); - throw; + catch (Exception) + { + // When this happens... the PC is broken + ex.Data.Add("fontFamilyName", fontFamily); + ex.Data.Add("fontBold", fontBold); + ex.Data.Add("fontItalic", fontItalic); + ex.Data.Add("fontSize", fontSize); + throw ex; + } } - + UpdateAlignment(); } - private void UpdateAlignment() { + private void UpdateAlignment() + { _stringFormat.Alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT); _stringFormat.LineAlignment = (StringAlignment)GetFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT); } @@ -317,36 +422,43 @@ namespace Greenshot.Drawing { /// This will create the textbox exactly to the inner size of the element /// is a bit of a hack, but for now it seems to work... /// - private void UpdateTextBoxPosition() { + private void UpdateTextBoxPosition() + { int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); int lineWidth = (int)Math.Floor(lineThickness / 2d); - int correction = (lineThickness +1 ) % 2; - if (lineThickness <= 1) { + int correction = (lineThickness + 1) % 2; + if (lineThickness <= 1) + { lineWidth = 1; correction = -1; } Rectangle absRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); _textBox.Left = absRectangle.Left + lineWidth; _textBox.Top = absRectangle.Top + lineWidth; - if (lineThickness <= 1) { + if (lineThickness <= 1) + { lineWidth = 0; } - _textBox.Width = absRectangle.Width - (2 * lineWidth) + correction; - _textBox.Height = absRectangle.Height - (2 * lineWidth) + correction; + _textBox.Width = absRectangle.Width - 2 * lineWidth + correction; + _textBox.Height = absRectangle.Height - 2 * lineWidth + correction; } - public override void ApplyBounds(RectangleF newBounds) { + public override void ApplyBounds(RectangleF newBounds) + { base.ApplyBounds(newBounds); UpdateTextBoxPosition(); } - private void UpdateTextBoxFormat() { - if (_textBox == null) { + private void UpdateTextBoxFormat() + { + if (_textBox == null) + { return; } - StringAlignment alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT); - switch (alignment) { + var alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT); + switch (alignment) + { case StringAlignment.Near: _textBox.TextAlign = HorizontalAlignment.Left; break; @@ -358,25 +470,29 @@ namespace Greenshot.Drawing { break; } - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); + var lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); _textBox.ForeColor = lineColor; } - - void textBox_KeyDown(object sender, KeyEventArgs e) { + + private void textBox_KeyDown(object sender, KeyEventArgs e) + { // ESC and Enter/Return (w/o Shift) hide text editor - if(e.KeyCode == Keys.Escape || ((e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) && e.Modifiers == Keys.None)) { + if (e.KeyCode == Keys.Escape || ((e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) && e.Modifiers == Keys.None)) + { HideTextBox(); e.SuppressKeyPress = true; } } - void textBox_LostFocus(object sender, EventArgs e) { + private void textBox_LostFocus(object sender, EventArgs e) + { // next change will be made undoable makeUndoable = true; HideTextBox(); } - - public override void Draw(Graphics graphics, RenderMode rm) { + + public override void Draw(Graphics graphics, RenderMode rm) + { base.Draw(graphics, rm); graphics.SmoothingMode = SmoothingMode.HighQuality; @@ -386,11 +502,13 @@ namespace Greenshot.Drawing { graphics.TextRenderingHint = TextRenderingHint.SystemDefault; Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - if (Selected && rm == RenderMode.EDIT) { + if (Selected && rm == RenderMode.EDIT) + { DrawSelectionBorder(graphics, rect); } - - if (text == null || text.Length == 0 ) { + + if (string.IsNullOrEmpty(text)) + { return; } @@ -411,24 +529,38 @@ namespace Greenshot.Drawing { /// /// /// + /// /// /// /// - public static void DrawText(Graphics graphics, Rectangle drawingRectange, int lineThickness, Color fontColor, bool drawShadow, StringFormat stringFormat, string text, Font font) { - int textOffset = (lineThickness > 0) ? (int)Math.Ceiling(lineThickness / 2d) : 0; + public static void DrawText(Graphics graphics, Rectangle drawingRectange, int lineThickness, Color fontColor, bool drawShadow, StringFormat stringFormat, string text, Font font) + { +#if DEBUG + Debug.Assert(font != null); +#else + if (font == null) + { + return; + } +#endif + int textOffset = lineThickness > 0 ? (int)Math.Ceiling(lineThickness / 2d) : 0; // draw shadow before anything else - if (drawShadow) { + if (drawShadow) + { int basealpha = 100; int alpha = basealpha; int steps = 5; int currentStep = 1; - while (currentStep <= steps) { + while (currentStep <= steps) + { int offset = currentStep; Rectangle shadowRect = GuiRectangle.GetGuiRectangle(drawingRectange.Left + offset, drawingRectange.Top + offset, drawingRectange.Width, drawingRectange.Height); - if (lineThickness > 0) { + if (lineThickness > 0) + { shadowRect.Inflate(-textOffset, -textOffset); } - using (Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100))) { + using (Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100))) + { graphics.DrawString(text, font, fontBrush, shadowRect, stringFormat); currentStep++; alpha = alpha - basealpha / steps; @@ -436,19 +568,25 @@ namespace Greenshot.Drawing { } } - if (lineThickness > 0) { + if (lineThickness > 0) + { drawingRectange.Inflate(-textOffset, -textOffset); } - using (Brush fontBrush = new SolidBrush(fontColor)) { - if (stringFormat != null) { + using (Brush fontBrush = new SolidBrush(fontColor)) + { + if (stringFormat != null) + { graphics.DrawString(text, font, fontBrush, drawingRectange, stringFormat); - } else { + } + else + { graphics.DrawString(text, font, fontBrush, drawingRectange); } } } - public override bool ClickableAt(int x, int y) { + public override bool ClickableAt(int x, int y) + { Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); r.Inflate(5, 5); return r.Contains(x, y); diff --git a/Greenshot/Forms/AboutForm.Designer.cs b/Greenshot/Forms/AboutForm.Designer.cs index 342d6d734..66c86ac20 100644 --- a/Greenshot/Forms/AboutForm.Designer.cs +++ b/Greenshot/Forms/AboutForm.Designer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,8 @@ * along with this program. If not, see . */ +using System.Reflection; + namespace Greenshot { partial class AboutForm { /// @@ -104,7 +106,7 @@ namespace Greenshot { this.linkLblHost.Size = new System.Drawing.Size(465, 23); this.linkLblHost.TabIndex = 6; this.linkLblHost.TabStop = true; - this.linkLblHost.Text = "http://sourceforge.net/projects/greenshot/"; + this.linkLblHost.Text = "https://github.com/greenshot/greenshot"; this.linkLblHost.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked); // // linkLblBugs @@ -114,7 +116,7 @@ namespace Greenshot { this.linkLblBugs.Size = new System.Drawing.Size(465, 23); this.linkLblBugs.TabIndex = 8; this.linkLblBugs.TabStop = true; - this.linkLblBugs.Text = "http://getgreenshot.org/tickets/"; + this.linkLblBugs.Text = "http://getgreenshot.org/tickets/?version=" + Assembly.GetEntryAssembly().GetName().Version; this.linkLblBugs.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked); // // lblBugs @@ -132,7 +134,7 @@ namespace Greenshot { this.linkLblDonations.Size = new System.Drawing.Size(465, 23); this.linkLblDonations.TabIndex = 10; this.linkLblDonations.TabStop = true; - this.linkLblDonations.Text = "http://getgreenshot.org/support/"; + this.linkLblDonations.Text = "http://getgreenshot.org/support/?version=" + Assembly.GetEntryAssembly().GetName().Version; this.linkLblDonations.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.LinkLabelClicked); // // lblDonations diff --git a/Greenshot/Forms/AboutForm.cs b/Greenshot/Forms/AboutForm.cs index 64934dea0..68f2d48a5 100644 --- a/Greenshot/Forms/AboutForm.cs +++ b/Greenshot/Forms/AboutForm.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool -* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom +* Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ -* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ +* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -41,21 +41,21 @@ namespace Greenshot { /// The about form /// public partial class AboutForm : AnimatingBaseForm { - private static ILog LOG = LogManager.GetLogger(typeof(AboutForm)); - private Bitmap gBitmap; - private ColorAnimator backgroundAnimation; - private List pixels = new List(); - private List colorFlow = new List(); - private List pixelColors = new List(); - private Random rand = new Random(); - private readonly Color backColor = Color.FromArgb(61, 61, 61); - private readonly Color pixelColor = Color.FromArgb(138, 255, 0); + private static readonly ILog LOG = LogManager.GetLogger(typeof(AboutForm)); + private Bitmap _bitmap; + private readonly ColorAnimator _backgroundAnimation; + private readonly IList _pixels = new List(); + private readonly IList _colorFlow = new List(); + private readonly IList _pixelColors = new List(); + private readonly Random _rand = new Random(); + private readonly Color _backColor = Color.FromArgb(61, 61, 61); + private readonly Color _pixelColor = Color.FromArgb(138, 255, 0); // Variables used for the color-cycle - private int waitFrames = 0; - private int colorIndex = 0; - private int scrollCount = 0; - private bool hasAnimationsLeft; + private int _waitFrames; + private int _colorIndex; + private int _scrollCount; + private bool _hasAnimationsLeft; // Variables are used to define the location of the dots private const int w = 13; @@ -70,7 +70,7 @@ namespace Greenshot { /// /// The location of every dot in the "G" /// - private List gSpots = new List() { + private readonly List gSpots = new List() { // Top row new Point(p2, p1), // 0 new Point(p3, p1), // 1 @@ -116,15 +116,15 @@ namespace Greenshot { // 18 19 20 21 22 23 // The order in which we draw the dots & flow the collors. - List flowOrder = new List() { 4, 3, 2, 1, 0, 5, 6, 7, 8, 9, 10, 14, 15, 18, 19, 20, 21, 22, 23, 16, 17, 13, 12, 11 }; + private readonly List flowOrder = new List() { 4, 3, 2, 1, 0, 5, 6, 7, 8, 9, 10, 14, 15, 18, 19, 20, 21, 22, 23, 16, 17, 13, 12, 11 }; /// /// Cleanup all the allocated resources /// private void Cleanup(object sender, EventArgs e) { - if (gBitmap != null) { - gBitmap.Dispose(); - gBitmap = null; + if (_bitmap != null) { + _bitmap.Dispose(); + _bitmap = null; } } @@ -144,22 +144,22 @@ namespace Greenshot { InitializeComponent(); // Only use double-buffering when we are NOT in a Terminal Server session - DoubleBuffered = !isTerminalServerSession; + DoubleBuffered = !IsTerminalServerSession; // Use the self drawn image, first we create the background to be the backcolor (as we animate from this) - gBitmap = ImageHelper.CreateEmpty(90, 90, PixelFormat.Format24bppRgb, BackColor, 96, 96); - pictureBox1.Image = gBitmap; + _bitmap = ImageHelper.CreateEmpty(90, 90, PixelFormat.Format24bppRgb, BackColor, 96, 96); + pictureBox1.Image = _bitmap; Version v = Assembly.GetExecutingAssembly().GetName().Version; // Format is like this: AssemblyVersion("Major.Minor.Build.Revision")] - lblTitle.Text = "Greenshot " + v.Major + "." + v.Minor + "." + v.Build + " Build " + v.Revision + (IniConfig.IsPortable ? " Portable" : "") + (" (" + OSInfo.Bits + " bit)"); + lblTitle.Text = "Greenshot " + v.Major + "." + v.Minor + "." + v.Build + " Build " + v.Revision + (IniConfig.IsPortable ? " Portable" : "") + (" (" + OsInfo.Bits) + " bit)"; //Random rand = new Random(); // Number of frames the pixel animation takes int frames = FramesForMillis(2000); // The number of frames the color-cycle waits before it starts - waitFrames = FramesForMillis(6000); + _waitFrames = FramesForMillis(6000); // Every pixel is created after pixelWaitFrames frames, which is increased in the loop. int pixelWaitFrames = FramesForMillis(2000); @@ -174,7 +174,7 @@ namespace Greenshot { int offset = (w - 2) / 2; // If the optimize for Terminal Server is set we make the animation without much ado - if (isTerminalServerSession) { + if (IsTerminalServerSession) { // No animation pixelAnimation = new RectangleAnimator(new Rectangle(gSpot.X, gSpot.Y, w - 2, w - 2), new Rectangle(gSpot.X, gSpot.Y, w - 2, w - 2), 1, EasingType.Cubic, EasingMode.EaseIn); } else { @@ -187,23 +187,23 @@ namespace Greenshot { // Increase the wait frames pixelWaitFrames += FramesForMillis(100); // Add to the list of to be animated pixels - pixels.Add(pixelAnimation); + _pixels.Add(pixelAnimation); // Add a color to the list for this pixel. - pixelColors.Add(pixelColor); + _pixelColors.Add(_pixelColor); } // Make sure the frame "loop" knows we have to animate - hasAnimationsLeft = true; + _hasAnimationsLeft = true; // Pixel Color cycle colors, here we use a pre-animated loop which stores the values. - ColorAnimator pixelColorAnimator = new ColorAnimator(pixelColor, Color.FromArgb(255, 255, 255), 6, EasingType.Quadratic, EasingMode.EaseIn); - pixelColorAnimator.QueueDestinationLeg(pixelColor, 6, EasingType.Quadratic, EasingMode.EaseOut); + ColorAnimator pixelColorAnimator = new ColorAnimator(_pixelColor, Color.FromArgb(255, 255, 255), 6, EasingType.Quadratic, EasingMode.EaseIn); + pixelColorAnimator.QueueDestinationLeg(_pixelColor, 6, EasingType.Quadratic, EasingMode.EaseOut); do { - colorFlow.Add(pixelColorAnimator.Current); + _colorFlow.Add(pixelColorAnimator.Current); pixelColorAnimator.Next(); - } while (pixelColorAnimator.hasNext); + } while (pixelColorAnimator.HasNext); // color animation for the background - backgroundAnimation = new ColorAnimator(BackColor, backColor, FramesForMillis(5000), EasingType.Linear, EasingMode.EaseIn); + _backgroundAnimation = new ColorAnimator(BackColor, _backColor, FramesForMillis(5000), EasingType.Linear, EasingMode.EaseIn); } /// @@ -211,7 +211,7 @@ namespace Greenshot { /// /// /// - void LinkLabelClicked(object sender, LinkLabelLinkClickedEventArgs e) { + private void LinkLabelClicked(object sender, LinkLabelLinkClickedEventArgs e) { LinkLabel linkLabel = sender as LinkLabel; if (linkLabel != null) { try { @@ -227,63 +227,63 @@ namespace Greenshot { /// Called from the AnimatingForm, for every frame /// protected override void Animate() { - if (gBitmap == null) { + if (_bitmap == null) { return; } - if (!isTerminalServerSession) { + if (!IsTerminalServerSession) { // Color cycle - if (waitFrames != 0) { - waitFrames--; + if (_waitFrames != 0) { + _waitFrames--; // Check if there is something else to do, if not we return so we don't occupy the CPU - if (!hasAnimationsLeft) { + if (!_hasAnimationsLeft) { return; } - } else if (scrollCount < (pixelColors.Count + colorFlow.Count)) { + } else if (_scrollCount < _pixelColors.Count + _colorFlow.Count) { // Scroll colors, the scrollCount is the amount of pixels + the amount of colors to cycle. - for (int index = pixelColors.Count - 1; index > 0; index--) { - pixelColors[index] = pixelColors[index - 1]; + for (int index = _pixelColors.Count - 1; index > 0; index--) { + _pixelColors[index] = _pixelColors[index - 1]; } // Keep adding from the colors to cycle until there is nothing left - if (colorIndex < colorFlow.Count) { - pixelColors[0] = colorFlow[colorIndex++]; + if (_colorIndex < _colorFlow.Count) { + _pixelColors[0] = _colorFlow[_colorIndex++]; } - scrollCount++; + _scrollCount++; } else { // Reset values, wait X time for the next one - waitFrames = FramesForMillis(3000 + rand.Next(35000)); - colorIndex = 0; - scrollCount = 0; + _waitFrames = FramesForMillis(3000 + _rand.Next(35000)); + _colorIndex = 0; + _scrollCount = 0; // Check if there is something else to do, if not we return so we don't occupy the CPU - if (!hasAnimationsLeft) { + if (!_hasAnimationsLeft) { return; } } - } else if (!hasAnimationsLeft) { + } else if (!_hasAnimationsLeft) { return; } // Draw the "G" - using (Graphics graphics = Graphics.FromImage(gBitmap)) { + using (Graphics graphics = Graphics.FromImage(_bitmap)) { graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBilinear; graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - graphics.Clear(backgroundAnimation.Next()); + graphics.Clear(_backgroundAnimation.Next()); graphics.TranslateTransform(2, -2); graphics.RotateTransform(20); - using (SolidBrush brush = new SolidBrush(pixelColor)) { + using (SolidBrush brush = new SolidBrush(_pixelColor)) { int index = 0; // We asume there is nothing to animate in the next Animate loop - hasAnimationsLeft = false; + _hasAnimationsLeft = false; // Pixels of the G - foreach (RectangleAnimator pixel in pixels) { - brush.Color = pixelColors[index++]; + foreach (RectangleAnimator pixel in _pixels) { + brush.Color = _pixelColors[index++]; graphics.FillEllipse(brush, pixel.Current); // If a pixel still has frames left, the hasAnimationsLeft will be true - hasAnimationsLeft = hasAnimationsLeft | pixel.hasNext; + _hasAnimationsLeft = _hasAnimationsLeft | pixel.HasNext; pixel.Next(); } } diff --git a/Greenshot/Forms/AnimatingBaseForm.cs b/Greenshot/Forms/AnimatingBaseForm.cs index 36d85c2b3..c97780417 100644 --- a/Greenshot/Forms/AnimatingBaseForm.cs +++ b/Greenshot/Forms/AnimatingBaseForm.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Forms/BaseForm.cs b/Greenshot/Forms/BaseForm.cs index 59293cd1c..532f42bc9 100644 --- a/Greenshot/Forms/BaseForm.cs +++ b/Greenshot/Forms/BaseForm.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Forms/BugReportForm.Designer.cs b/Greenshot/Forms/BugReportForm.Designer.cs index f1c5147e0..48d06fdc1 100644 --- a/Greenshot/Forms/BugReportForm.Designer.cs +++ b/Greenshot/Forms/BugReportForm.Designer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Forms/BugReportForm.cs b/Greenshot/Forms/BugReportForm.cs index 2f6fb0247..9cf72b968 100644 --- a/Greenshot/Forms/BugReportForm.cs +++ b/Greenshot/Forms/BugReportForm.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,8 +37,8 @@ namespace Greenshot.Forms { public BugReportForm(string bugText) : this() { textBoxDescription.Text = bugText; } - - void LinkLblBugsLinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { + + private void LinkLblBugsLinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { openLink((LinkLabel)sender); } diff --git a/Greenshot/Forms/CaptureForm.Designer.cs b/Greenshot/Forms/CaptureForm.Designer.cs index 72deb4ffd..5ec1d8903 100644 --- a/Greenshot/Forms/CaptureForm.Designer.cs +++ b/Greenshot/Forms/CaptureForm.Designer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/Greenshot/Forms/CaptureForm.cs b/Greenshot/Forms/CaptureForm.cs index 528cd6515..7af509c03 100644 --- a/Greenshot/Forms/CaptureForm.cs +++ b/Greenshot/Forms/CaptureForm.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,10 +40,10 @@ namespace Greenshot.Forms { /// /// The capture form is used to select a part of the capture /// - public partial class CaptureForm : AnimatingForm { + public sealed partial class CaptureForm : AnimatingForm { private enum FixMode {None, Initiated, Horizontal, Vertical}; - private static readonly ILog LOG = LogManager.GetLogger(typeof(CaptureForm)); + private static readonly ILog Log = LogManager.GetLogger(typeof(CaptureForm)); private static readonly CoreConfiguration Conf = IniConfig.GetIniSection(); private static readonly Brush GreenOverlayBrush = new SolidBrush(Color.FromArgb(50, Color.MediumSeaGreen)); private static readonly Pen OverlayPen = new Pen(Color.FromArgb(50, Color.Black)); @@ -61,9 +61,9 @@ namespace Greenshot.Forms { private int _mX; private int _mY; private Point _mouseMovePos = Point.Empty; - private Point _cursorPos = Point.Empty; - private CaptureMode _captureMode = CaptureMode.None; - private readonly List _windows = new List(); + private Point _cursorPos; + private CaptureMode _captureMode; + private readonly List _windows; private WindowDetails _selectedCaptureWindow; private bool _mouseDown; private Rectangle _captureRect = Rectangle.Empty; @@ -73,34 +73,23 @@ namespace Greenshot.Forms { private RectangleAnimator _windowAnimator; private RectangleAnimator _zoomAnimator; private readonly bool _isZoomerTransparent = Conf.ZoomerOpacity < 1; - private bool _isCtrlPressed = false; + private bool _isCtrlPressed; + private bool _showDebugInfo; /// /// Property to access the selected capture rectangle /// - public Rectangle CaptureRectangle { - get { - return _captureRect; - } - } + public Rectangle CaptureRectangle => _captureRect; /// /// Property to access the used capture mode /// - public CaptureMode UsedCaptureMode { - get { - return _captureMode; - } - } + public CaptureMode UsedCaptureMode => _captureMode; /// /// Get the selected window /// - public WindowDetails SelectedCaptureWindow { - get { - return _selectedCaptureWindow; - } - } + public WindowDetails SelectedCaptureWindow => _selectedCaptureWindow; /// /// This should prevent childs to draw backgrounds @@ -108,19 +97,19 @@ namespace Greenshot.Forms { protected override CreateParams CreateParams { [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)] get { - CreateParams cp = base.CreateParams; - cp.ExStyle |= 0x02000000; - return cp; + CreateParams createParams = base.CreateParams; + createParams.ExStyle |= 0x02000000; + return createParams; } } private void ClosedHandler(object sender, EventArgs e) { _currentForm = null; - LOG.Debug("Remove CaptureForm from currentForm"); + Log.Debug("Remove CaptureForm from currentForm"); } private void ClosingHandler(object sender, EventArgs e) { - LOG.Debug("Closing captureform"); + Log.Debug("Closing captureform"); WindowDetails.UnregisterIgnoreHandle(Handle); } @@ -131,7 +120,7 @@ namespace Greenshot.Forms { /// public CaptureForm(ICapture capture, List windows) { if (_currentForm != null) { - LOG.Warn("Found currentForm, Closing already opened CaptureForm"); + Log.Warn("Found currentForm, Closing already opened CaptureForm"); _currentForm.Close(); _currentForm = null; Application.DoEvents(); @@ -153,7 +142,7 @@ namespace Greenshot.Forms { // InitializeComponent(); // Only double-buffer when we are not in a TerminalServerSession - DoubleBuffered = !isTerminalServerSession; + DoubleBuffered = !IsTerminalServerSession; Text = "Greenshot capture form"; // Make sure we never capture the captureform @@ -184,18 +173,21 @@ namespace Greenshot.Forms { /// /// Create an animation for the zoomer, depending on if it's active or not. /// - void InitializeZoomer(bool isOn) { + private void InitializeZoomer(bool isOn) { if (isOn) { // Initialize the zoom with a invalid position _zoomAnimator = new RectangleAnimator(Rectangle.Empty, new Rectangle(int.MaxValue, int.MaxValue, 0, 0), FramesForMillis(1000), EasingType.Quintic, EasingMode.EaseOut); VerifyZoomAnimation(_cursorPos, false); - } else if (_zoomAnimator != null) { - _zoomAnimator.ChangeDestination(new Rectangle(Point.Empty, Size.Empty), FramesForMillis(1000)); + } + else + { + _zoomAnimator?.ChangeDestination(new Rectangle(Point.Empty, Size.Empty), FramesForMillis(1000)); } } #region key handling - void CaptureFormKeyUp(object sender, KeyEventArgs e) { + + private void CaptureFormKeyUp(object sender, KeyEventArgs e) { switch(e.KeyCode) { case Keys.ShiftKey: _fixMode = FixMode.None; @@ -211,7 +203,7 @@ namespace Greenshot.Forms { /// /// /// - void CaptureFormKeyDown(object sender, KeyEventArgs e) { + private void CaptureFormKeyDown(object sender, KeyEventArgs e) { int step = _isCtrlPressed ? 10 : 1; switch (e.KeyCode) { @@ -263,6 +255,14 @@ namespace Greenshot.Forms { Invalidate(); } break; + case Keys.D: + if (_captureMode == CaptureMode.Window) + { + // Toggle debug + _showDebugInfo = !_showDebugInfo; + Invalidate(); + } + break; case Keys.Space: // Toggle capture mode switch (_captureMode) { @@ -300,6 +300,10 @@ namespace Greenshot.Forms { HandleMouseUp(); } break; + case Keys.F: + ToFront = !ToFront; + TopMost = !TopMost; + break; } } #endregion @@ -310,7 +314,7 @@ namespace Greenshot.Forms { /// /// /// - void OnMouseDown(object sender, MouseEventArgs e) { + private void OnMouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { HandleMouseDown(); } @@ -351,7 +355,7 @@ namespace Greenshot.Forms { /// /// /// - void OnMouseUp(object sender, MouseEventArgs e) { + private void OnMouseUp(object sender, MouseEventArgs e) { if (_mouseDown) { HandleMouseUp(); } @@ -383,7 +387,7 @@ namespace Greenshot.Forms { /// /// /// - void OnMouseMove(object sender, MouseEventArgs e) { + private void OnMouseMove(object sender, MouseEventArgs e) { // Make sure the mouse coordinates are fixed, when pressing shift _mouseMovePos = FixMouseCoordinates(User32.GetCursorLocation()); _mouseMovePos = WindowCapture.GetLocationRelativeToScreenBounds(_mouseMovePos); @@ -394,11 +398,11 @@ namespace Greenshot.Forms { /// /// /// - bool isAnimating(IAnimator animator) { + private bool IsAnimating(IAnimator animator) { if (animator == null) { return false; } - return animator.hasNext; + return animator.HasNext; } /// @@ -408,7 +412,7 @@ namespace Greenshot.Forms { Point lastPos = _cursorPos; _cursorPos = _mouseMovePos; - if (_selectedCaptureWindow != null && lastPos.Equals(_cursorPos) && !isAnimating(_zoomAnimator) && !isAnimating(_windowAnimator)) { + if (_selectedCaptureWindow != null && lastPos.Equals(_cursorPos) && !IsAnimating(_zoomAnimator) && !IsAnimating(_windowAnimator)) { return; } @@ -431,16 +435,14 @@ namespace Greenshot.Forms { Point cursorPosition = Cursor.Position; _selectedCaptureWindow = null; lock (_windows) { - foreach (WindowDetails window in _windows) { - if (window.Contains(cursorPosition)) { - // Only go over the children if we are in window mode - if (CaptureMode.Window == _captureMode) { - _selectedCaptureWindow = window.FindChildUnderPoint(cursorPosition); - } else { - _selectedCaptureWindow = window; - } - break; + foreach (var window in _windows) { + if (!window.Contains(cursorPosition)) + { + continue; } + // Only go over the children if we are in window mode + _selectedCaptureWindow = CaptureMode.Window == _captureMode ? window.FindChildUnderPoint(cursorPosition) : window; + break; } } @@ -486,7 +488,7 @@ namespace Greenshot.Forms { invalidateRectangle = new Rectangle(x1,y1, x2-x1, y2-y1); Invalidate(invalidateRectangle); } else if (_captureMode != CaptureMode.Window) { - if (!isTerminalServerSession) { + if (!IsTerminalServerSession) { Rectangle allScreenBounds = WindowCapture.GetScreenBounds(); allScreenBounds.Location = WindowCapture.GetLocationRelativeToScreenBounds(allScreenBounds.Location); if (verticalMove) { @@ -515,8 +517,8 @@ namespace Greenshot.Forms { // always animate the Window area through to the last frame, so we see the fade-in/out untill the end // Using a safety "offset" to make sure the text is invalidated too const int safetySize = 30; - // Check if the - if (isAnimating(_windowAnimator)) { + // Check if the animation needs to be drawn + if (IsAnimating(_windowAnimator)) { invalidateRectangle = _windowAnimator.Current; invalidateRectangle.Inflate(safetySize, safetySize); Invalidate(invalidateRectangle); @@ -524,12 +526,12 @@ namespace Greenshot.Forms { invalidateRectangle.Inflate(safetySize, safetySize); Invalidate(invalidateRectangle); // Check if this was the last of the windows animations in the normal region capture. - if (_captureMode != CaptureMode.Window && !isAnimating(_windowAnimator)) { + if (_captureMode != CaptureMode.Window && !IsAnimating(_windowAnimator)) { Invalidate(); } } - if (_zoomAnimator != null && (isAnimating(_zoomAnimator) || _captureMode != CaptureMode.Window)) { + if (_zoomAnimator != null && (IsAnimating(_zoomAnimator) || _captureMode != CaptureMode.Window)) { // Make sure we invalidate the old zoom area invalidateRectangle = _zoomAnimator.Current; invalidateRectangle.Offset(lastPos); @@ -540,11 +542,7 @@ namespace Greenshot.Forms { } // The following logic is not needed, next always returns the current if there are no frames left // but it makes more sense if we want to change something in the logic - if (isAnimating(_zoomAnimator)) { - invalidateRectangle = _zoomAnimator.Next(); - } else { - invalidateRectangle = _zoomAnimator.Current; - } + invalidateRectangle = IsAnimating(_zoomAnimator) ? _zoomAnimator.Next() : _zoomAnimator.Current; invalidateRectangle.Offset(_cursorPos); Invalidate(invalidateRectangle); } @@ -570,7 +568,7 @@ namespace Greenshot.Forms { screenBounds.Location = WindowCapture.GetLocationRelativeToScreenBounds(screenBounds.Location); int relativeZoomSize = Math.Min(screenBounds.Width, screenBounds.Height) / 5; // Make sure the final size is a plural of 4, this makes it look better - relativeZoomSize = relativeZoomSize - (relativeZoomSize % 4); + relativeZoomSize = relativeZoomSize - relativeZoomSize % 4; Size zoomSize = new Size(relativeZoomSize, relativeZoomSize); Point zoomOffset = new Point(20, 20); @@ -613,8 +611,10 @@ namespace Greenshot.Forms { if (_isZoomerTransparent) { //create a color matrix object to change the opacy - ColorMatrix opacyMatrix = new ColorMatrix(); - opacyMatrix.Matrix33 = Conf.ZoomerOpacity; + ColorMatrix opacyMatrix = new ColorMatrix + { + Matrix33 = Conf.ZoomerOpacity + }; attributes = new ImageAttributes(); attributes.SetColorMatrix(opacyMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); } else { @@ -652,9 +652,9 @@ namespace Greenshot.Forms { // Calculate some values int pixelThickness = destinationRectangle.Width / sourceRectangle.Width; int halfWidth = destinationRectangle.Width / 2; - int halfWidthEnd = (destinationRectangle.Width / 2) - (pixelThickness / 2); + int halfWidthEnd = destinationRectangle.Width / 2 - pixelThickness / 2; int halfHeight = destinationRectangle.Height / 2; - int halfHeightEnd = (destinationRectangle.Height / 2) - (pixelThickness / 2); + int halfHeightEnd = destinationRectangle.Height / 2 - pixelThickness / 2; int drawAtHeight = destinationRectangle.Y + halfHeight; int drawAtWidth = destinationRectangle.X + halfWidth; @@ -673,8 +673,8 @@ namespace Greenshot.Forms { graphics.DrawLine(pen, destinationRectangle.X + halfWidthEnd + 2 * padding, drawAtHeight, destinationRectangle.X + destinationRectangle.Width - padding, drawAtHeight); // Fix offset for drawing the white rectangle around the crosshair-lines - drawAtHeight -= (pixelThickness / 2); - drawAtWidth -= (pixelThickness / 2); + drawAtHeight -= pixelThickness / 2; + drawAtWidth -= pixelThickness / 2; // Fix off by one error with the DrawRectangle pixelThickness -= 1; // Change the color and the pen width @@ -689,9 +689,7 @@ namespace Greenshot.Forms { // Horizontal middle + 1 to right graphics.DrawRectangle(pen, destinationRectangle.X + halfWidthEnd + 2 * padding, drawAtHeight, halfWidthEnd - 2 * padding - 1, pixelThickness); } - if (attributes != null) { - attributes.Dispose(); - } + attributes?.Dispose(); } /// @@ -699,7 +697,7 @@ namespace Greenshot.Forms { /// /// /// - void OnPaint(object sender, PaintEventArgs e) { + private void OnPaint(object sender, PaintEventArgs e) { Graphics graphics = e.Graphics; Rectangle clipRectangle = e.ClipRectangle; //graphics.BitBlt((Bitmap)buffer, Point.Empty); @@ -709,23 +707,16 @@ namespace Greenshot.Forms { graphics.DrawIcon(_capture.Cursor, _capture.CursorLocation.X, _capture.CursorLocation.Y); } - if (_mouseDown || _captureMode == CaptureMode.Window || isAnimating(_windowAnimator)) { + if (_mouseDown || _captureMode == CaptureMode.Window || IsAnimating(_windowAnimator)) { _captureRect.Intersect(new Rectangle(Point.Empty, _capture.ScreenBounds.Size)); // crop what is outside the screen - - Rectangle fixedRect; - //if (captureMode == CaptureMode.Window) { - if (isAnimating(_windowAnimator)) { - // Use the animator - fixedRect = _windowAnimator.Current; - } else { - fixedRect = _captureRect; - } + + var fixedRect = IsAnimating(_windowAnimator) ? _windowAnimator.Current : _captureRect; // TODO: enable when the screen capture code works reliable //if (capture.CaptureDetails.CaptureMode == CaptureMode.Video) { // graphics.FillRectangle(RedOverlayBrush, fixedRect); //} else { - graphics.FillRectangle(GreenOverlayBrush, fixedRect); + graphics.FillRectangle(GreenOverlayBrush, fixedRect); //} graphics.DrawRectangle(OverlayPen, fixedRect); @@ -762,7 +753,7 @@ namespace Greenshot.Forms { graphics.DrawPath(rulerPen, p); graphics.DrawString(captureWidth, rulerFont, rulerPen.Brush, fixedRect.X + (fixedRect.Width / 2 - hSpace / 2) + 3, fixedRect.Y - dist - 7); graphics.DrawLine(rulerPen, fixedRect.X, fixedRect.Y - dist, fixedRect.X + (fixedRect.Width / 2 - hSpace / 2), fixedRect.Y - dist); - graphics.DrawLine(rulerPen, fixedRect.X + (fixedRect.Width / 2 + hSpace / 2), fixedRect.Y - dist, fixedRect.X + fixedRect.Width, fixedRect.Y - dist); + graphics.DrawLine(rulerPen, fixedRect.X + fixedRect.Width / 2 + hSpace / 2, fixedRect.Y - dist, fixedRect.X + fixedRect.Width, fixedRect.Y - dist); graphics.DrawLine(rulerPen, fixedRect.X, fixedRect.Y - dist - 3, fixedRect.X, fixedRect.Y - dist + 3); graphics.DrawLine(rulerPen, fixedRect.X + fixedRect.Width, fixedRect.Y - dist - 3, fixedRect.X + fixedRect.Width, fixedRect.Y - dist + 3); } @@ -780,7 +771,7 @@ namespace Greenshot.Forms { graphics.DrawPath(rulerPen, p); graphics.DrawString(captureHeight, rulerFont, rulerPen.Brush, fixedRect.X - measureHeight.Width + 1, fixedRect.Y + (fixedRect.Height / 2 - vSpace / 2) + 2); graphics.DrawLine(rulerPen, fixedRect.X - dist, fixedRect.Y, fixedRect.X - dist, fixedRect.Y + (fixedRect.Height / 2 - vSpace / 2)); - graphics.DrawLine(rulerPen, fixedRect.X - dist, fixedRect.Y + (fixedRect.Height / 2 + vSpace / 2), fixedRect.X - dist, fixedRect.Y + fixedRect.Height); + graphics.DrawLine(rulerPen, fixedRect.X - dist, fixedRect.Y + fixedRect.Height / 2 + vSpace / 2, fixedRect.X - dist, fixedRect.Y + fixedRect.Height); graphics.DrawLine(rulerPen, fixedRect.X - dist - 3, fixedRect.Y, fixedRect.X - dist + 3, fixedRect.Y); graphics.DrawLine(rulerPen, fixedRect.X - dist - 3, fixedRect.Y + fixedRect.Height, fixedRect.X - dist + 3, fixedRect.Y + fixedRect.Height); } @@ -796,17 +787,17 @@ namespace Greenshot.Forms { // When capturing a Region we need to add 1 to the height/width for correction string sizeText; if (_captureMode == CaptureMode.Region) { - // correct the GUI width to real width for the shown size - sizeText = (_captureRect.Width + 1) + " x " + (_captureRect.Height + 1); + // correct the GUI width to real width for the shown size + sizeText = _captureRect.Width + 1 + " x " + (_captureRect.Height + 1); } else { sizeText = _captureRect.Width + " x " + _captureRect.Height; } - + // Calculate the scaled font size. SizeF extent = graphics.MeasureString( sizeText, sizeFont ); float hRatio = _captureRect.Height / (extent.Height * 2); float wRatio = _captureRect.Width / (extent.Width * 2); - float ratio = ( hRatio < wRatio ? hRatio : wRatio ); + float ratio = hRatio < wRatio ? hRatio : wRatio; float newSize = sizeFont.Size * ratio; if ( newSize >= 4 ) { @@ -816,13 +807,20 @@ namespace Greenshot.Forms { } // Draw the size. using (Font newSizeFont = new Font(FontFamily.GenericSansSerif, newSize, FontStyle.Bold)) { - PointF sizeLocation = new PointF(fixedRect.X + (_captureRect.Width / 2) - (extent.Width / 2), fixedRect.Y + (_captureRect.Height / 2) - (newSizeFont.GetHeight() / 2)); + PointF sizeLocation = new PointF(fixedRect.X + _captureRect.Width / 2 - extent.Width / 2, fixedRect.Y + _captureRect.Height / 2 - newSizeFont.GetHeight() / 2); graphics.DrawString(sizeText, newSizeFont, Brushes.LightSeaGreen, sizeLocation); + + if (_showDebugInfo && _selectedCaptureWindow != null) + { + string title = $"#{_selectedCaptureWindow.Handle.ToInt64():X} - {(_selectedCaptureWindow.Text.Length > 0 ? _selectedCaptureWindow.Text : _selectedCaptureWindow.Process.ProcessName)}"; + PointF debugLocation = new PointF(fixedRect.X, fixedRect.Y); + graphics.DrawString(title, sizeFont, Brushes.DarkOrange, debugLocation); + } } } } } else { - if (!isTerminalServerSession) { + if (!IsTerminalServerSession) { using (Pen pen = new Pen(Color.LightSeaGreen)) { pen.DashStyle = DashStyle.Dot; Rectangle screenBounds = _capture.ScreenBounds; @@ -848,11 +846,11 @@ namespace Greenshot.Forms { } // Zoom - if (_zoomAnimator != null && (isAnimating(_zoomAnimator) || _captureMode != CaptureMode.Window)) { + if (_zoomAnimator != null && (IsAnimating(_zoomAnimator) || _captureMode != CaptureMode.Window)) { const int zoomSourceWidth = 25; const int zoomSourceHeight = 25; - Rectangle sourceRectangle = new Rectangle(_cursorPos.X - (zoomSourceWidth / 2), _cursorPos.Y - (zoomSourceHeight / 2), zoomSourceWidth, zoomSourceHeight); + Rectangle sourceRectangle = new Rectangle(_cursorPos.X - zoomSourceWidth / 2, _cursorPos.Y - zoomSourceHeight / 2, zoomSourceWidth, zoomSourceHeight); Rectangle destinationRectangle = _zoomAnimator.Current; destinationRectangle.Offset(_cursorPos); diff --git a/Greenshot/Forms/ColorDialog.Designer.cs b/Greenshot/Forms/ColorDialog.Designer.cs index 622a799cc..94dda653d 100644 --- a/Greenshot/Forms/ColorDialog.Designer.cs +++ b/Greenshot/Forms/ColorDialog.Designer.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -144,7 +144,7 @@ namespace Greenshot { this.textBoxRed.TabIndex = 2; this.textBoxRed.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; this.textBoxRed.Click += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxRed.TextChanged += new System.EventHandler(this.TextBoxRGBTextChanged); + this.textBoxRed.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged); this.textBoxRed.GotFocus += new System.EventHandler(this.TextBoxGotFocus); this.textBoxRed.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown); // @@ -156,7 +156,7 @@ namespace Greenshot { this.textBoxGreen.TabIndex = 3; this.textBoxGreen.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; this.textBoxGreen.Click += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxGreen.TextChanged += new System.EventHandler(this.TextBoxRGBTextChanged); + this.textBoxGreen.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged); this.textBoxGreen.GotFocus += new System.EventHandler(this.TextBoxGotFocus); this.textBoxGreen.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown); // @@ -168,7 +168,7 @@ namespace Greenshot { this.textBoxBlue.TabIndex = 4; this.textBoxBlue.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; this.textBoxBlue.Click += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxBlue.TextChanged += new System.EventHandler(this.TextBoxRGBTextChanged); + this.textBoxBlue.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged); this.textBoxBlue.GotFocus += new System.EventHandler(this.TextBoxGotFocus); this.textBoxBlue.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown); // @@ -189,7 +189,7 @@ namespace Greenshot { this.textBoxAlpha.TabIndex = 5; this.textBoxAlpha.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; this.textBoxAlpha.Click += new System.EventHandler(this.TextBoxGotFocus); - this.textBoxAlpha.TextChanged += new System.EventHandler(this.TextBoxRGBTextChanged); + this.textBoxAlpha.TextChanged += new System.EventHandler(this.TextBoxRgbTextChanged); this.textBoxAlpha.GotFocus += new System.EventHandler(this.TextBoxGotFocus); this.textBoxAlpha.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextBoxKeyDown); // diff --git a/Greenshot/Forms/ColorDialog.cs b/Greenshot/Forms/ColorDialog.cs index 2f630d064..5cfbf187d 100644 --- a/Greenshot/Forms/ColorDialog.cs +++ b/Greenshot/Forms/ColorDialog.cs @@ -1,9 +1,9 @@ /* * Greenshot - a free and open source screenshot tool - * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom + * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom * * For more information see: http://getgreenshot.org/ - * The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ + * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,8 +34,8 @@ namespace Greenshot { /// Description of ColorDialog. /// public partial class ColorDialog : BaseForm { - private static ColorDialog uniqueInstance; - private static EditorConfiguration editorConfiguration = IniConfig.GetIniSection(); + private static ColorDialog _uniqueInstance; + private static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection(); private ColorDialog() { SuspendLayout(); @@ -47,17 +47,15 @@ namespace Greenshot { UpdateRecentColorsButtonRow(); } - public static ColorDialog GetInstance() { - if (uniqueInstance == null) { - uniqueInstance = new ColorDialog(); - } - return uniqueInstance; + public static ColorDialog GetInstance() + { + return _uniqueInstance ?? (_uniqueInstance = new ColorDialog()); } private readonly List