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
Mit Hilfe der Leertaste können Sie vom Bereichsmodus in den
- Fenstermodus wechseln (und umgekehrt).
+ Fenstermodus wechseln (und umgekehrt).
Wenn Sie einen exakten Bereich abfotografieren, ist es eventuell einfacher, zuerst
diff --git a/Greenshot/Languages/help-es-ES.html b/Greenshot/Languages/help-es-ES.html
index 43437a96a..e248bd90a 100644
--- a/Greenshot/Languages/help-es-ES.html
+++ b/Greenshot/Languages/help-es-ES.html
@@ -168,7 +168,7 @@
Usted puede mover o redimensionar formas existentes después de elegir la
- Herramienta de SelecciónESC desde la barra de herramientas. Herramienta de SelecciónESC desde la barra de herramientas.
Para cada tipo de elemento hay un conjunto específico de opciones disponibles
para cambiar la apariencia del elemento (por ej. grosor de la línea, color
de la línea, color de relleno). Usted puede cambiar las opciones para un
diff --git a/Greenshot/Languages/help-it-IT.html b/Greenshot/Languages/help-it-IT.html
index 7d0d69e3b..1d5744287 100644
--- a/Greenshot/Languages/help-it-IT.html
+++ b/Greenshot/Languages/help-it-IT.html
@@ -335,7 +335,6 @@
Stampa con colori inverititi (negativo): Trasformerà l'immagine in negativo prima di stamparla, utile per esempio quando si stampa un'immagine con testo bianco su sfondo nero (per risparmiare toner o inchiostro).
Visualizza scelta opzioni di stampa ogni volta che si stampa un'immagine: Permette di scegliere se visualizzare o meno la finestra di scelta opzioni per le stampe successive alla prima.
-
Impostazioni Componenti Aggiuntivi
diff --git a/Greenshot/Languages/help-nl-NL.html b/Greenshot/Languages/help-nl-NL.html
index 0169cca9d..d4e90dee9 100644
--- a/Greenshot/Languages/help-nl-NL.html
+++ b/Greenshot/Languages/help-nl-NL.html
@@ -15,7 +15,7 @@
a:link, a:hover, a:visited, a:active {color:#009900;}
kbd {background-color:#dddddd;border:1px solid #bbbbbb;padding:0 2px;border-radius:2px;}
p.hint {background-color:#ffffdd;border:1px solid #ddddbb;padding:5px;}
-
+ em {padding-right:0.2em;}
@@ -23,273 +23,398 @@
- Version 0.8 Nederlanse vertaling van de help door Jurjen Ladenius
+ Versie 1.0 - Nederlandse vertaling van de help door Jurjen Ladenius en Stephan Paternotte
- U kunt een screenshot maken door de Print toets van uw keyboard te drukken of
- rechts op het Greenshot icon in de systray te klikken
- Er zijn meerdere mogelijkheden om een screenshot te maken:
+ U kunt een schermopname maken door op uw toetsenbord de Print-toets te drukken of
+ een rechtermuisklik op het Greenshot-icoon in het systeemvak te geven
+ Er zijn meerdere mogelijkheden om een schermopname te maken:
-
Regio vastleggen Print
+
Interactief kader Print
- De "regio vastleggen" modus maakt het mogelijk om een gebied van het beeldscherm te markeren voor een screenshot.
+ De "regio-opname" modus maakt het mogelijk om een gebied van het beeldscherm te markeren voor een schermopname.
Nadat de regio vastlegen modus gestart wordt verandert de mouse-cursor in een kruis.
- Stuur de muis naar een hoek van het gebied waarvan u een screenshot wilt hebben en
- druk op de linker muisknop en hou deze gedrukt. Beweeg nu de muis naar de tegenovergestelde hoek
- van uw doelgebied, tijdens het bewegen ziet u een groeiende groene rechthoek.
- Op het moment dat u de linker muisknop los laat word het gehele groene gebied vastgelegd.
+ Positioneer de muis naar een hoek van het gebied waarvan u een schermopname wilt hebben en
+ druk op de linkermuisknop en houd deze ingedrukt. Beweeg nu de muis naar de diagonale hoek
+ van uw doelgebied. Tijdens het bewegen ontstaat een groeiende groene rechthoek.
+ Op het moment dat u de linkermuisknop loslaat wordt van het groene gebied een schermopname gemaakt.
- U kunt de spatie toets gebruiken om tussen de "regio vastleggen" en de
- window modus te wisselen. De Esc-toets breekt het vastleggen af.
+ U kunt de spatie toets gebruiken om wisselen tussen de modi "regio-opname" en
+ venster. Met de Esc-toets breekt u de schermopname af.
- Als u een zeer exact gebied wilt vastleggen is het misschen eenvoudiger om eerst een groter
- gebied te nemen en dan de screeshot bij te snijden in de
- Greenshot beeld bewerking.
+ Als u een zeer exact gebied wilt vastleggen is het misschien eenvoudiger om eerst van een groter
+ gebied een schermopname te maken en deze vervolgens in de Greenshot beeldbewerker
+ bij te snijden.
-
Laast gebruikte regio vastleggen Shift + Print
+
Laatstgebruikte schermopnameShift + Print
- Als u al een keer een regio of een window
- vastgelegt heeft, heeft u met deze optie de mogelijkheid nog een keer de zelfde regio vast te leggen.
+ Als u al een keer een schermopname heeft gemaakt van een kader
+ of een venster, dan heeft u met deze optie de mogelijkheid hetzelfde gebied nog eens vast te leggen.
-
Window vangen Alt + Print
+
Actief venster Alt + Print
- Maakt een screenshot van het aktive window.
+ Maakt een schermopname van het aktieve venster.
- In de voorkeursinstellingen is een optie om niet
- het aktive window te vangen, maar om een window interaktiv uit te kiezen.
- Als deze optie aan staat kunt u een window selekteren door erop te klikken.
- (net als in de regio vastleggen modus tekent Greenshot
- een groene rechhoek om het window wat gekozen wordt.)
- Als u gedeeltes van een window wilt vangen, bijvoorbeeld het zichtbare gedeelte
- van de website die op dit moment in Internet Explorer getoont word, dan beweeg de muis
- over het window een druk de PgDown toets. Op dit moment is het mogelijk
- om kleinere gedeeltes van het window te selekteren en te vangen.
+ Gebruik bij Windows 7 of Vista de Schermopname-instellingen om te bepalen
+ hoe Greenshot omgaat met transparante (Aero) vensterranden, etc. het vervangen
+ van transparanties door een vaste kleur.
+
+
+ De instellingendialoog biedt de mogelijkheid om niet direct
+ het actieve venster te fotograferen, maar een venster interactief te selecteren.
+ Als deze optie geactiveerd is, kunt u een venster selecteren door het te klikken (zoals bij
+ Interactief kader, zal Greenshot het te fotograferen
+ gebied markeren). Als u een deelvenster wilt fotograferen, zoals bijv. een browservenster
+ zonder menu of gereedschapsbalk of een enkel onderdeel in een webpagina,
+ positioneer dan de muis over het deelvenster en druk de PgDown-toets. Hierna
+ kunt u de specifieke vensterelementen selecteren voor de schermopname.
+
+
+ Schermopnamen van contextmenu's zijn lastig te maken: bij gebruik van de sneltoets voor een
+ "Venster"-schermopname zal het contextmenu verdwijnen en dat zal ook gebeuren als u
+ Greenshot's contextmenu gebruikt om de schermopname te maken. Wilt u een
+ schermopname maken van een contextmenu dat u zojuist met een rechtermuisklik hebt geopend,
+ gebruik dan eenvoudig "Interactief kader" Print en druk dan de Spatie-balk.
-
Gehele beeldscherm vastleggen Control + Print
+
Volledige schermopname Control + Print
- Maakt een screenshot van het gehele beeldscherm, ook als er meerdere monitoren gebruikt worden.
+ Hierbij wordt een schermopname gemaakt van het gehele scherm, ook als meerdere monitoren gebruikt worden.
+
+
+
Internet Explorer schermopnameControl + Shift + Print
+
+ Deze funcie maakt eenvoudig een schermopname van een webpagina die geopend is in Internet Explorer.
+ Gebruik Greenshot's contextmenu om de tab in Internet Explorer te selecteren voor schermopname, of druk
+ Crtl + Shift + Print om een schermopname te maken van de actieve tab.
+
+
-
De Greenshot beeld bewerking gebruiken
+
De Greenshot beeldbewerker gebruiken
- Greenshot komt met een eenvoudig te gebruiken beeld bewerking die verschillende handige werktuigen heeft en het
- mogelijk maakt om vormen en annotaties op een screenshot te maken. Het is zelfs mogelijk om bepaalde delen van
+ Greenshot heeft een eenvoudig te gebruiken beeldbewerkingsprogramma met verschillende handige functies en
+ mogelijkheden om een schermopname te voorzien van vormen en annotaties. Het is ook mogelijk om bepaalde delen van
uw screenshot onherkenbaar te maken of te markeren waardoor het beter opvalt.
- De Greenshot beeld bewerking kan niet alleen voor screenshot maar ook voor andere beelden uit bestanden of het klembord gebruikt worden.
- Klik hiervoor met de rechter muis knop op het Greenshot icon in de systray en selekteer Open beeld uit bestand
- of Laad beeld van het klembord.
+ De Greenshot beeldbewerker is niet alleen handig voor schermopnamen, maar is ook te gebruiken voor andere
+ afbeeldingen uit bestanden of het klembord. Klik hiervoor met de rechter muisknop op het Greenshot-icoon
+ in het systeemvak en selecteer Afbeelding uit bestand openen of
+ Afbeelding laden van het klembord.
- By default, the image editor will be opened whenever a screenshot is
- captured. If you do not want to use the image editor, you can disable this
- behavior in the settings dialog.
+ Wanneer een schermopname is gemaakt wordt standaard de beeldbewerker geopend.
+ Indien u dit niet wenst, kunt u dit gedrag in het instellingen-venster
+ afschakelen.
-
Drawing shapes
+
Vormen tekenen
- Select one of the shape drawing tools from the toolbar on the left hand side
- of the image editor or from the Object menu. There is also a key assigned
- to each tool for your convenience.
- Available shapes are: rectangle R, ellipse E, line L
- and arrow A.
- Click, hold down the mouse button and drag to define position and size of the shape.
- Release the mouse button when you are done.
+ Kies een van de vormen in de gereedschapsbalk aan de linkerzijde van de beeldbewerker
+ of van het menu Object. Aan elke toets is tevens een sneltoets gekoppeld
+ voor snelle toegang via het toetsenbord.
+ Beschikbare vormen zijn: rechthoek R, ellips E, lijn L
+ pijl A en vrije vorm F.
+ Klik en sleep de muis om de positie en de grootte van de vorm te bepalen.
+ Laat de muisknop los als de vorm van de juiste afmetingen is.
- You can move or resize existing shapes after selecting the selection tool
- ESC from the toolbar. For every element type there is a specific
- set of options available to change the look of the element (e.g. line thickness,
- line color, fill color). You can change the options for an existing element after
- selecting it, but also for the next element to be drawn after selecting a drawing tool.
+ Getekende vormen kunnen worden verplaatst en vergroot met behulp van de knop Selectie
+ ESC op de gereedschapsbalk. Voor elk vormtype zijn specifieke
+ opties beschikbaar om het uiterlijk aan te passen (bijv. lijndikte,
+ lijnkleur, vulkleur). U kunt het uiterlijk veranderen voor een bestaand geselecteerd object,
+ maar u kunt ook de eigenschappen instellen voor de volgende te tekenen vorm.
- You can select multiple elements for editing at a time. In order to select multiple
- elements, hold down the Shift key while clicking the elements.
+ Op elk moment kunnen meerdere elementen worden geselecteerd door tijdens het maken van de selectie
+ de Shift-toets ingedrukt te houden.
+
+
+ Wilt u een symmetrische vorm tekenen (bijv. een vierkant of een cirkel)? Houd dan tijdens het tekenen
+ de Shift-toets ingedrukt. Bij het tekenen van pijlen, beperkt de Shift-toets
+ de mogelijke hoeken tot veelvouden van 15°.
+ Bij het vergroten van een bestaand object zorgt de Shift-toets ervoor dat de verhoudingen behouden blijven.
+
+
+ Bij het tekenen of het vergroten kunt u de Ctrl-toets ingedrukt houden om het object
+ in het geometrische centrum te fixeren. Zo kan een object ook in tegenovergestelde richting worden vergroot.
+ (Dit kan erg handig zijn om een ellips aan een schermafdruk toe te voegen.)
-
Adding text
+
Tekst toevoegen
- Usage of the text tool T is similar to the usage of the
- shape tools. Just draw the text element to the desired
- size, then type in the text.
- Double click an existing text element to edit the text.
+ Het gebruik van de Tekst-functie T is vergelijkbaar met dat van
+ Vormen toevoegen. Plaats een tekst-element van de gewenste grootte
+ en typ de tekst.
+ Dubbelklik een bestaande tekst om deze te bewerken.
+ Gebruik Return of Enter als u klaar bent met bewerken.
+
+
+ Gebruik Shift + Return of Shift + Enter
+ om binnen een tekstkader een nieuwe regel te beginnen.
-
Highlighting things
+
Markeren
- After selecting the highlight tool H, you can define the area to be
- highlighted exactly like you would draw a shape.
- There are several options for highlighting, which you can choose from by clicking
- the leftmost button in the toolbar on top:
+ Met de Markeer-functie H, kunt u een gebied markeren op precies dezelfde wijze
+ als waarmee u een vorm shape tekent.
+ De volgende opties bij het markeren zijn beschilbaar via de meest linkse knop
+ in de gereedschapsbalk:
-
Highlight text: highlights an area by applying a bright color to it, like
- an office text highlighter
-
Highlight area: blurs* and darkens everything outside the selected area
-
Grayscale: everything outside the selected area will be turned to grayscale
-
Magnify: the selected area will be displayed magnified
+
Tekst markeren: Een gebied markeren met een heldere kleur, zoals een markeerstift
+
+
Gebied oplichten: Alles buiten het geselecteerde gebied vervagen* en donkerder maken
+
Grijstinten: Alles buiten het geselecteerde gebied wordt omgezet naar grijstinten
+
Vergroten: Het geselecteerde gebied wordt vergroot weergegeven
-
Obfuscating things
+
Maskeren
- Obfuscating parts of a screenshot is a good idea if it contains data which is not
- intended for other people to see, e.g. bank account data, names, passwords or faces on images.
- Use the obfuscate tool O exactly like the highlight
- tool.
- Available options for obfuscation are:
+ Delen van een schermopname maskeren is een goed gebruik wanneer persoonlijke gegevens in beeld zijn
+ die beter privé kunnen blijven, zoals bijv. bankgegevens, namen, wachtwoorden of herkenbare personen.
+ De functie Maskeren O gebruikt u net als het Markeren.
+
+ Beschikbare opties voor Maskeren zijn:
-
Pixelize: increases the pixel size for the selected area
Pixeleren: Vergroot de pixels in het geselecteerde gebied
+
Vervagen*: Vervaagt het beeld in het geselecteerde gebied
- * Depeding on the performance of your computer, applying a blur effect might slow down
- Greenshot's image editor. If you feel the image editor reacting slowly as soon as a
- blur is applied, try reducing the value for Preview quality in the toolbar or
- decrease the value for Blur radius.
- If the blur performance is still too bad for you to work with, you might prefer
- to use the pixelize effect instead.
+ * Afhankelijk van uw computer kan het vervagingseffect de werking van Greenshot's beeldbewerker
+ trager maken. Merkt u dat de beeldbewerker bij de toepassing van Vervagen traag en sloom wordt,
+ probeer dan de kwaliteit van de voorvertoning in de gereedschapsbalk te verminderen of
+ verlaag de waarde voor de Vervagings-radius.
+ Blijft de functie Vervagen traag reageren, probeer dan de functie Pixeleren te gebuiken.
+
+
+
+
Effecten toevoegen
+
+ U kunt aan uw schermopname verschillende effecten toevoegen. Zo kunt u bijvoorbeeld een lijst toevoegen
+ of een schaduw of het effect van gescheurde randen om de afbeelding meer nadruk te geven.
+ De effecten Grijstinten en Negatief zijn met name nuttig voor het afdrukken en de besparing van inkt of toner bij
+ kleurrijke of donkere schermopnames.
-
Cropping the screenshot
+
Schermopname bijsnijden
- If you only need a part of the screenshot you have captured, use the crop tool C
- to crop it to the desired area.
- After selecting the crop tool, draw a rectangle for the area of the screenshot you want
- to keep. You can resize the selected area like any other element.
- When you are content with your selection, use the confirm button in the toolbar or hit
- the Enter key. You can cancel cropping by clicking the cancel button or hitting
- ESC.
+ Als u maar een deel van de schermopname nodig hebt, gebruik dan de functie bijsnijden C
+ om de overtollige delen weg te snijden.
+ Na het activeren van de functie bijsnijden, tekent u een rechthoek om het gebied van de schermopname dat behouden
+ moet worden. U kunt de afmetingen van het geselecteerde gebied naar wens aanpassen.
+ Bent u tevreden over het geselecteerde gebied, bevestig het bijsnijden dan in de gereedschapsbalk of type Enter.
+ U kunt het bijsnijden afbreken met de toets ESC.
+
+
+
+ Automatisch Bijsnijden: Als u een schermopname wilt bijsnijden tot een rand of vlakke achtergrondkleur,
+ gebruik dan Automatisch bijsnijden in het menu Bewerken en Greenshot zal het bij te snijden gebied
+ automatisch bepalen.
+
+
+
+
+ Gebruik de functie Roteren om een schermopname linksom of rechtsom te draaien.
+
+
+
+
Afbeeldingen aan een schermopname toevoegen
+
+ U kunt eenvoudig afbeeldingen aan een schermopname toevoegen door een afbeeldingsbestand in
+ het venster van de beeldbewerker te slepen. U kunt ook schermopnames van andere vensters invoegen met behulp van
+ de functie Venster invoegen in het menu Bewerken. Een lijst van alle geopende vensters biedt u
+ de gelegenheid er een te kiezen om in te voegen.
-
Re-using drawn elements
+
Eerder getekende elementen hergebruiken
- If you find yourself using the same or similar elements on most of your screenshots
- (e.g. a textfield containing browser type and version, or obfuscating the same
- element on several screenshots) you can re-use elements.
- Select Save objects to file from the Object menu to save the current
- set of elements for re-using it later. Load objects from file applies the
- same elements to another screenshot.
+ Als u regelmatig dezelfde elementen toepast in de bewerking van uw schermopnamen
+ (bijv. een tekstkader met browsertype en versienummer, of het maskeren van hetzelfde
+ element in verschillende schermopnamen) dan kunt u deze elementen hergebruiken.
+ Kies in het menu Objecten, Objecten opslaan om de huidige elementen op te slaan
+ voor later gebruik. Objecten laden past deze eerder opgeslagen elementen toe
+ op een andere schermopname.
-
Exporting the screenshot
+
Schermopname exporteren
- After editing the screenshot, you can export the result for different purposes,
- depending on your needs. You can access all export options through the File
- menu, the topmost toolbar or via shortcuts:
+ Na het bewerken van de schermopname, kunt u het resultaat naar believen
+ opslaan voor later gebruik. Alle opties voor het exporteren zijn beschikbaar via het menu Bestand,
+ de bovenste gereedschapsbalk of via de sneltoetsen:
-
SaveControl + S: saves the image to a file (if the image has already been saved, else displays Save as... dialog
-
Save as...Control + Shift + S: lets you choose location, filename and image format for the file to save
-
Copy image to clipboardControl + Shift + C: puts a copy of the image into the clipboard, allowing to paste into other programs
-
Print...Control + P: sends the image to a printer
-
E-MailControl + E: opens a new message in your default e-mail client, adding the image as attachment
+
OpslaanCtrl + S: slaat de afbeelding op naar een bestand (als het bestand al is opgeslagen, anders wordt Opslaan als… getoond
+
Opslaan als…Ctrl + Shift + S: laat u een locatie, bestandsnaam en afbeeldingsformaat kiezen voor het opslaan van het bestand
+
Afbeelding naar klembord kopiërenCtrl + Shift + C: plaatst een kopie van de afbeelding op het klembord, zodat u het vervolgens in een ander programma kunt kopiëren
+
Afdrukken…Ctrl + P: stuurt de afbeelding naar een printer
+
E-mailCtrl + E: opent een nieuw bericht in uw standaard e-mailprogramme met de afbeelding als bijlage
+
+ Er zijn plugins om schermopnamen te exporteren naar andere bestemmingen, zoald DropBox, Picasa, Flickr.
+ Selecteer de relevante plugins tijdens de installatie van Greenshot.
+
- After saving an image from the editor, right-click the status bar at the bottom of
- the editor window to either copy the file path into the clipboard or open the
- containing directory in Windows Explorer.
+ Klik, nadat u de afbeelding hebt opgeslagen, de statusbalk onderaan de beeldbewerker
+ om het bestandspad naar het klembord te kopiëren of de betreffende map met
+ Windows Explorer te openen.
-
The settings dialog
+
Het instellingenvenster
-
General settings
+
Algemene instellingen
-
Language: The language you prefer to be used.
- You can download additional language files for Greenshot here.
-
Register hotkeys: If checked, Greenshot can be used with the Print key.
-
Launch Greenshot on startup: Start the program when the system has been booted.
-
Show flashlight: Visual feedback when doing a capture
-
Play camera sound: Audible feedback when doing a capture
-
Capture mousepointer: If checked, the mousepointer will be captured. The pointer is handled is a separate element in the editor, so that you can move or remove it later.
+
Taal: De taal waarin Greenshot wordt weergegeven.
+ Aanvullende taalbestanden zijn te downloaden van de Greenshot website.
+
Greenshot automatisch opstarten: Start het programma als de PC wordt opgestart.
+
Sneltoetsen: De sneltoetsen aanpassen voor het maken van schermopnames.
+
Systeem-proxy gebruiken: Greenshot gebruikt de systeem-proxy instelllingen bij het zoeken naar updates.
+
Versiecontrole-interval [dagen]: Greenshot automatisch uitkijken naar nieuwe versies. Gebruik deze instelling om het
+ interval (in dagen) aan te passen of gebruik 0 om de versiecontrole af te schakelen.
+
+
+
+
Opname-instellingen
+
+
Muisaanwijzer opnemen: Indien geactiveerd, wordt de muisaanwijzer in de schermopname meegenomen. De muisaanwijzer is een apart element in the beeldbewerker, dus u kunt deze later nog verplaatsen of verwijderen.
+
Camerageluid afspelen: Het maken van een schermopname gaat gepaard met een geluidseffect
+
Vertragingstijd voor de schermopname [ms]: Een instelbare tijdsvertraging welke wordt toegepast voor de schermopname.
Use interactive window capture mode: Instead of capturing the active window right away, interactive mode
allows you to select the window to capture. It is also possible to capture child windows, see window capture.
+
+ Aero schermopname (alleen Windows Vista / 7): Als u Greenshot gebruikt bij Windows Vista of Windows 7 met aero geactiveerd, dan kunt u
+ aangeven hoe transparante vensterranden moeten worden behandeld bij het maken van de schermopname. Gebruik deze instelling om te voorkomen dat elementen
+ in de achtergrond met de transparante vensterranden mee worden gefotografeerd.
+
+
Automatisch: Laat Greenshot bepalen hoe om te gaan met transparantie.
+
Zoals weergegeven: Transparante randen worden opgenomen zoals deze op het scherm worden weergegeven.
+
Standaardkleur gebruiken: De transparantie wordt vervangen door een solide standaardkleur.
+
Aangepaste kleur gebruiken: Selecteer een kleur die wordt gebruikt ter vervanging van transparanties.
+
Transparantie behouden: Vensterranden worden opgenomen met behoud van hun transparantie, waarbij objecten in de achtergrond worden geneerd.
+ (Opm.: transparante gebied worden in de beeldbewerker weergegeven met een geblokt patroon. Dit blokpatroon wordt niet bij het opslaan van de afbeeelding niet geëxporteerd.
+ Sla de afbeelding op als PNG voor volledige ondersteuning van transparanties.)
+
+
+
Internet Explorer schermopname: Maakt eenvoudige schermopnames mogelijk van webpagina's in Internet Explorer.
+
Beeldbewerker-venster aanpassen op schermopname: Indien geactiveerd, past de beeldbewerker automatisch het venster aan op de afmetingen van de schermopname.
+
-
Output settings
+
Resultaat-instellingen
-
Screenshot destination: Allows you to choose the destination(s) for your screenshot right after capturing it.
+
Bestemming schermopname: Hiermee kunt u opgeven naar welke bestemming(en) de schermopnamen moeten worden opgeslagen.
Preferred output file settings: Directory and filename to be used when saving directly or to be suggested when saving (using the save-as dialog). Click the ? button to learn more about the placeholders that can be used as filename pattern.
-
JPEG settings: Quality to be used when saving JPEG files
+
JPEG-instellingen: De kwaliteit waarmee de afbeeldingen worden opgeslagen als JPEG-bestand.
+
+
Bestemming
+
+ Na de schermopname vertoont Greenshot een eenvoudig menu waarmee u zelf een bestemmingsmap kiezen.
+ Is er geen noodzaak of heeft u geen behoefte om de bestemminsmap aan te passen,
+ dan kunt Greenshot instellen de schermopnames direct naar meerdrere bestemmingen op te slaan, zonder
+ tussenkomst van het keuzemenu.
+ Opmerking: Net als bij het exporteren vanuit het beeldbewerkingsvenster, zullen mogelijke bestemmingen
+ afhangen van de plugins welke met Greenshot zijn geïnstalleerd.
+
+
-
Printer settings
+
Printer-instellingen
-
Shrink printout to fit paper size: If the image would exceed paper size, it will be shrinked to fit on the page.
-
Enlarge printout to fit paper size: If the image is smaller than the paper size, it will be scaled to be printed as large as possible without exceeding paper size.
-
Rotate printout to page orientation: Will rotate a landscape format image by 90� for printing.
+
Afbeelding verkleinen tot pagina-afmetingen: Wanneer de afbeelding te groot zou zijn voor het papier, wordt deze verkleind zodat deze past op de pagina.
+
Afbeelding vergroten tot pagina-afmetingen: Wanneer de afbeelding kleiner is dan de papiergrootte, wordt deze vergroot zodat de pagina vult.
+
Afdruk roteren en aanpassen aan papier-oriëntatie: Afbeeldingen met horizontale oriëntatie worden 90° gedraaid voor een afdruk op papier met verticale oriëntatie.
+
Negatieve kleuren afdrukken: De afbeelding wordt in kleur-negatief afgedrukt. Bijvoorbeeld handig bij het afdrukken van een afbeelding met witte tekst tegen een donkere achtergrond (besparing toner/inkt).
+
Grijstinten forceren: Kleuren in de afbeelding worden voor de afdruk omgezet naar grijstinten.
+
+
+
Plugin-instellingen
+
+ Hier wordt de lijst met geïnstalleerde Greenshot-plugins weergegeven. Selecteer een plugin van de lijst and klik Instellingen
+ om de instellingen van de plugin aan te passen.
+
+
+
+
Expert-instellingen
+
+ Serieus: Als u geen idee heeft wat u doet en welke gevolgen het kan hebben, verander dan niets aan deze instellingen.
+
U wilt helpen?
- Op dit moment zoeken we geen hulp voor de ontwikkeling. Maar u kunt meerdere dingen doen om
+ Op dit moment zoeken we geen hulp bij de ontwikkeling. Maar u kunt wel iets doen om
het Greenshot ontwikkelteam te ondersteunen.
Bij voorbaat dank :)
@@ -297,35 +422,37 @@
Overweeg een donatie
- We stoppen een hoop tijd en werk in Greenshot om goede software gratis en open tot uw beschiking te stellen!
- Als u het gevoel heeft dat Greenshot u meer produktief maakt, u of uw firma een hoop tijd en geld bespaard
- of als u eenvoudig Greenshot en het idee van open source software goed vindt:
- Overweeg een donatie ter eren van onze inspanningen.
- Kijk AUB op onze home page om te lezen hoe u het Greenshot ontwikkelteam kunt ondersteunen:
- http://getgreenshot.org/support/
+ Wij verrichten een hoop werk aan Greenshot en besteden nogal wat tijd om
+ goede software gratis en vrij toegankelijk te houden. Als Greenshot
+ u helpt in uw werkzaamheden, als het u (of uw bedrijf)
+ tijd en geld bespaart, of u vindt het gewoon een fijn programma en
+ u staat positief tegenover het concept van open source software: Ondersteun ons werk dan met een donatie.
+ Bezoek onze website en lees daar hoe u het Greenshot team kunt ondersteunen:
+ http://getgreenshot.org/support/
Vertel het door
- Als u Greenshot goed vind, vertel het door: vertel uw vrienden en kollegas over Greenshot.
- Uw aanhang en achterban ook! :)
- Geef Greenshot goede kritiek in software portals of verlink Greenshot in uw blog of website.
+ Bevalt Greenshot u? Vertel het dan door: vertel uw vrienden en collega's over Greenshot.
+ En ook uw aanhang en achterban ! :)
+ Bespreek Greenshot met goede kritieken in software portals of plaats een verwijzing naar Greenshot in uw blog of op uw website.
Maak een vertaling
- Greenshot is niet in uw favorite taal vertaald? Als u denkt dat u software kunt vertalen dan bent u welkom!
- Als u een geregisteerde gebruiker bij sourceforge.net bent kunt u uw vertaling in onze
- vertalings tracker bekent maken.
- Voordat u begin is het verstandig om te kijken of Greenshot niet al in de taal vertaalt is, zie de
- downloads pagina. Ook kunt u op onze vertalings tracker kijken,
- het zou kunnen dat al iemand aan de vertaling werkt of misschien hierover een diskussie heeft.
+ Is Greenshot niet beschikbaar in uw favoriete taal en u denkt dat u software kunt vertalen dan bent u welkom!
+ Als geregisteerde gebruiker bij sourceforge.net kunt u uw vertaling in onze
+ vertalings tracker aanmelden.
+ Voordat u begint is het verstandig om te kijken of Greenshot niet al in de taal vertaald is, zie de
+ downloads pagina. Ook kunt u op onze vertalings tracker kijken.
+ Het zou namelijk kunnen dat iemand al aan de vertaling werkt of misschien hierover heeft gecommuniceerd.
- Een belangrijk punt is dat we vertalingen alleen op onze website zetten als het door iemand vertaalt is die
- ook een sourceforge.net gebruiker is. Omdat we zeer waarschijnlijk de vertaling niet begrijpen is het nodig
- dat we de gebruiker kunnen vinden, alleen dan kunnen we bij nieuwe Greenshot versies ook deze taal weer uitleveren.
+ Merk op dat vertalingen alleen kunnen worden geaccepteerd als ze afkomstig zijn van een geregistreerde
+ sourceforge.net-gebruiker. Wij kunnen niet elke vertaling doorgronden en daarom is het belangrijk dat we
+ de vertaler kunnen bereiken. Alleen op deze manier kunnen we bij nieuwe versies van Greenshot deze taal
+ laten bijwerken en weer uitleveren.
diff --git a/Greenshot/Languages/help-ru-RU.html b/Greenshot/Languages/help-ru-RU.html
index f04d2548d..33eb7d114 100644
--- a/Greenshot/Languages/help-ru-RU.html
+++ b/Greenshot/Languages/help-ru-RU.html
@@ -23,7 +23,7 @@
- Version 0.8
Содержание
diff --git a/Greenshot/Languages/help-sv-SE.html b/Greenshot/Languages/help-sv-SE.html
index 5225f0797..cdff974f1 100644
--- a/Greenshot/Languages/help-sv-SE.html
+++ b/Greenshot/Languages/help-sv-SE.html
@@ -316,7 +316,7 @@
Som standard lter Greenshot dig vlja en destination dynamiskt efter en skrmdump, genom att visa en liten meny med olika destinationer att vlja mellan. Om du inte vill eller behver vlja mellan destinationer direkt kanske du fredrar att konfigurera Greenshot till att exportera till en eller fler destinationer direkt, utan att visa destinationsvljaren.
- Liksom exportering frn redigerarfnstret kommer de visade destinationerna variera baserat p de insticksprogram du har installerade med Greenshot.
+ Liksom exportering frn redigerarfnstret kommer de visade destinationerna variera baserat p de insticksprogram du har installerade med Greenshot.
Translating Inno Setup's text into another language does not require modifying the source code. Simply make a copy of the Default.isl file (included with Inno Setup) and start editing the text in it. (Do not directly edit the Default.isl file, otherwise your changes will be lost when you install a new Inno Setup version.) See the "[Messages] Section" topic in the Inno Setup help file for some important tips.
-
Once you have finished creating the new .isl file, create a [Languages] section to tell the compiler to use it:
There are many contributed translations available for download on the Inno Setup Third-Party Files page, as well as a program to assist in editing the .isl file.
Inno Setup 2.0.6 adds complete support for MBCS. It does lead byte checking on all filename and constant parsing, so it should no longer mistake trail bytes for backslashes ("\") or braces ("{").
-
Versions prior to 2.0.6 did not include any special support for MBCS.
At the present time, there are no plans for a Windows Installer edition of Inno Setup. "Supporting" Windows Installer would likely involve a near-complete rewrite of the program.
No, nor is such a feature planned (it would be abused). If it is your intention to keep user interaction to a minimum, use the Disable* [Setup] section directives.
This message is typically displayed if you try to embed a quote (") character in a parameter's data, but do not double it as required. Read the "Parameters in Sections" topic in the Inno Setup help file for more information.
Your application is most likely not specifying pathnames on the files it is trying to open, so it is expecting to find them in the current directory. Inno Setup by default does not set the "Start In" field on shortcuts its creates; this causes Windows to pick a directory itself, which usually won't be the directory containing your application.
-
In virtually all cases, this is something that should be corrected at the application level. Properly designed GUI applications should not expect to be started from a particular directory; they should always specify full pathnames on files they open. In Delphi or C++Builder, for example, it's possible to get the full pathname of the directory containing the application EXE by calling: ExtractFilePath(ParamStr(0)). To get the full path of a file named "File.txt" in the application directory, use: ExtractFilePath(ParamStr(0)) + 'File.txt'.
-
If for some reason you cannot fix this at the application level, you can tell Inno Setup to set the "Start In" field by adding "WorkingDir: {app}" to your [Icons] entries.
This error message is displayed when a file pertaining to the installation (e.g., setup.exe, setup.1) has the wrong size, or part of a file fails a CRC check. It is not displayed for any other reason.
-
If your installation is distributed over the internet and you're getting a lot of reports of this error, it could be that your web server is delivering partial files by dropping connections prematurely. Have the affected users check the size in the bytes of the file(s) they downloaded.
-
If your installation is distributed via CD-ROM or floppy disk, it could be that the CD-ROM or floppy disk is bad, or possibly the drive is defective.
This happens when you change AppId between versions, or if AppId is not specified, AppName. If you do that, Setup has no way of knowing that the two versions are of the same application, and thus will create a new entry in Add/Remove Programs. Additionally, a new uninstall log file (unins???.dat) will be created. The obvious solution for this is to not change AppId or AppName.
-
If you must change AppName in a new version, set AppId to the value of AppId or AppName from the previous version.
This message normally means that you specified the "regserver" flag on a file that doesn't possess the ability to be registered. Remove the "regserver" flag from the [Files] entry and the message will go away.
There are several reasons why a directory may not be removed:
-
-
It already existed prior to installation. By default, the uninstaller plays it safe and doesn't remove directories that the installer didn't create.
-
It contains files or subdirectories. Use [UninstallDelete] if you need the uninstaller to delete additional files/directories.
-
A running process has the directory as its current directory.
-
-
Note: In Inno Setup versions prior to 2.0.1, directories must be specified in either the [Dirs] or [UninstallDelete] sections for them to be deleted by the uninstaller. In newer Inno Setup versions, directories created by [Files] section entries will be deleted automatically by the uninstaller if they didn't exist prior to installation.
At startup Setup looks in the registry to see if the same application was already installed previously, and if so, it will use the directory of the previous installation as the default directory presented to the user in the wizard. If you uninstall the application and run Setup again, it will use the new DefaultDirName setting. If you wish to disable this feature, set UsePreviousAppDir to "no".
First, make sure that you are not using the "nowait" or "waituntilidle" flags on the [Run] entry. These flags prevent Setup from waiting until the process completely terminates.
-
If you aren't using those flags and it still doesn't seem to be waiting for the program to finish, then likely what is happening is that the EXE you're running is spawning some other process and then terminating itself immediately, causing Setup to think the program has finished. This is known to happen with older InstallShield-based installers (to work around it, try using the /SMS switch).
-
A simple way to check if a program does that is to run "START /WAIT ProgramName.exe" from the command line, and see if you are returned to the command prompt before the program exits.
Beginning with Inno Setup 4.2.2, languages specified in the [Languages] section that cannot be displayed under the active Windows ANSI code page are not listed in the Select Setup Language dialog. For example, Russian text can only be displayed properly if the active code page is 1251; if the user isn't running code page 1251 they will not see Russian as an option.
-
On Windows XP, the active code page may be changed by going to Regional and Language Options in Control Panel, and setting Language for non-Unicode programs on the Advanced tab. On Windows 2000, the active code page may be changed by going to Regional Options in Control Panel, and clicking Set default....
-
If you are sure you're running in the correct code page and a language still isn't being listed, then most likely LanguageCodePage is set incorrectly inside the language's .isl file.
-
If you would like to force all languages to be visible regardless of whether they can be displayed properly under the active code page, set the ShowUndisplayableLanguages [Setup] section directive (new in Inno Setup 5.1.7).
-".myp" is the extension we're associating. "MyProgramFile" is the internal name for the file type as stored in the registry. Make sure you use a unique name for this so you don't inadvertently overwrite another application's registry key.
-
-
-
-Root: HKCR; Subkey: "MyProgramFile"; ValueType: string; ValueName: ""; ValueData: "My Program File"; Flags: uninsdeletekey
-
-
-"My Program File" above is the name for the file type as shown in Explorer.
-
-"DefaultIcon" is the registry key that specifies the filename containing the icon to associate with the file type. ",0" tells Explorer to use the first icon from MYPROG.EXE. (",1" would mean the second icon.)
-
-"shell\open\command" is the registry key that specifies the program to execute when a file of the type is double-clicked in Explorer. The surrounding quotes are in the command line so it handles long filenames correctly.
-
Environment variables are stored as string values in the registry, so it is possible to manipulate them using the [Registry] section. System-wide environment variables are located at:
Inno Setup does not currently have a specific feature for doing that, but you can make a copy of a file before it is replaced by using a [Files] section entry similar to this:
Beginning with Inno Setup 4.1.0, the [Dirs], [Files], and [Registry] sections support Permissions parameters for setting permissions on directories, files, and registry keys respectively.
-
If you have more advanced needs, take a look at SetACL.
If your application requires an updated version of COMCTL32.DLL, you can direct your users to
-download
-the COMCTL32 update from Microsoft, or call the COMCTL32 update from your installation by using the following lines:
-
-[Files]
-Source: "50comupd.exe"; DestDir: "{tmp}"
-
-[Code]
-function ShouldInstallComCtlUpdate: Boolean;
-var
- MS, LS: Cardinal;
-begin
- // Only install if the existing comctl32.dll is < 5.80
- Result := False;
- if GetVersionNumbers(ExpandConstant('{sys}\comctl32.dll'), MS, LS) then
- if MS < $00050050 then
- Result := True;
-end;
-
-[Run]
-Filename: "{tmp}\50comupd.exe"; Parameters: "/r:n /q:1"; Check: ShouldInstallComCtlUpdate
-
-
Don't try to install COMCTL32.DLL directly using the [Files] section; Microsoft does not allow this, and it's dangerous.
Currently supported platforms include every Windows release since 2000. No service packs or other OS updates are required on any of the supported platforms.
-
The 16-bit version of Inno Setup was discontinued starting with version 1.3. Support for Windows NT 3.51 was discontinued starting with version 3.0. Support for Windows 95, 98, Me, and NT 4.0 was discontinued starting with version 5.5.
A typical Inno Setup installation does not require administrative or "power user" privileges. However, there are exceptions as noted below.
-
Things that require administrative privileges:
-
-
Using "PrivilegesRequired=admin" in the script's [Setup] section. This causes Setup to abort with an error message if the user lacks administrative privileges.
-
Using the "restartreplace" flag in the [Files] section. This flag causes Inno Setup to call the MoveFileEx function, which attempts to write to "HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Control\ Session Manager". Write access to this key is restricted to Administrators.
-
Writing to any key under HKEY_USERS\.DEFAULT using the [Registry] section. Write access to this key is restricted to Administrators.
-
-
Things that require either administrative or "power user" privileges:
-
-
Using "PrivilegesRequired=poweruser" in the script's [Setup] section. This causes Setup to abort with an error message if the user lacks either administrative or "power user" privileges.
-
Using the "regserver" flag in the [Files] section. In most cases registering a DLL involves writing to HKEY_CLASSES_ROOT, a privilege not granted to ordinary users.
-
Using the "sharedfile" flag is the [Files] section. This flag causes Inno Setup to create/update a value in "HKEY_LOCAL_MACHINE\ SOFTWARE\ Microsoft\ Windows\ CurrentVersion\ SharedDLLs". Ordinary users are not allowed to write to that key.
-
Using the FontInstall parameter in the [Files] section.
-
Writing to any key under HKEY_LOCAL_MACHINE or HKEY_CLASSES_ROOT using the [Registry] section. Ordinary users are not allowed to write to those keys.
-
-
Inno Setup itself does not require write access to the WINNT directory, or any other registry keys not mentioned above.
-
What is different when an installation is run by a user without administrative privileges?
-
-
The registry key for the Add/Remove Programs Control Panel entry is created under HKEY_CURRENT_USER instead of HKEY_LOCAL_MACHINE. Thus, only the user who installed the program will see an Add/Remove Programs entry for it.
-
The "{group}" constant always points to the current user's profile, as opposed to the All Users profile.
-
All "{common...}" constants are equivalent to the "{user...}" constants.
-
The program may be uninstalled by any user. (When an administrator installs a program, only an administrator is allowed to uninstall it.)
Inno Setup places no arbitrary limits on how many files, shortcuts, registry entries, etc. that you may include in an installation. However, keep in mind that Setup does need memory for each entry in a script. For example, roughly 120 bytes of memory is needed for each [Files] entry.
-
In Inno Setup 3.x and earlier, installations and individual files cannot exceed 2 GB, because it does not use 64-bit arithmetic in most places. This has been addressed in Inno Setup 4.
When Cancel is clicked, Setup will begin reverting changes it's made so far in the very same manner as the Uninstall program. Thus, a partially installed application isn't left over.
-
-
-
-
-
diff --git a/Greenshot/tools/innosetup/islzma.dll b/Greenshot/tools/innosetup/islzma.dll
deleted file mode 100644
index 49395ada5..000000000
Binary files a/Greenshot/tools/innosetup/islzma.dll and /dev/null differ
diff --git a/Greenshot/tools/innosetup/islzma32.exe b/Greenshot/tools/innosetup/islzma32.exe
deleted file mode 100644
index 1c52e778c..000000000
Binary files a/Greenshot/tools/innosetup/islzma32.exe and /dev/null differ
diff --git a/Greenshot/tools/innosetup/islzma64.exe b/Greenshot/tools/innosetup/islzma64.exe
deleted file mode 100644
index 2c9f30578..000000000
Binary files a/Greenshot/tools/innosetup/islzma64.exe and /dev/null differ
diff --git a/Greenshot/tools/innosetup/isscint.dll b/Greenshot/tools/innosetup/isscint.dll
deleted file mode 100644
index ac5707ea3..000000000
Binary files a/Greenshot/tools/innosetup/isscint.dll and /dev/null differ
diff --git a/Greenshot/tools/innosetup/isunzlib.dll b/Greenshot/tools/innosetup/isunzlib.dll
deleted file mode 100644
index 49929d3c8..000000000
Binary files a/Greenshot/tools/innosetup/isunzlib.dll and /dev/null differ
diff --git a/Greenshot/tools/innosetup/iszlib.dll b/Greenshot/tools/innosetup/iszlib.dll
deleted file mode 100644
index 841834f28..000000000
Binary files a/Greenshot/tools/innosetup/iszlib.dll and /dev/null differ
diff --git a/Greenshot/tools/innosetup/license.txt b/Greenshot/tools/innosetup/license.txt
deleted file mode 100644
index 5a528db0b..000000000
--- a/Greenshot/tools/innosetup/license.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-Inno Setup License
-==================
-
-Except where otherwise noted, all of the documentation and software included
-in the Inno Setup package is copyrighted by Jordan Russell.
-
-Copyright (C) 1997-2013 Jordan Russell. All rights reserved.
-Portions Copyright (C) 2000-2013 Martijn Laan. All rights reserved.
-
-This software is provided "as-is," without any express or implied warranty.
-In no event shall the author be held liable for any damages arising from the
-use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter and redistribute it,
-provided that the following conditions are met:
-
-1. All redistributions of source code files must retain all copyright
- notices that are currently in place, and this list of conditions without
- modification.
-
-2. All redistributions in binary form must retain all occurrences of the
- above copyright notice and web site addresses that are currently in
- place (for example, in the About boxes).
-
-3. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software to
- distribute a product, an acknowledgment in the product documentation
- would be appreciated but is not required.
-
-4. Modified versions in source or binary form must be plainly marked as
- such, and must not be misrepresented as being the original software.
-
-
-Jordan Russell
-jr-2010 AT jrsoftware.org
-http://www.jrsoftware.org/
diff --git a/Greenshot/tools/innosetup/whatsnew.htm b/Greenshot/tools/innosetup/whatsnew.htm
deleted file mode 100644
index c7a64dd44..000000000
--- a/Greenshot/tools/innosetup/whatsnew.htm
+++ /dev/null
@@ -1,1168 +0,0 @@
-
-
-
-Inno Setup 5 Revision History
-
-
-
-
-
-
Windows 8 change: [Icons] section flag excludefromshowinnewinstall now additionally prevents the new shortcut from being automatically pinned the Start screen.
-
Added new command line parameters supported by Setup: /HELP and /?. Cause Setup to display the list of accepted command line parameters in a message box, exiting with exit code 0 afterwards. Ignored if the UseSetupLdr [Setup] section directive was set to no.
-
Added new command line parameter supported by Inno Setup's own installer: /PORTABLE=1. Causes Inno Setup's own installer to not create an uninstaller nor an entry in the Add/Remove Programs Control Panel applet. Also supported by QuickStart Pack's installer.
-
Added workaround for bug in 64-bit Windows which in some cases would cause Windows to display an error message when a user tries to change the icon of an installed shortcut.
-
Updated the compiler and document icons, created by Motaz.
-
Restart Manager: If Setup is not running silently and is unable to close all applications using files that need to be updated, it will now ask the user to abort, retry, or ignore. Previously it always ignored.
Added official Corsican and Nepali translations. The Nepali translation requires Unicode Inno Setup.
-
Inno Setup Preprocessor (ISPP) changes:
-
-
Added directive #redim to increase or decrease the dimension of an existing array variable.
-
Added function DimOf. Returns the dimension of the specified identifier.
-
-
-
Pascal Scripting changes:
-
-
Added new function: ExtractTemporaryFiles. This function is like ExtractTemporaryFile but supports wildcards and doesn't ignore directory information.
-
When ExtractTemporaryFile or ExtractTemporaryFiles extracts a file, this is now logged.
-
Unicode Inno Setup: Now has an Int64 type, supported by IntToStr. Also added new StrToInt64, StrToInt64Def, and GetSpaceOnDisk64 support functions.
-
-
-
If the Flags parameter of a [Files] entry includes isreadme and the entry also has a BeforeInstall or AfterInstall parameter, the BeforeInstall or AfterInstall functions will now only be called when the file is installed and no longer a second time when the file is viewed after the installation has completed.
-
[Setup] section directive VersionInfoProductTextVersion, which sets the textual product version value, is now truncated at 50 characters instead of 20. Contributed by Lukas Ais via GitHub.
-
The Inno Setup help file source code has been moved into the main Inno Setup source code repository.
-
Fix: [Setup] section directive CloseApplicationsFilter was partially case sensitive.
-
Unicode [Code] based on RemObjects Pascal Script Git commit 31abd2925837d85a6965b5325e8fb7835ca73ea8.
-
QuickStart Pack: No longer offers to download and install InnoIDE (which is no longer maintained by its author) unless /ALLOWINNOIDE=1 is specified on the command line. If you're still using InnoIDE it is recommended you switch to Inno Script Studio (which QuickStart pack can download and install).
-
Minor tweaks.
-
-
-
5.5.2 (2012-10-08)
-
-
Added the Windows 8 "compatibility" section to the various manifest resources used by Inno Setup.
-
Added constants {userpf} and {usercf}. Only Windows 7 and later supports {userpf} and {usercf}; if used on previous Windows versions, they will translate to the same directories as {localappdata}\Programs and {localappdata}\Programs\Common.
-
Pascal Scripting: Added new RegisterExtraCloseApplicationsResources event function and also added new RegisterExtraCloseApplicationsResource support function. These functions can be used to register extra files which Setup should check for being in-use.
-
Added new command line parameters supported by Setup: /CLOSEAPPLICATIONS and /RESTARTAPPLICATIONS. These can be used to override the CloseApplications and RestartApplications directives.
Unicode [Code] based on RemObjects Pascal Script Git commit 52291ffbfc14f3cf1a445f3e88c6902e13fbdf78.
-
Minor tweaks.
-
-
-
5.5.1 (2012-07-09)
-
-
Added official Greek translation.
-
Updated the official Catalan, Czech, Danish, Finnish, French (Standard), German, Hebrew, Hungarian, Italian, Japanese, Norwegian (Bokmal), Polish, Portuguese (Brazil), Portuguese (Portugal), Russian, Serbian (Cyrillic), Serbian (Latin), Slovenian, Spanish, and Ukrainian translations for the changes introduced by the previous version.
-
Demoted the official Basque and Slovak translations to unofficial because of a lack of updates by the maintainers. To send updates yourself, see this post for what needs updating and use this form to send updates (or use GitHub). See the Inno Setup Translations page for more information.
-
Fix: The Preparing to Install wizard page's detection of files that need to be updated but are in use or queued (by some other installation) to be replaced or deleted on the next restart did not work for [Files] and [InstallDelete] entries with a Components or Tasks parameter.
-
Minor tweaks.
-
-
-
5.5.0 (2012-05-29)
-
-
Non-Unicode Inno Setup OS requirements change: Windows 95, 98, Me, and NT 4.0 are no longer supported. Like the Unicode version, Windows 2000 is now the minimum supported operating system.
-
The MinVersion and OnlyBelowVersion directives and parameters now require only a single version number. For example: MinVersion=5.1. For compatibility with previous versions of Inno Setup, separate Windows 95/98/Me and Windows NT version numbers may still be specified, but these aren't used anymore.
-
On Windows Vista and newer, Setup now supports the Windows Restart Manager API to close and restart applications using files that need to be updated:
-
-
Added new [Setup] section directive: CloseApplications, which defaults to yes. If set to yes and Setup is not running silently, Setup will now pause on the Preparing to Install wizard page if it detects applications using files that need to be updated by the [Files] or [InstallDelete] section, showing the applications and asking the user if Setup should automatically close the applications and restart them after the installation has completed. If set to yes and Setup is running silently, Setup will always close and restart such applications, unless told not to via the command line (see below).
-
Added new [Setup] section directive: CloseApplicationsFilter, which defaults to *.exe,*.dll,*.chm. Controls which files Setup will check for being in use. Setting this to *.* can provide better checking at the expense of speed.
-
Added new [Setup] section directive: RestartApplications, which defaults to yes. Note: for Setup to be able to restart an application after the installation has completed, the application needs to be using the Windows RegisterApplicationRestart API function.
-
Added new command line parameters supported by Setup: /NOCLOSEAPPLICATIONS and /NORESTARTAPPLICATIONS. These can be used to override the new CloseApplications and RestartApplications directives.
-
Added new [Code] support function: RmSessionStarted.
-
TWizardForm: Added new PreparingMemo property.
-
-
-
The Preparing to Install wizard page now also checks if one or more files specified in the [InstallDelete] section were queued (by some other installation) to be replaced or deleted on the next restart, making Setup stop on the page if it does. Previously it only checked files specified in the [Files] section.
-
Setup now additionally hides the Back and Next buttons while the PrepareToInstall [Code] event function is running. Previously it only disabled itself.
-
Added new [Setup] section directive: AllowNetworkDrive, which defaults to yes. If set to no, the user will not be allowed to enter a network drive on the Select Destination Location page of the wizard. Note: to fully disallow installation to network locations, you must also set AllowUNCPath to no.
-
Windows 7 changes:
-
-
Added new [Icons] section flag: preventpinning. Prevents a Start menu entry from being pinnable to Taskbar or the Start Menu on Windows 7 (or later). This also makes the entry ineligible for inclusion in the Start menu's Most Frequently Used (MFU) list. Ignored on earlier Windows versions. Contributed by Milan Burda via GitHub.
-
Windows 7 SP1 fixed the issue with EstimatedSize values in the Uninstall registry key and on Windows 7 SP1 or newer Setup now sets EstimatedSize even for sizes of 4GB or more.
-
-
-
Improved the "auto-retry" feature of the [Files] section: it now automatically retries even if the restartreplace [Files] section flag is used.
-
Pascal Scripting: Changed the InstallOnThisVersion support function to return a Boolean value. If an invalid version string is passed, an exception will be raised.
-
Added 128x128 and 256x256 sizes to the compiler and document icons, created by Motaz.
New custom messages: AutoStartProgramGroupDescription, AutoStartProgram, AddonHostProgramNotFound.
-
Removed messages: ToUNCPathname.
-
- Note: only the official English and Dutch (Netherlands) translations have been updated for these changes at this moment. See the Inno Setup Translations page for more information.
-
-
Inno Setup Preprocessor (ISPP) changes:
-
-
Added function DirExists.
-
The ISPP source code has been moved into the main Inno Setup source code repository.
-
-
-
Unicode [Code] based on RemObjects Pascal Script Git commit e5a93a963f785e89810e61e3eb5e2b6ee3efd3e7.
Setup now only allows the "Don't create a Start Menu folder" check box to suppress the creation of shortcuts under {group}. Previously, it would also suppress the creation of shortcuts in other locations, such as {userstartup}, on entries that lacked a Tasks parameter.
-
Setup now doesn't count files with Tasks/Check parameters when calculating the disk space shown at the bottom of the Select Components page.
-
Improved throughput of external file copying on some devices.
-
On Unicode, Setup now supports Rich Edit 4.1 when available.
-
Inno Setup Preprocessor (ISPP) changes:
-
-
Documentation improvements: Added the functions available from ISPPBuiltins.iss to the help file.
-
#ifexist/#ifnexist: For consistency with ISPP functions, prepend SourcePath if the filename is relative, and also support prefix expansion.
-
ReadReg: Now only requests KEY_QUERY_VALUE access on the key. Previously, it requested KEY_ALL_ACCESS.
-
-
-
The Inno Setup source code is now also available as a Git repository at GitHub. This should make it easier to contribute to Inno Setup, see GitHub Help - Fork A Repo for more info.
-
Added official Serbian (both Latin and Cyrillic) and Ukrainian translations.
-
Minor tweaks.
-
-
-
5.4.2 (2011-03-17)
-
-
Windows 7 change:
-
-
Added new [Icons] section flag: excludefromshowinnewinstall. Prevents the Start menu entry for the new shortcut from receiving a highlight on Windows 7. Ignored on earlier Windows versions.
-
-
-
Compiler IDE change:
-
-
Changed shortcut for Edit | Complete Word to Alt+Right (but still recognize Ctrl+Space). Reportedly, Ctrl+Space conflicts with the Chinese IME.
-
-
-
Fixes:
-
-
Inno Setup Preprocessor: #include handling of '.\' and '..\' now treats such filenames as relative to the directory containing the current file, not to the current directory (which is undefined).
-
On the 5.4.1 Unicode compiler, trying to build a multi-language installer while running under a DBCS code page could unexpectedly result in "Illegal null character" errors.
-
On Unicode, string-type parameters passed to BeforeInstall and AfterInstall functions were being converted to ANSI.
-
-
-
-
-
5.4.1 (2011-02-09)
-
-
Inno Setup Preprocessor (ISPP) changes:
-
-
ISPP is now an official part of Inno Setup and is included in the standard Inno Setup installer instead of only being included in the QuickStart Pack installer.
-
It is now possible to enable ISPP preprocessing on .isl files by adding a line saying #preproc ispp at the top of the .isl file.
-
With the exception of Exec, ReadIni, and WriteIni, all ISPP functions that take filenames have been changed to interpret the filenames as relative to SourcePath instead of the current directory. Additionally, these functions, the #include directive, and the #file directive now support prefix expansion (e.g. 'compiler:') in filenames.
-
The #include directive no longer searches the current directory.
-
Builtins.iss has been renamed to ISPPBuiltins.iss.
-
The Compiler IDE no longer displays a separate ISPP version number in its title bar.
-
-
-
Compiler IDE changes:
-
-
The Edit | Replace | Replace All command now actually replaces all occurrences, instead of doing a Delphi-style "From Cursor" replacement. Also it now counts all replacements as a single undo action and shows how many occurrences were replaced.
-
Unicode change: Added a new File | Save Encoding submenu. It now defaults to preserving the UTF-8 BOM of existing files, even if the UTF-8 encoding isn't really needed.
-
-
-
Unicode change: Added support for Unicode characters in DLL filenames (not specified directly in the script, but returned by constants like {app}). This fixes the "Cannot Import" error seen with for example the CodeDll.iss example script when uninstalling from an {app} path containing non-ANSI characters.
-
Two new Setup exit codes related to the Preparing to Install stage were added. See the help file for more information.
-
Minor tweaks.
-
-
-
5.4.0 (2010-10-31)
-
-
Compiler IDE changes:
-
-
The editor component has been changed from SynEdit to Scintilla.
-
Autocompletion support has been added to all sections except for [Messages], [CustomMessages], and [Code].
-
Brace highlighting has been added to all sections.
-
Syntax errors are now underlined during editing. (Support for the [Code] section is limited.)
-
Constants are now highlighted.
-
Variable-pitch fonts may now be selected as the editor font.
-
ISPP inline directives ({#...}) are now consistently highlighted in all contexts.
-
Zooming is now supported.
-
Added new options: Word wrap (default: off), Auto indent mode (default: on), Show indentation guides (default: off), Invoke autocomplete automatically (default: on), Underline syntax errors (default: on), and Use tab character (default: off).
-
-
-
Setup now instructs edit controls which are used to input a file or folder name to use AutoComplete to help complete file system paths.
-
On disk space checks, Setup now queries the nearest volume mount point rather than the root.
-
The default directory and Start Menu folder names specified via the /DIR=, /GROUP=, and /LOADINF= command line parameters now may include an "expand:" prefix which instructs Setup to expand any constants in the name. For example: /DIR="expand:{pf}\My Program".
-
Pascal Scripting changes:
-
-
TNewProgressBar: Added new Style and State properties. See the CodeClasses.iss example script for an example.
-
TBitmapImage: Added new OnClick and OnDblClick properties. See the CodeClasses.iss example script for an example.
-
-
-
Dropped Itanium-specific 64-bit support for the [Files] section's regtypelib flag and the [Registry] section's Permissions parameter. These features depended on an Itanium-specific "helper" binary, which we no longer have the ability to test or build. (x64 support for these features is unaffected.)
-
Updated bzip2 library to version 1.0.6.
-
Minor tweaks.
-
-
-
-
-
5.3.11 (2010-09-17)
-
-
QuickStart Pack: Now offers to download and install InnoIDE instead of ISTool. InnoIDE is an easy to use Inno Setup Script editor by Graham Murt and meant as a replacement of the standard Compiler IDE that comes with Inno Setup. Using InnoIDE is especially recommended for new users. Note: unlike ISTool, InnoIDE supports Unicode scripts.
-
Unicode changes:
-
-
Previously, if a Unicode installer included translations for both Traditional Chinese and Simplified Chinese using the language IDs $0404 (Taiwan) and $0804 (PRC), a user running under another Traditional Chinese language ID—such as $0C04 (Hong Kong)—could have incorrectly received the Simplified Chinese translation by default if it was listed first in the script's [Languages] section. Now, like the ANSI version of Setup, Traditional Chinese and Simplified Chinese are treated as completely separate languages. Thus, provided other options are available, Simplified Chinese will not be considered for selection as the default language on Traditional Chinese systems, and vice versa.
-
Compiler IDE editor updated to the latest UniSynEdit version. This fixes the extra empty line appearing at the end of scripts when first saved.
-
Ctrl+V/Esc/etc. are no longer intercepted by the Compiler IDE's main window while the Find dialog has the focus.
-
Based on RemObjects Pascal Script SVN code revision 233. This fixes GetExceptionMessage always returning "(There is no current exception)" on Unicode.
-
-
-
Compiler IDE: Added new Build | Open Output Folder command.
-
In certain cases, applications started via postinstallnowait [Run] entries did not come to the foreground (top of the Z-order) as expected. This could occur if Setup exited before the spawned process(es) were able to initialize, causing Windows to bring the window that was underneath Setup in the Z-order to the foreground instead. Now, when postinstallnowait [Run] entries are processed, Setup will wait briefly (up to one second) before exiting for another process to bump Setup from the foreground.
-
To help protect applications against potential DLL preloading attacks, Setup now always specifies a working directory on shortcuts it creates. If a WorkingDir parameter is not specified or is blank, Setup will try to extract a directory name from the Filename parameter. If for some reason that fails, the working directory will be set to {sys}.
-
To help protect installers against potential DLL/EXE preloading attacks, Setup/Uninstall now calls SetDllDirectory to remove the current directory from the DLL search order, and SetSearchPathMode to prevent SearchPath and CreateProcess from searching the current directory before system directories.
-
If the Filename parameter of a [Run]/[UninstallRun] entry or Exec/ShellExec call does not include a path, and a WorkingDir value is not provided, Setup/Uninstall will now specify a known-safe default (currently {sys}) for the process's initial current directory, instead of allowing the process to inherit Setup/Uninstall's current directory. You should not rely on this behavior, however; it is best to always specify a path in the Filename parameter.
-
When an Open or Save common dialog is dismissed, the current directory is now restored to its original value.
-
Updated bzip2 library to version 1.0.5.
-
QuickStart Pack: Any ISPP function that uses the system's DLL search path such as GetFileVersion will no longer search the current directory.
-
Minor tweaks.
-
-
-
5.3.10 (2010-06-11)
-
-
Added .NET Framework 4.0 support:
-
-
Added constants {dotnet40}, {dotnet4032}, and {dotnet4064}. An exception will be raised if an attempt is made to expand these constants on a system with no .NET Framework version 4.0 present.
-
[Files] section flag gacinstall can now be used on .NET Framework 4.0 assemblies too.
-
-
-
Windows 7 changes:
-
-
[Icons] section flag foldershortcut is now ignored when running on Windows 7 (or later), as folder shortcuts do not expand properly on the Start Menu anymore.
-
-
-
[Setup] section directive changes:
-
-
When SignedUninstaller is set to yes, any temporary self-copies used by Setup are now digitally signed too.
-
Uninstallable may now be set to a boolean expression, which may contain calls to check functions. For example: Uninstallable=not IsTaskSelected('portablemode'). See the Uninstallable documentation for details.
-
AppVerName is no longer required if AppVersion is specified. It will now effectively default to: {cm:NameAndVersion,[AppName],[AppVersion]}. The Compiler IDE's New Script Wizard now also asks for an AppVersion instead of an AppVerName.
-
If a text VersionInfo* directive is set to an empty string (as opposed to not being specified), then the version info field is really set to an empty string now, instead of forcing a default value.
-
VersionInfoProductTextVersion now defaults to VersionInfoProductVersion if set, else AppVersion if AppVersion is set and does not include constants, else VersionInfoTextVersion.
-
-
-
Unicode Inno Setup: An issue with the taskbar button re-appearing on /VERYSILENT installs has been fixed.
-
Unicode [Code] based on RemObjects Pascal Script SVN code revision 228.
-
Minor tweaks.
-
-
-
5.3.9 (2010-04-10)
-
-
For better appearance on Windows 7 and Vista when ClearType is enabled, Tahoma is the new default font used by Setup and Uninstall. A new [Setup] section directive DefaultDialogFontName has also been added to make it easy to override the default dialog font for all languages that do not have a custom DialogFontName setting. If you would like to revert to the dialog font used in previous versions of Inno Setup (Microsoft Sans Serif if available, else MS Sans Serif), set DefaultDialogFontName to an empty string (DefaultDialogFontName=).
-
Added new [Setup] section directive: DisableWelcomePage to hide the Welcome wizard page. Doing so is recommended by the Aero wizard guidelines. Additionally, the ShouldSkipPage event function is now also called for wpWelcome.
-
When Setup is not running silently, the Ready To Install wizard page now ignores attempts to skip it when no other wizard page before it has been shown yet.
-
Added LZMA2 compression support:
-
-
Updated the LZMA SDK compression code to version 9.10 which adds support for LZMA2 compression. LZMA2 is a modified version of LZMA that offers a better compression ratio for uncompressible data (random data expands about 0.005%, compared to 1.35% with original LZMA), and optionally can compress multiple parts of large files in parallel, greatly increasing compression speed but with a possible reduction in compression ratio. LZMA2 compression may be activated by setting the Compression [Setup] section directive to lzma2, and lzma2 is now also the default value.
-
-
-
Added various new [Setup] section directives with names that start with LZMA to fine-tune LZMA and LZMA2 compression parameters, including LZMADictionarySize which allows the LZMA dictionary size to be increased up to 256 MB from the previous maximum of 64 MB. Review the memory requirements listed in the Compression topic before using.
-
Tweaked the JMP/CALL instruction optimization algorithm for slightly better compression of executable files. (On Inno Setup's own installer, this saved about 2 KB.)
-
Improved compression of x64 executable files: just like for x86 executable files, JMP/CALL instruction optimization is now performed for x64 executable files. On average, this will reduce the compressed size of x64 executable files by 2-3%.
-
[Setup] section directive DiskSliceSize can now be set to max, and max is now also the default value.
-
Windows 7 change: The Compiler IDE is now pinnable. Also, files that are opened via the Welcome dialog, MRU list, and drag & drop now get added to the Jump List.
-
Windows 7 and Vista changes:
-
-
Before deleting a pinned shortcut, Uninstall now automatically removes it from the current user's Start menu pinned list and on Windows 7 also from the taskbar.
-
Changed the icon that is shown on Select Start Menu Folder wizard page. Previously, it used the same icon as the preceding Select Destination Location page, but that was never really the intention.
-
When Setup and Uninstall respawn for elevation, any SUBST'ed drives in the EXE filename are now expanded before the respawn, since the elevated user will not retain the original user's SUBST mappings. Fixes error seen when starting Setup from a SUBST'ed drive.
-
-
-
Setup now uses the SHA-1 algorithm instead of MD5 for file checksums and various internally-used hashes.
-
Pascal Scripting: Added support functions GetSHA1OfString, GetSHA1OfUnicodeString, and GetSHA1OfFile.
-
QuickStart Pack: Added ISPP functions GetSHA1OfString, GetSHA1OfUnicodeString, and GetSHA1OfFile.
-
[Icons] section parameter AppUserModelID is now also used on Windows Server 2008 R2.
Unicode Inno Setup: Added workaround for upstream Delphi bug that could cause Setup (versions 5.3.6 to 5.3.8) to display a "Stream read error" error message at startup on Windows 2000 systems that did not have Service Pack 4 installed.
-
Compiler IDE change: the Tools | Configure Sign Tools... dialog now allows editing of existing Sign Tools.
-
The uninstall program's version is now 51.(10)52.0.0.
-
Minor tweaks.
-
-
-
5.3.8 (2010-02-18)
-
-
Added new [Setup] section directive: UsePreviousLanguage. When this directive is yes, the default, at startup Setup will look in the registry to see if the same application is already installed, and if so, it will use the language of the previous installation as the default language selected in the list of available languages on the Select Language dialog. Note that this directive does not change the language used by the Select Language dialog itself because it cannot assume that the current user understands the same languages as the previous user. UsePreviousLanguage must be set to no when AppId includes constants.
-
On Windows Vista and newer, Uninstall no longer blocks system shutdown until the uninstallation has actually started. This should make the Windows 7 Logo Kit (which wrongly tests any .exe in the application directory including the uninstaller) happy when it tries to shutdown an Uninstall sitting on its confirmation prompt.
-
On Windows NT and newer, PrivilegesRequired=lowest now has an additional effect: the uninstall info root key will always be HKEY_CURRENT_USER, and the "common" forms of the Shell Folder constants are always mapped to the "user" forms, even if administrative privileges are available.
-
[Setup] section directive CreateUninstallRegKey may now be set to a boolean expression, which may contain calls to check functions. For example: CreateUninstallRegKey=not IsTaskSelected('portablemode'). See the CreateUninstallRegKey documentation for details.
-
The Preparing to Install wizard page now offers the user an option to directly reboot instead of just saying a reboot is needed. To trigger this option from a PrepareToInstall event function set its new NeedsRestart parameter to True.
-
In the MinVersion and OnlyBelowVersion directives and parameters, .x is now treated the same as .0x when a major version of 5 or higher is specified. Thus, you now have the option of using either 5.01 or 5.1 to specify Windows XP. However, to maintain compatibility with existing scripts, 4.x will still be interpreted as 4.x0.
-
Pascal Scripting: Added new PageIndexFromID support function.
The uninstall program's version is now 51.(10)51.0.0.
-
Minor tweaks.
-
-
-
5.3.7 (2010-01-06)
-
-
The PrivilegesRequired [Setup] section directive can now be set to lowest. On Windows Vista and later this instructs Setup to not request elevated rights (via a User Account Control dialog) even if it was started by a member of the Administrators group. Do not use this setting unless you are sure your installation will run successfully on unprivileged accounts. If you were using PrivilegesRequired=none before, it is recommended to switch to PrivilegesRequired=lowest.
-
Added new Compiler IDE option: Autosave before compiling.
-
[Tasks] section flags checkedonce and unchecked may now be combined. This combination specifies the task to be unchecked by default on the first install, and always unchecked by default on subsequent installs as well.
-
A problem with "Not Implemented" errors when Setup or Uninstall was run on Windows 7 under special conditions such as from a non-interactive service was fixed.
-
Changed the CodePrepareToInstall.iss example script to use the RunOnce registry key instead of a shortcut placed in {commonstartup}.
-
Pascal Scripting: the Non Unicode compiler now has a PAnsiChar type just like the Unicode compiler.
-
Added official Japanese translation.
-
Unicode [Code] based on RemObjects Pascal Script SVN code revision 197.
-
Minor tweaks.
-
-
-
5.3.6 (2009-11-14)
-
-
Windows 7 change:
-
-
Added new [Setup] section directive: UninstallDisplaySize. On Windows 7 and newer, Setup uses this directive to set the EstimatedSize value in the Uninstall registry key when possible since the Windows 7 Add/Remove Programs Control Panel (called Program and Features) no longer automatically calculates it. If an UninstallDisplaySize is not set, Setup estimates the size itself by taking the size of all files installed and adding any ExtraDiskSpaceRequired values set. Note: Windows 7 only supports the display of values smaller than 4 GB.
-
-
-
Pascal Scripting now supports IUnknown based COM. Previously it only supported IDispatch based COM but a growing number of Windows API functions are COM based without implementing the IDispatch interface, and you can now use these as well. See the new CodeAutomation2.iss example script for an example. Note: this is only supported by Unicode Inno Setup at the moment, because of Delphi 2's limitations (Delphi 2 is used to compile Non Unicode Inno Setup):
-
-
Added StringToGUID, CreateComObject, and OleCheck support functions.
-
Added HResult, TGUID, TCLSID, and TIID support types.
-
-
-
The compiler no longer allows a single LanguageCodePage directive to be applied to multiple languages at once. If you were using this to force Non Unicode Setup to allow the user to select any language regardless of the system code page, set [Setup] section directive ShowUndisplayableLanguages to yes instead.
-
Added new CodePrepareToInstall.iss example script.
-
Fix: Unicode Pascal scripting: passing a very long string to Format caused an error.
-
Minor tweaks.
-
-
-
5.3.5 (2009-09-23)
-
-
Windows 7 changes:
-
-
Setup, Uninstall and custom TOutputProgressWizardPage pages now make use of the new Windows 7 taskbar functionality to display progress, pause and error indicators on their taskbar buttons.
-
Added new [Icons] section parameter: AppUserModelID. Specifies the Windows 7 Application User Model ID for the shortcut. Ignored on earlier Windows versions and on server versions. This parameter can include constants.
-
-
-
Windows 7 and Vista changes:
-
-
Setup, Uninstall and custom TOutputProgressWizardPage pages now display pause and error indicators on their progress bars.
-
Setup and Uninstall now call the Windows API function ShutdownBlockReasonCreate to set the shutdown block reason string to be displayed to the user if system shutdown is initiated. Note: this change is purely cosmetic, the fact that Setup and Uninstall block system shutdown is not new.
-
-
-
Pascal Scripting changes:
-
-
TWinControl: Added new ParentBackground property. By setting this to False, you can ensure the background of a TPanel will always display the color assigned to its Color property, instead of it becoming transparent under certain conditions. See the CodeClasses.iss example script for an example.
-
-
-
The Unicode compiler now behaves identical to the Non Unicode compiler if a language uses more than one .isl file (it no longer requires the LanguageCodePage to be set in each file), or if a languages LanguageCodePage is overwritten from the .iss file (it no longer ignores this), or if any language specific plain text ANSI LicenseFile, InfoBeforeFile, or InfoAfterFile is used (it now converts these to Unicode using the languages LanguageCodePage at compile-time, instead of using the system codepage at run-time).
-
Fix: Pascal scripting: passing a Unicode string to some built-in functions like Copy caused the string to be converted to ANSI.
-
The uninstall program's version is now 51.(10)50.0.0.
-
Minor tweaks.
-
-
-
5.3.4 (2009-08-15)
-
-
On Windows 7 the Compiler IDE now makes use of the new Windows 7 taskbar functionality to display progress, pause and error indicators on its taskbar button.
-
Pascal Scripting: Documented function IDispatchInvoke, which can be used to access a COM Automation property or method whose name is a reserved word.
-
Fix: Unicode [Registry] section entries with ValueType set to binary did not set the correct value.
-
Fix: Pascal scripting: setting a COM Automation property or method parameter to a Unicode string variable caused an 'Invalid Type' error.
-
-
-
5.3.3 (2009-08-01)
-
-
[Setup] section directives VersionInfoProductVersion now sets the binary product version value instead of the textual product version value.
-
Added new [Setup] section directive: VersionInfoProductTextVersion, which sets the textual product version value. Its default value is VersionInfoProductVersion if set, else VersionInfoVersion.
-
[Setup] section directives DisableDirPage and DisableProgramGroupPage can now be set to auto. If they are, at startup Setup will look in the registry to see if the same application is already installed, and if so, it will hide the pages automatically.
-
Pascal Scripting changes:
-
-
WizardForm.PrevAppDir is now available and returns the directory of the previous installation. Returns an empty string if there's no previous installation or if UsePreviousAppDir is set to no or if Uninstallable was previously set to no.
-
While running any PrepareToInstall event function Setup now displays the Preparing to Install wizard page instead of the Ready to Install page and disables itself.
-
-
-
Added the Windows 7 "compatibility" section to the various manifest resources used by Inno Setup.
-
Documentation improvements.
-
-
-
5.3.2-beta (2009-05-29)
-
-
Replaced constant {regasmexe} with {dotnet11} and {dotnet20}.
-
Pascal Scripting: Added new PrepareToInstall event function. Return a non empty string from this function to instruct Setup to stop at the Preparing to Install wizard page showing the returned string as the error message.
-
Minor fixes and tweaks.
-
-
-
5.3.1-beta (2009-05-15)
-
-
[Setup] directive AppMutex and support function CheckForMutexes change: to specify a mutex name containing a comma you can now escape the comma with a backslash.
-
Minor tweaks.
-
-
-
5.3.0-beta (2009-04-22)
-
-
Added .NET support (these cause an internal error if used on a system with no .NET Framework present):
-
-
Added new [Files] section flag: gacinstall.
-
Added new [Files] section parameter: StrongAssemblyName.
-
Added new constants: {regasmexe}, {regasmexe32}, {regasmexe64}.
-
-
-
MinVersion parameter/directive change: if you leave one of the versions empty then it will use the default MinVersion for that platform.
-
Pascal Scripting: Added new MinimizePathName support function.
-
Added Unicode support: there's now a second version of Inno Setup available called Unicode Inno Setup. Key features of this version are its ability to display any language on any system regardless of the system code page, and its ability to work with Unicode filenames. Notes:
-
-
Unicode Inno Setup uses the existing ANSI .isl language files and you should not and may not convert these to Unicode or anything similar since it does so automatically during compilation using the LanguageCodePage setting listed inside the language's .isl file. However, you do need to convert existing [Messages] and [CustomMessages] entries in your .iss files to Unicode if the language used a special LanguageCodePage.
-
The [Setup] directive ShowUndisplayableLanguages is ignored by Unicode Inno Setup.
-
Unicode Inno Setup is compiled with Delphi 2009 instead of Delphi 2 and 3, leading to slightly larger files. The source code however is still compatible with Delphi 2 and 3, and a non Unicode version will remain available.
-
Unicode Inno Setup and installers created by it require Windows 2000/XP or newer. The non Unicode version still works on NT/9x.
-
Existing installations of your programs done by non Unicode installers can be freely updated by Unicode installers, and vice versa.
-
Unicode Pascal Scripting notes:
-
-
The Unicode compiler sees type 'String' as a Unicode string, and 'Char' as a Unicode character. Its 'AnsiString' type hasn't changed and still is an ANSI string. Its 'PChar' type has been renamed to 'PAnsiChar'.
-
The Unicode compiler is more strict about correct ';' usage: it no longer accepts certain missing ';' characters.
-
The new RemObjects PascalScript version used by the Unicode compiler supports Unicode, but not for its input source. This means it does use Unicode string types as said, but any literal Unicode characters in the script will be converted to ANSI. This doesn't mean you can't display Unicode strings: you can for example instead use encoded Unicode characters to build Unicode strings (like S := #$0100 + #$0101 + 'Aa';), or load the string from a file using LoadStringsFromFile.
-
Some support functions had their prototype changed: some parameters of CreateOutputMsgMemoPage, RegQueryBinaryValue, RegWriteBinaryValue, OemToCharBuff, CharToOemBuff, LoadStringFromfile, SaveStringToFile, and GetMD5OfString are of type AnsiString now instead of String.
-
Added new SaveStringsToUTF8File, and GetMD5OfUnicodeString support functions.
-
If you want to compile an existing script that imports ANSI Windows API calls with the Unicode compiler, either upgrade to the 'W' Unicode API call or change the parameters from 'String' or 'PChar' to 'AnsiString'. The 'AnsiString' approach will make your [Code] compatible with both the Unicode and the non Unicode version.
Thanks to Carlo Kok and Evgeny Karpov of RemObjects Software for their help related to Unicode support.
-
QuickStart Pack: added ISPP functions Trim, and GetMD5OfUnicodeString.
-
-
-
-
-
5.2.4 (2009-03-16)
-
-
Added new [Registry] section ValueType: qword.
-
Added new [Setup] section directive: SignTool, which makes it possible to further automate digital signing of Setup and Uninstall. See the help file for more information.
-
The value of the AppVersion directive is now also used to set the MajorVersion and MinorVersion values in the Uninstall registry key when possible.
-
/LOG: Now logs exit codes on [UninstallRun] entries.
-
Compiler IDE changes:
-
-
Added new Tools | Configure Sign Tools... command.
-
-
-
Command line compiler changes:
-
-
Added new "/S" parameter to specify a Sign Tool.
-
-
-
Added new [Files] section flag: sortfilesbyname.
-
-
-
5.2.3 (2008-03-10)
-
-
Improved support for right-to-left languages (Arabic and Hebrew): Added new [LangOptions] section directive: RightToLeft. If set to yes, text alignment and reading order will be reversed (with some intentional exceptions), and controls will be arranged from right to left ("flipped").
-
Added new [Setup] section directives: VersionInfoProductName and VersionInfoProductVersion.
-
Changed the fixed Language field in Setup's version info from "English (United States)" to "Language Neutral".
-
Uninstall now supports custom message constants ({cm:...}) like Setup.
-
Right-to-left-related Pascal Scripting changes:
-
-
The control flipping that is performed when RightToLeft=yes is mostly transparent, normally requiring no changes to existing code. Controls created on custom wizard pages will be flipped automatically after the InitializeWizard event function returns, and controls created on custom forms will, by default, be flipped the first time the form is shown.
-
Changes to TSetupForm (the class used for custom forms):
-
-
Added RightToLeft Boolean property (read-only): True if right-to-left text alignment and reading order is enabled on the form. The RightToLeft [LangOptions] directive determines the value of this property.
-
Added FlipControlsOnShow Boolean property: If True (the default setting if RightToLeft is True), controls on the form will be flipped the next time the form is shown. After the form has been shown, the property is reset to False automatically.
-
Added ControlsFlipped Boolean property (read-only): True if the controls have been flipped.
-
Added FlipControlsIfNeeded method. This flips the controls immediately if FlipControlsOnShow is True, then resets FlipControlsOnShow to False.
-
-
-
Added new classes: TNewEdit, TNewMemo, TNewComboBox, TNewButton, TNewCheckBox, TNewRadioButton, and TNewListBox. On these classes, right-to-left text alignment and reading order is used when the parent TSetupForm's RightToLeft property is True.
-
TNewStaticText: Added ForceLTRReading property. If set to True, the text will always be rendered with left-to-right reading order, overriding the parent form's RightToLeft setting.
-
-
-
Other Pascal Scripting changes:
-
-
TNewStaticText: Added AdjustHeight method. This adjusts the value of the Height property to fit the text. Only useful when AutoSize is set to False.
-
Added new object UninstallProgressForm of class TUninstallProgressForm. Also added new event function InitializeUninstallProgressForm, which is called after the Uninstall progress form has been created and before it is shown. See the help file and the CodeClasses.iss example script for more information.
-
-
-
Added workaround for bug in Windows Vista (still present in SP1): With UAC turned off, launching an uninstaller from the Programs and Features Control Panel applet and answering No at the confirmation message box would cause a "This program might not have uninstalled correctly" dialog to be displayed, even though the uninstaller includes a proper "Vista-aware" manifest.
-
Compiler IDE changes:
-
-
The New Script Wizard now generates random unique AppId [Setup] section directives.
-
Added new Tools | Generate GUID command.
-
-
-
QuickStart Pack: added ISPP functions GetMD5OfFile, GetMD5OfString and GetFileDateTimeString.
-
Minor tweaks.
-
-
-
5.2.2 (2007-10-22)
-
-
The Setup loader now extracts the Setup program executable file with a ".tmp" extension. Versions 5.2.0 and 5.2.1 used a ".exe.tmp" extension, which reportedly, in some cases, caused an "Unable to execute file in temporary directory" error message on systems with a certain antivirus program installed. We were unable to reproduce the error in our own tests, however; it is suspected that this may have only impacted users with custom filename blocking rules defined in their antivirus configuration.
-
Pascal Scripting: Added new GetSaveFileName support function.
-
Fix: The compiler could fail with an "Out of memory" error on script files containing more than ~100,000 lines, due to a heap fragmentation issue.
-
-
-
5.2.1 (2007-10-13)
-
-
Added new [Setup] section directive: SignedUninstaller, which makes it possible to attach a digital signature to the uninstaller program (unins???.exe). When the uninstaller has a valid digital signature, Windows Vista users will not see an "unidentified program" warning when launching it from outside of Control Panel.
-
Added new [Setup] section directive: SignedUninstallerDir.
-
Check functions associated with [Tasks] entries are now called when the Select Tasks wizard page is entered. Previously, they were called prior to the wizard being shown, which meant they couldn't depend on the user's selections in preceding wizard pages. (There are plans to make the same change to [Components] in the future.)
-
Brought back the pre-5.1.13 duplicate [Components]/[Tasks] entry semantics. For example, in the following case:
-
-[Tasks]
-Name: foo; Description: "foo #1"; Components: bar
-Name: foo; Description: "foo #2"; Components: not bar
-Name: foo\child; Description: "foo\child"
-
-"foo\child" will now, once again, be shown regardless of which "foo" is conditionally created.
-
-
Pascal Scripting: "files:" function imports may now include multiple filenames. "files:A.dll,B.dll" will cause both A.dll and B.dll to be extracted before A.dll is loaded.
-
On Windows Vista, Setup no longer alters the uninstaller program's manifest resource to request elevation, because this would invalidate a digital signature. Instead, the uninstaller now respawns itself when elevation is required, much like Setup does beginning with version 5.2.0.
-
The uninstall program's version is now 51.49.0.0.
-
Minor tweaks.
-
-
-
5.2.0 (2007-09-19)
-
-
On Windows Vista, [Run] section entries with the postinstall flag no longer inherit Setup's elevated privileges by default, and instead now execute with the (normally non-elevated) credentials of the user that started Setup initially. (There are some exceptions; see the runasoriginaluser flag documentation for details.)
-
Added new [Run] section flags: runascurrentuser and runasoriginaluser. These control which user credentials are used on Windows Vista when spawning processes. (runasoriginaluser is the default when the postinstall flag is used; runascurrentuser is the default otherwise.)
-
Improved compression of x86 executable files. (This reduced the size of Inno Setup's own installer by approximately 10 KB.)
-
Added new [Files] section parameter: ExternalSize.
-
Added new constant: {log}. Translates to the log file name, or an empty string if logging is not enabled.
-
Added new [Files] and [Dirs] sections flags: setntfscompression and unsetntfscompression. These flags instruct Setup to enable or disable NTFS compression on the file or directory.
-
Pascal Scripting:
-
-
Added new ExecAsOriginalUser, ShellExecAsOriginalUser, and SetNTFSCompression support functions.
-
Now supports new DLL loading flag loadwithalteredsearchpath to load DLLs with the Windows flag LOAD_WITH_ALTERED_SEARCH_PATH.
-
-
-
The Setup loader now uses the original Setup EXE filename + .tmp as the filename for the extracted Setup executable instead of a name comprised of random letters and numbers, which may have seemed suspicious to firewall users.
-
In a multilingual installation, Setup now waits until after the Select Language dialog is shown to display any error messages concerning the user's Windows version or privilege level.
-
QuickStart Pack: added ISPP function GetDateTimeString.
-
Fix: On Windows Vista, AutoPlay wasn't being suppressed when the user swapped out discs in a disk-spanned install.
-
Fix: When the waituntilidle flag was used in the [UninstallRun] section, it behaved like waituntilterminated.
-
Based on RemObjects Pascal Script SVN code revision 1045a.
-
The uninstall program's version is now 51.48.0.0.
-
Minor tweaks.
-
-
-
-
-
5.1.14 (2007-08-07)
-
-
Updated the LZMA SDK compression code to version 4.49. This version adds support for multi-threading, which can speed up the compression process by 50% or more on systems with multiple processor cores, and 20% or more on systems with single-core Intel processors featuring Hyper-Threading Technology.
-
Added new CompressionThreads [Setup] section directive.
-
Fix: When cleaning the output directory, the compiler would not only delete files matching OutputBaseFilename-*.bin, but files matching OutputBaseFilename-*-*.bin as well.
-
-
-
5.1.13 (2007-07-22)
-
-
Added new lzma/ultra64 compression level. Same as lzma/ultra, but uses a dictionary size that is twice as large (64 MB).
-
Added new SetupLogging [Setup] section directive. If set to yes, Setup will always create a log file (equivalent to passing /LOG on the command line).
-
Added new AppSupportPhone [Setup] section directive.
-
Added new [Files] section flag: solidbreak.
-
Added new [Run] and [UninstallRun] sections parameter: Verb. When used with the shellexec flag, specifies the action to be performed on the file.
-
When the shellexec flag is used in the [Run] and [UninstallRun] sections, it now uses the default verb for the file type instead of hardcoding "open". (If necessary, you can override this by adding a Verb parameter.)
-
Setup now supports a /TYPE parameter to override the default setup type.
-
Components/tasks-related changes:
-
-
/COMPONENTS & /TASKS: When a parent component/task is specified, it no longer automatically checks every child component/task. To achieve the old behavior, prefix the name of the parent component/task with a "*" character, or list each child component/task individually.
-
/COMPONENTS: It is now possible to force a child component to be deselected by including its name in the list with a "!" prefix. (/TASKS already supports this.)
-
/COMPONENTS is now ignored if no custom type is defined.
-
/SAVEINF now writes the selected setup type in the INF file. Previously, using /LOADINF would always select a custom type.
-
/SAVEINF now writes the selected tasks in the INF file.
-
When a MinVersion/OnlyBelowVersion/Languages/Check/Components parameter causes a parent component/task to be hidden from view, child items will now be hidden as well. (Previously, it was necessary to include the same conditions on every child item in order for them to be hidden along with the parent item.)
-
Fix: When new child components/tasks were introduced in a new install, they would always be selected by default if the parent component/task was selected in the previous installation.
-
Fix: /LOADINF would select child components that weren't selected during the initial install.
-
Fix: In a /COMPONENTS parameter, it is no longer necessary to list fixed components in order for them to be selected.
-
-
-
Pascal Scripting changes:
-
-
FindFirst/FindNext: Add CreationTime, LastAccessTime, LastWriteTime, AlternateName fields to TFindRec.
-
TInputFileWizardPage: Added new IsSaveButton property. This can be used to make a button open a Save As dialog instead of the default Open dialog.
-
TNewCheckListBox: Setting Checked[] to True will no longer automatically check an item's child check boxes. To do that now, call the new CheckItem method with coCheckWithChildren in the AOperation parameter.
-
ParamStr/ParamCount: Empty parameters ("") are no longer skipped.
-
-
-
/LOG: Logged times now include milliseconds.
-
Compiler IDE changes:
-
-
During the compression phase of a compile, the status bar now shows the estimated time remaining and KB compressed/second.
-
The Edit | Redo shortcut is now Ctrl+Y. The previous shortcut (Shift+Ctrl+Z) still works too.
-
-
-
Fix: In the [INI] section, if Filename was blank, the uninsdelete* flags didn't actually delete anything.
-
The uninstall program's version is now 51.47.0.0.
-
Minor tweaks.
-
-
-
5.1.12 (2007-04-24)
-
-
Fix: On Windows Vista, attempting to expand a shell folder constant that mapped to the root directory of a drive would fail with an error message. This was due to a bug in Vista's SHGetFolderPath API. A workaround for the problem has been implemented.
-
On Browse dialogs, the BrowseDialogLabel message text may now span multiple lines.
-
The OnlyOnThisPlatform message is no longer used. Now, when a Windows 95/98/Me user attempts to run an installation with a MinVersion setting that blocks installation on non-NT platforms, Setup will display the WinVersionTooLowError message, which is a bit more helpful as it mentions the required version number.
-
Corrected some trivial one-pixel-off issues when non-default dialog fonts or font sizes were used.
-
Added official Hebrew translation.
-
Minor tweaks.
-
-
-
5.1.11 (2007-03-01)
-
-
On Windows 2000 and later, it now uses Windows' own regsvr32.exe to handle DLL registration/unregistration instead of an internal program. This should address errors seen on Windows Vista when registering certain older DLLs. (Windows Vista applies a compatibility fix known as "WRP Mitigation" to regsvr32.exe, which allows it to successfully register DLLs that attempt to write to system registry keys in violation of Windows Resource Protection.)
Added two new [Run]/[UninstallRun] section flags: 32bit and 64bit. Similar to the [Files] section flags of the same name, these override the install mode and affect which System directory the {sys} constant maps to on 64-bit Windows.
-
Pascal Scripting:
-
-
Added new EnableFsRedirection support function.
-
On the Exec function, you can now pass '>' in the Filename parameter and it will use the value of the Params parameter as the full command line. This feature can come in handy when executing command lines obtained from UninstallString registry values; no longer is it necessary to separate strings into filename and parameter components manually.
-
Fix:IsComponentSelected and IsTaskSelected didn't accept forward slashes.
-
-
-
Improved Setup's folder tree view control (seen when a Browse button is clicked):
-
-
On Windows Vista, it now uses the same theme as Windows Explorer.
-
On Windows Vista, for consistency with Explorer, single-clicking in a node's text area no longer causes the node to expand.
-
Like Windows Explorer, folder nodes now use the shell's "display names", as opposed to the actual directory names. This matters on localized versions of Windows Vista, where the on-disk names of system folders are always in English.
-
The system "icon" font is now used instead of the default dialog font. This font defaults to Segoe UI on Windows Vista, and typically Tahoma or MS Sans Serif on earlier versions of Windows.
-
Disconnected network drives are now listed; expanding one will restore the connection (on Windows 2000, Me, and later).
-
-
-
On the Select Destination Location wizard page (as well as custom directory selection pages created using the CreateInputDirPage support function), if the letter of a disconnected network drive is entered, and the user is running Windows XP or later, it will now attempt to restore the connection automatically when Next is clicked. (It also does this on silent installs.)
-
On Windows Vista, eliminated the flickering on Setup's progress bar (purely a cosmetic issue).
-
On Windows Vista, Setup now calls SetProcessDPIAware to avoid bitmap scaling when Windows is configured to use Large Fonts and the "Use Windows XP style DPI scaling" option is unchecked (not the default setting).
-
Compiler IDE changes:
-
-
Added new option: Always launch Setup/Uninstall as different user. This forces the IDE to display a "Run as" dialog when launching Setup/Uninstall.
-
The Stop Compile command now displays a confirmation message box.
-
-
-
Added a "Vista-aware" manifest resource to ISCC so it doesn't request elevation on Windows Vista.
-
Fix: ISCC didn't always print error messages when standard output was redirected to a file.
-
When Setup fails to set the permissions on files, directories, or registry keys, the error code is now included in the log output.
-
When Setup fails to expand a shell folder constant, a warning message containing the error code is now logged.
-
Changed the way version information is read from VXD files to be more compliant with the MSDN docs.
-
The uninstall program's version is now 51.45.0.0.
-
Minor tweaks.
-
-
-
5.1.9 (2006-12-10)
-
-
Change in default behavior: The PrivilegesRequired [Setup] section directive now defaults to admin. The default in all previous versions was none. More often than not, installations do need administrative privileges to run successfully; therefore, none should not be used unless you have actually tested your installation on unprivileged accounts.
-
On Windows Vista, the setting of the PrivilegesRequired directive now influences whether elevated rights are requested when the installation is started under a user account that does not have administrative privileges. Installations built with previous versions of Inno Setup always requested elevation on Vista. Beginning with this version, elevation will not be requested if the user is unprivileged and PrivilegesRequired is set to none.
-
On Windows Vista, the uninstaller will no longer request elevation when Setup was never run with administrative privileges.
-
URLs (web site addresses) may now be specified in the Filename parameter of [Icons] section entries. When a URL is detected, Setup will create an Internet Shortcut (.url) file instead of a regular shortcut.
-(Note: While you could sometimes get away with specifying URLs in previous versions of Inno Setup, it was never recommended because the shortcuts would fail to resolve on Windows 95 or NT 4.0. Internet Shortcuts, on the other hand, will work on any version of Windows, as long as Internet Explorer is installed.)
-
Added workaround for bug in the 64-bit version of Windows Vista: The fields on the User Information wizard page would default to "Microsoft".
-
Pascal Scripting: Added new FontExists support function.
-
The uninstall program's version is now 51.44.0.0.
-
Minor tweaks.
-
-
-
5.1.8 (2006-10-11)
-
-
Converted the documentation to HTML Help format for compatibility with Windows Vista, which does not support WinHelp-based help files at all (as of RC2). HTML Help is also said to work better with screen readers. Much of the conversion process was done by hand, so there may be some mistakes. Please report any problems you encounter.
-
Updated the LZMA SDK compression/decompression code to version 4.43. Compression is noticably faster in this version. (Compiling Inno Setup's own installer used to take 7 seconds; now it takes 4.)
-
Added a "requestedExecutionLevel" setting to Setup's manifest resource to disable Windows Vista's legacy application compatibility hacks. Now you should no longer see bogus "This program might not have installed correctly" dialogs when cancelling installations or after running installations that do not create an Uninstall key.
-Note: It is possible that you were unwittingly relying on some of these application compatibility hacks, so it is recommended that you re-test your installations on Windows Vista after upgrading to this version.
-
When deleting a .chm file, the uninstaller will now automatically delete any corresponding .chw file as well.
-
Paths that are accessed at compile time may now include a "userdocs:" prefix, which is replaced with the path of your My Documents folder. For a usage example, see any of the example scripts.
-
Setup now creates an "InstallDate" value in the Uninstall key so that Vista's Programs and Features Control Panel applet doesn't have to guess the "Installed on" date.
-
Pascal Scripting changes/improvements:
-
-
The StringChange function now returns an Integer indicating the number of changes made. Performance was also improved.
-
Introduced new StringChangeEx function, which adds support for strings containing double-byte characters (used in Chinese, Japanese, and Korean languages). Unless you require binary safety, this function should be used instead of StringChange, especially if you're working with strings containing paths or filenames.
-
-
-
IDE changes:
-
-
The Open and Save As dialogs now permit sizing and include a places bar.
-
On Windows Vista, the IDE no longer requests administrative privileges when started. (You will, however, still see UAC popups when launching compiled installations from within the IDE.)
-
When you compile an unsaved script, the output is now placed under your My Documents folder (instead of the current directory). It asks if you want to save the script first, though.
-
-
-
Updated bzip2 library to version 1.0.3.
-
Minor tweaks.
-
-
-
5.1.7 (2006-08-18)
-
-
New [Setup] section directive: TerminalServicesAware. If set to yes (the default), the "Terminal Services aware" flag will be set in the headers of the Setup and Uninstall programs. Most notably, this ensures that the {win} constant consistently returns the system's real Windows directory on systems with Terminal Services installed in application mode. Refer to the help file for details.
-
The program Setup internally uses to register/unregister DLLs/OCXs is now compiled with the "Terminal Services aware" flag set, like Microsoft's regsvr32.exe.
-
When determining which language to select by default, Setup now checks the LanguageCodePage values of each language in addition to LanguageID. Previously, Traditional Chinese could be auto-selected on a Simplified Chinese system due to both languages having the same primary language ID. This resulted in unreadable text as they use completely different character sets (code pages).
-
New [Setup] section directive: ShowUndisplayableLanguages. If set to yes, all languages will be listed in the Select Language dialog, including those that cannot be displayed properly on the user's system. If you were using the LanguageCodePage=0 trick in your script before, you should replace it with this to avoid the above-mentioned problem with Chinese languages.
-
A unique value is now appended to unins*.exe files so that uninstallers from different applications won't have the same hash.
-
The compiler now flags MSCOREE.DLL as an "unsafe" file.
-
Fix: The createallsubdirs [Files] section flag didn't properly escape directory names containing "{" characters.
-
Fix: The text on the Finished wizard page wasn't initialized when a restart was needed and /NORESTART was used without /SILENT.
-
Pascal Scripting: Defined new DWORD_PTR, UINT_PTR, and INT_PTR types for completeness.
-
Added official Basque and Spanish translations.
-
The uninstall program's version is now 51.43.0.0.
-
Minor tweaks.
-
-
-
5.1.6 (2005-11-18)
-
-
Registration and unregistration of 32-bit DLLs is now performed in an external process. This change was primarily made to ensure that a buggy DLL cannot bring down the entire Setup/Uninstall process by, for example, corrupting its memory.
-
Pascal Scripting changes/improvements:
-
-
The already-existing AnsiUppercase and AnsiLowercase functions are now documented. Unlike their non-Ansi counterparts, these can handle non-ASCII characters (e.g. accented letters).
-
TNewCheckListBox: Added new ItemCaption property. This can be used to change the caption of an already-created item. (Setting an item's caption through the Items property is not supported by TNewCheckListBox.)
-
-
-
OLE is now initialized before registering a 64-bit DLL.
-
While Setup is waiting for a 64-bit DLL to register, it now processes messages.
-
On CD/DVD-spanned installs, fixed issue with AutoPlay not being suppressed if you clicked OK too quickly on the Setup Needs the Next Disk dialog after swapping CDs/DVDs.
-
When WindowVisible=yes, the gradient background now uses 256 colors instead of 64, resulting in a smoother appearance when running in 24- or 32-bit color mode.
-
In the documentation for the Excludes [Files] section parameter, mention that a simple Unix-style pattern matching routine is used, which exhibits some differences from the DOS/Windows-style pattern matching used in the Source parameter.
-
Added official Slovak translation.
-
Minor tweaks.
-
-
-
5.1.5 (2005-08-17)
-
-
Added new VersionInfoCopyright [Setup] section directive, which allows you to set the Copyright field in Setup's version info.
-
Pascal Scripting changes/improvements:
-
-
New functions: CustomMessage, FmtMessage.
-
The FileExists function no longer strips off any trailing backslash from the specified filename. Previously, FileExists('c:\filename\') could return True.
-
TNewCheckListBox: Add new RequireRadioSelection Boolean property, which defaults to False. The "require a selection on top-level radio button groups" behavior introduced in 5.1.4 is now optional and disabled by default on user-created TNewCheckListBoxes.
-
-
-
Now handles values with surrounding quotes consistently across all [Setup] and [LangOptions] directives. Previously, only certain directives would strip surrounding quotes; now they all do. If you were relying on the old, inconsistent behavior, it may be necessary to tweak your scripts.
-
On [INI] section entries whose filenames include paths, it now checks if the directories exist and creates them if necessary.
-
For consistency with regsvr32, FPU exceptions are now masked while registering/unregistering 32-bit DLLs.
-
/LOG: When processing a [Files] entry that has the 32bit or 64bit flag, it now logs a message to that effect.
-
Added official Finnish translation.
-
SetupLdr's internal data is now stored in a resource instead of in the DOS header. This should address compatibility issues with third-party apps that replace the DOS header.
-
Updated zlib library to version 1.2.3.
-
Minor tweaks.
-
-
-
5.1.4 (2005-05-30)
-
-
New command line parameters supported by Setup: /TASKS and /MERGETASKS. These can be used to initially select/deselect tasks.
-
Pascal Scripting: Added new GetWindowsVersionEx function, which returns extended information about the user's version of Windows, including the service pack level and product edition (e.g. Professional or Home, Standard or Enterprise Server).
-
Using /COMPONENTS= with an empty components list now deselects all components. Ditto for "Components=" in a .INF file (loaded via /LOADINF). Previously, it would keep the default selection in these cases.
-
On the Select Tasks wizard page, when the list of tasks has to be reinitialized due to the user going back and changing the component selection, it now restores the checked state of the items from when the page was last shown.
-
It should no longer be possible for a top-level, exclusive group of components or tasks to have no selection. If the script specifies that all items in the group are to be unchecked, Setup will check the first item automatically.
-
Removed 1024-character limit on .INI-file values read via the {ini:...} constant or GetIniString support function. Now, values can be up to 64 KB in length, or the maximum length supported by the operating system, whichever is smaller.
-
Fix: The CreateOleObject and GetActiveOleObject support functions leaked references in some cases.
-
Fix: Setup would crash or fail to start if passed a command line parameter more than 255 characters in length. (This was due to a buffer overflow bug in a Delphi run-time library function.)
-
Based on RemObjects Pascal Script SVN code revision 1045.
-
Minor tweaks.
-
-
-
5.1.3-beta (2005-05-03)
-
-
Pascal Scripting:
-
-
When Setup/Uninstall is running in 64-bit mode, most of the support functions that access files now disable WOW64 file system redirection, meaning they are now capable of working with files located in the 64-bit System directory. Some, however, still do not. See the 64-bit Installation Limitations topic in the help file for specifics.
-
Replaced FileSearch function with a new implementation that properly supports MBCS, and doesn't search the current directory unless it is told to (e.g. by including "." in the directory list).
-
-
-
Uninstaller: Now hides the taskbar button when the /VERYSILENT switch is used.
-
IDE change: Added an option to the New Script Wizard to specify that the application doesn't have a main executable file.
-
Based on RemObjects Pascal Script SVN code revision 1039.
-
Minor tweaks.
-
-
-
5.1.2-beta (2005-04-14)
-
-
Addressed some 64-bit limitations in previous betas:
-
-
Setup is now capable of registering 64-bit DLLs/OCXs and 64-bit type libraries. When Setup is running in 64-bit mode, the regserver and regtypelib [Files] section flags assume that files are 64-bit by default. If you need to register a 32-bit file in a 64-bit mode install, include the new 32bit flag.
-
Setup is now capable of setting permissions on 64-bit registry keys and on files located in the 64-bit System directory.
-
-
-
Added two new [Files] section flags: 32bit and 64bit. These override the install mode and affect which System directory the {sys} constant maps to, whether the regserver and regtypelib flags treat the file as 32-bit or 64-bit, and which SharedDLLs key the sharedfile flag updates.
-
Pascal Scripting: Added new Is64Bit parameters to the following functions: IncrementSharedCount, DecrementSharedCount, RegisterServer, UnregisterServer, RegisterTypeLibrary, UnregisterTypeLibrary. See the documentation for details.
-
Setup will now only append to existing uninstall logs created by installs done in the same bit mode (32- or 64-bit).
-
When an error occurs while registering a DLL/OCX/type library after a restart, it now displays an error message, provided the noregerror flag isn't used. Before, it was silent.
-
Constants may now be used in the AppMutex [Setup] section directive.
-
Added official Brazilian Portuguese, Danish, Hungarian, and Italian translations.
-
Renamed official Standard Portuguese translation file from PortugueseStd.isl to Portuguese.isl.
-
Various minor fixes to the 64-bit functionality.
-
Updated the LZMA SDK compression/decompression code to version 4.16. The new version incorporates some fixes and a minor speed improvement.
-
Based on RemObjects Pascal Script SVN code revision 1033.
-
The uninstall program's version is now 51.42.0.0.
-
Minor tweaks.
-
-
-
5.1.1-beta (2005-03-24)
-
-
When Setup is running in 64-bit mode, it is now possible to install files to the 64-bit System directory, and execute programs located there.
-The {sys} constant now maps to the 64-bit System directory when used in the [Dirs], [Files], [InstallDelete], [Run], [UninstallDelete], and [UninstallRun] sections. Elsewhere, the {sys} constant still maps to the 32-bit System directory. See the Install Mode: 32-bit vs. 64-bit and 64-bit Installation Limitations topics in the help file for details.
-
Added workaround for bug in the 64-bit editions of Windows prior to Windows Server 2003 SP1 RC2 which caused the restartreplace [Files] section flag to fail when used on files installed to {sys}. (Specifically, Windows would try to replace the file in the 64-bit System directory instead of the 32-bit one.)
-
Compiler: A warning is now emitted instead of an error when a custom message isn't defined for all languages.
-
Fix: The /COMPONENTS command line parameter supported by Setup didn't accept forward slashes in component names -- only backslashes.
-
Fix: The compiler no longer automatically strips any trailing slashes/backslashes from the Subkey parameter of [Registry] entries. Versions 5.0.8 and 5.1.0-beta stripped forward slashes. This was wrong because valid registry key names can include forward slashes.
-
Fix: When files were deleted by an [InstallDelete]/[UninstallDelete] section entry or DelTree function call, it also inappropriately stripped the read-only attribute from directories that matched the wildcard.
-
Fix: An "internal error" message was displayed if the user removed all contents from the Select Start Menu Folder wizard page's edit control and also checked the Don't create a Start Menu folder check box.
-
Based on RemObjects Pascal Script SVN code revision 1032.
-
The uninstall program's version is now 51.41.0.0.
-
Minor tweaks.
-
-
-
5.1.0-beta (2005-03-01)
-
-
Inno Setup now has initial support for the installation of 64-bit applications on 64-bit versions of Windows:
-
-
-
Setup can run in one of two modes: 32-bit or 64-bit. 64-bit mode is selected if the user is running a 64-bit version of Windows and the system's processor architecture is included in the value of the new ArchitecturesInstallIn64BitMode [Setup] section directive. Otherwise, 32-bit mode is used. How do the two modes of installation differ? Primarily, the differences lie in where things are installed by default. For example, 64-bit applications have their own Program Files directory, and their own isolated view of the registry. See the Install Mode: 32-bit vs. 64-bit topic in the help file for details.
-
Added new [Setup] section directive ArchitecturesAllowed. When set, it specifies which processor architecture(s) Setup is allowed to run on.
-
Even when running in 32-bit mode, Setup is capable of installing files and creating registry keys in 64-bit locations, and vice versa. New options have been added that override the default locations:
-
-
New constants: {pf32}, {pf64}, {cf32}, {cf64}.
-
Root key names used in the [Registry] section, {reg:...} constants, and the Reg* [Code] support functions may now include 32 or 64 suffixes to specify either the 32-bit or the 64-bit view of the registry respectively.
-
-
-
To allow "multi-architecture" installations, new [Code] support functions have been added: IsWin64, Is64BitInstallMode, ProcessorArchitecture.
-
Added new {syswow64} constant and GetSysWow64Dir support function.
-
Added new example scripts: 64Bit.iss, 64BitTwoArch.iss, and 64BitThreeArch.iss.
-
Note: There are some limitations to be aware of when utilizing the 64-bit installation features. See the 64-bit Installation Limitations topic in the help file for details. There are plans to address these limitations in the near future, where possible.
-
-
- Purchase of the necessary 64-bit development hardware has been made possible by our kind donators, many thanks to them!
-
-
-
Pascal Scripting: New Format support function, which replaces the old Format1, Format2, Format3, and Format4 functions. Unlike those functions, Format accepts a variable number of arguments, and supports argument types other than strings.
-
Compiler: A warning is now emitted instead of an error when an unrecognized message name in a [Messages] section is encountered.
-
IDE changes: The New Script Wizard now allows you to specify the Setup languages.
-
/LOG improvement: The parameters of programs spawned in the [Run] and [UninstallRun] sections are now logged.
-
'&' characters in the BeveledLabel message no longer need to be escaped using another '&'.
New messages: OnlyOnTheseArchitectures, MissingWOW64APIs, TranslatorNote, UninstallOnlyOnWin64.
-
Removed messages: NoIconsCheck.
-
-
-
Based on RemObjects Pascal Script SVN code revision 1024.
-
The uninstall program's version is now 51.40.0.0.
-
Minor tweaks.
-
-
-
-
-
5.0.8 (2005-02-17)
-
-
IDE changes:
-
-
Added support for setting breakpoints (Run | Toggle Breakpoint).
-
The dots in the editor's gutter now shift properly when you insert/remove lines while debugging. (Note, however, that any changes you make while debugging won't take effect until you re-compile.)
-
-
-
Uninstaller: When a DLL/OCX was installed multiple times by separate installations of the same application, the uninstaller would unregister the DLL/OCX once for each install. As an optimization, it will now unregister the DLL/OCX only once.
-
Compiler: Using outdated .isl files that are missing some messages no longer results in a fatal compiler error. Now, warnings will be printed, and the missing messages will be pulled from Default.isl.
-
Various improvements/fixes to the parsing of pathnames. For example, ExtractFilePath('\\server\share') now returns \\server\share rather than \\server, and ExtractFileDir('path\\') now returns path rather than path\\.
-
When recursively deleting directories (for example, from an [InstallDelete] entry or a call to DelTree), it no longer recurses into reparse points.
-
The value of the NoProgramGroupCheck2 message is now always used as the caption of the "no icons" check box on the Select Start Menu Folder page of the wizard. Previously, it used either NoIconsCheck or NoProgramGroupCheck2 depending on whether an installation had [Icons] entries with Tasks parameters.
-
exclusive [Tasks] items that have no visible siblings are no longer automatically converted into check boxes. (If you really want check boxes, then you shouldn't use the exclusive flag.)
-
Based on RemObjects Pascal Script SVN code revision 1022.
-
Minor tweaks.
-
-
-
5.0.7 (2005-01-19)
-
-
When AllowNoIcons and UsePreviousGroup are set to yes, the Don't create any icons setting is now preserved between installs.
-
Both Setup and Uninstall now support a /SUPPRESSMSGBOXES command line parameter to suppress message boxes. This parameter only has an effect when combined with /SILENT or /VERYSILENT. See the help file for more details.
-
IDE changes:
-
-
Various enhancements to the New Script Wizard.
-
Added a new Tools menu with a command that opens the Add/Remove Programs Control Panel applet.
-
When stepping through code, the IDE now uses a different method of bringing Setup to the foreground, and vice versa. Previously, if for some reason Setup hung it was possible for the IDE to hang as well.
-
-
-
/LOG changes:
-
-
Now logs the contents of message boxes.
-
On NT platforms, the OS service pack level is now logged, as well as the privilege level of the user (Administrative, Power User, or None).
-
Now doesn't skip the replacement of a protected system file until after the version numbers of the new and existing files are logged.
-
-
-
Pascal Scripting changes/improvements:
-
-
Added new CharLength, DLLGetLastError, RegWriteExpandStringValue and SuppressibleMsgBox functions.
-
GetSpaceOnDisk no longer requires that a root directory be specified, or that a trailing backslash be included.
-
-
-
Removed the requirement that Windows NT 4.0 users have SP6 installed, which was added in version 5.0.1-beta. Setup should run on previous service pack levels but no guarantees can be made as I generally only test with SP6. Therefore I recommend setting MinVersion to at least 4.0,4.0sp6 if possible.
-
Removed legacy code that searched for and deleted Uninstall keys with suffixes of _is2 and higher. Only Inno Setup 1.08 (from 1998) created such keys.
-
Reverted the change in 5.0.4-beta that made it automatically expand relative paths specified in [Icons] section because it didn't work when the paths contained environment-variable strings (e.g. %SystemRoot%\...).
-
Fix: In 5.0.6, if you clicked Back on the Select Tasks wizard page and changed component settings causing a different set of tasks to be activated, the new tasks would show up with the wrong item type when you returned to the Select Tasks wizard page. (If you do not have tasks with Components parameters, then this bug did not affect you.)
-
Fix: In rare cases, component and task items with multi-line captions were painted incorrectly (strictly a cosmetic issue).
-
Fix: The UninstallSilent support function always returned False.
-
Fix: Even though they were not being installed, files with the dontcopy flag were being displayed on the installation progress page and included in the required disk space figure(s).
Based on RemObjects Pascal Script SVN code revision 1017.
-
Minor tweaks.
-
-
-
5.0.6 (2004-12-24)
-
-
This version introduces a new Inno Setup logo, new icons for the Inno Setup IDE, and new wizard images for the Inno Setup installer, created by glyFX.
-
New [Files] section flag: createallsubdirs. By default the compiler skips empty directories when it recurses subdirectories searching for the Source filename/wildcard. The createallsubdirs flag causes these directories to be created at install time (just like if you created [Dirs] entries for them). Must be combined with recursesubdirs.
-
New flag supported by the [Components] and [Tasks] sections: checkablealone. This flag specifies that the component/task can be checked when none of its children are. By default, if no Components/Tasks parameter directly references the component/task, unchecking all of the component/task's children will cause the component/task to become unchecked.
-
Pascal Scripting changes/improvements:
-
-
An AddEx function has been added to TInputOptionWizardPage to allow the addition of subitems.
-
Various properties have been added to the TInput...WizardPage classes to allow access to the wizard page controls.
-
Event function NeedRestart is now called near the end of the installation process instead of at the beginning.
-
In DLL function imports, new options 'setuponly' and 'uninstallonly' are supported, which cause a DLL to be loaded only when the script is running from Setup or Uninstall, respectively.
-
Added new UnloadDLL and GetShellFolderByCSIDL functions.
-
-
-
/LOG changes:
-
-
No longer (automatically) logs when the event functions InitializeSetup, InitializeWizard, GetCustomSetupExitCode, and DeinitializeSetup are called successfully -- only if they raise exceptions, and in the case of InitializeSetup, if False is returned.
-
Now logs the function name when the NeedRestart, RegisterPreviousData, InitializeUninstall, DeinitializeUninstall, CurUninstallStepChanged, and UninstallNeedRestart event functions raise exceptions.
-
-
-
Compiler IDE changes/improvements:
-
-
New "Debug Output" view that shows log messages from Setup/Uninstall in real time. (These are the same messages seen in the log file produced when Setup/Uninstall is run with the /LOG switch.)
-
New Pause on exceptions option (accessible via View | Options). Unchecking this will prevent the debugger from pausing when an exception is raised from [Code].
-
Now preserves the position of the splitter when you close the IDE.
-
-
-
Console-mode compiler (ISCC.exe): A new /F switch is supported which can be used to specify a new output filename, overriding any OutputBaseFilename setting in the script.
-
Improved Setup load time on installations containing hundreds of components at varying levels.
-
Updated zlib library to version 1.2.2.
-
Fix: When multiple patterns were specified in a [Files] section Excludes parameter, patterns that included backslashes were handled incorrectly.
-
Fix: [Components]: If you had two child radio buttons and one had children of its own, then unchecking & rechecking the top-level item would cause both radio buttons to be checked.
-
Based on RemObjects Pascal Script SVN code revision 1000.
-
Minor tweaks.
-
-
-
5.0.5-beta (2004-11-14)
-
-
New [Setup] section directive: OutputManifestFile. When set, the compiler will create a text file detailing information about the files compiled into Setup.
-
Pascal Scripting changes/improvements:
-
-
Added new exception-related functions: GetExceptionMessage, RaiseException, and ShowExceptionMessage.
-
The ExtractTemporaryFile support function now raises an exception with a descriptive error message when it fails, instead of returning a Boolean indicating success/failure.
-
GetSpaceOnDisk: Added new InMegabytes parameter. By setting it to False, you can get figures in bytes (capped at 2 GB-1).
-
RegWriteMultiStringValue: When writing values, it now appends two null terminators automatically, like [Registry] does when writing multisz-type values.
-
-
-
Console-mode compiler (ISCC.exe) improvements:
-
-
A new /O switch is supported which can be used to specify a new output path, overriding any OutputDir setting in the script.
-
A new /Q switch is supported which causes it to compile quietly, printing only error messages.
-
Error messages are now written to standard error instead of standard output. Note: If you were previously redirecting all compiler messages to a file using >filename you will now need to use >filename 2>&1 to capture standard error as well. If you wish to redirect only standard error, use 2>filename.
-
-
-
When ChangesAssociations=yes and/or ChangesEnvironment=yes are used, it now notifies Windows of the changes after any [Run] section entries are processed and the CurStepChanged(ssPostInstall) event function is called.
-
Reverted one of the small image placement changes in 5.0.4: horizontally centering has been restored.
-
Fix: When the ExpandConstant support function was called at uninstall time, {common*} constants always mapped to their {user*} equivalents even if the user had administrative privileges.
-
Fix:ChangesEnvironment=yes worked on Windows NT 4.0 and 2000 but had no effect on Windows XP.
-
Fix: When writing empty REG_MULTI_SZ values, it should only append 1 null terminator, not 2.
-
Based on RemObjects Pascal Script SVN code revision 983.
-
The uninstall program's version is now 51.34.0.0.
-
Minor tweaks.
-
-
-
5.0.4-beta (2004-10-06)
-
-
New [Setup] section directive: ChangesEnvironment. When set to yes, at the end of the installation Setup will notify other running applications (notably Windows Explorer) that they should reload their environment variables from the registry.
-
Pascal Scripting changes/improvements:
-
-
The support functions CreateCustomForm, ScaleX, and ScaleY may now be called at uninstall time.
-
TRichEditViewer support class improvement: The Color property is now respected.
-
-
-
/LOG improvements:
-
-
It's now possible to specify a fixed path/filename to use for the log file via /LOG="filename".
-
Now logs when various event functions are called, and in the case of InitializeSetup it also logs the return value of the function.
-
Now logs when DLL/OCX/type library registration fails, even if the noregerror flag is specified.
-
-
-
Stretching of the small wizard image (specified by WizardSmallImage) now only occurs if the image is larger than the default size, or if the user is running larger-than-normal fonts. Previously, it always attempted to stretch the image.
-
The WizardSmallImageBackColor [Setup] section directive is now deprecated and ignored. Any unused space around the small wizard image is now filled with the standard window color (usually white).
-
Relative paths specified in [Icons] section entries are now converted into absolute paths automatically.
-
Fix: On Windows XP, folder shortcuts (which were introduced in 5.0.3-beta) showed ".lnk" at the end of them.
-
Based on RemObjects Pascal Script SVN code revision 960.
-
The uninstall program's version is now 51.33.0.0.
-
Minor tweaks.
-
-
-
5.0.3-beta (2004-08-16)
-
-
New supported [Files] section flag uninsnosharedfileprompt, which tells the uninstaller to automatically remove the shared file when its reference count reaches zero instead of asking the user. Must be combined with the sharedfile flag to have an effect.
-
New supported [Icons] section flag foldershortcut, which creates a special type of shortcut known as a "Folder Shortcut". Normally, when a shortcut to a folder is present on the Start Menu, clicking the item causes a separate Explorer window to open showing the target folder's contents. In contrast, a "folder shortcut" will show the contents of the target folder as a submenu instead of opening a separate window.
-Folder shortcuts are only supported by Windows 2000, Me, and later. On earlier versions of Windows, Setup will fall back to creating a normal shortcut when this flag is used.
-
Pascal Scripting changes/improvements:
-
-
The return value of the CreateShellLink function has changed from a Boolean to a String. Now, any failure results in an exception being raised.
-
-
-
The uninstaller is now capable of removing directories that have the read-only attribute set. (No special flags are needed; this is the default behavior.)
-
Based on RemObjects Pascal Script SVN code revision 948.
-
The uninstall program's version is now 51.32.0.0.
-
Minor tweaks.
-
-
-
5.0.2-beta (2004-08-05)
-
-
Pascal Scripting changes/improvements:
-
-
New GetUILanguage support function.
-
-
-
Compiler IDE: When a file has been modified outside the editor, offer to reload it.
-
Fix: The per-page event functions introduced in 5.0.1 that returned Boolean values didn't work properly.
-
Fix: When the overwritereadonly [Files] section flag was used and Setup was unable to remove the read-only attribute from a file (e.g. due to ACL restrictions), it would get stuck in an infinite loop.
-
Based on RemObjects Pascal Script SVN code revision 947.
-
-
-
5.0.1-beta (2004-08-02)
-
-
Compiler IDE: the toolbar now uses a modern looking set of images kindly donated by glyFX.
-
Setup/Uninstall can now wait on processes spawned using [Run]/[UninstallRun] entries that have the shellexec flag. Combine shellexec with either the new waituntilterminated flag (the default behavior when shellexecisn't specified) or the waituntilidle flag.
-
When Setup is running on Windows NT 4.0, Service Pack 6 is now required. This change shouldn't impact any significant number of users; SP6 was released five years ago, and almost all other programs that still support NT 4.0 nowadays have the same requirement.
-
Pascal Scripting changes/improvements:
-
-
Added new supported event function CancelButtonClick, which is called when the user clicks the Cancel button.
-
The prototype of the CurStepChanged function has changed, as has the names of the CurStep values passed to it. See the help file for details.
-
The names of the values passed to the CurUninstallStepChanged function have changed. See the help file for details.
-
Per-page event functions are now supported. TWizardPage and its descendants now include these properties: OnActivate, OnBackButtonClick, OnCancelButtonClick, OnNextButtonClick, OnShouldSkipPage. See the Support Classes Reference topic in the help file for the prototypes of these event functions.
-
Replaced the InstExec function with a new function named Exec. The new function offers the same functionality as the old one, but uses a slightly different prototype. The WaitUntilTerminated and WaitUntilIdle parameters have been replaced with a single Wait parameter.
-
Replaced the InstShellExec function with a new function named ShellExec. The new function adds Verb and Wait parameters. To get ShellExec to behave the same way as the old function, specify 'open' in the Verb parameter and ewNoWait in the Wait parameter.
-
Replaced the FindFirst and FindNext support functions with new versions that return more information about found files and can handle nested searches. Any existing scripts that called these functions will need updating. There is also a new FindClose function that you should call at the end of a find sequence.
-
Replaced the confusingly-named ShouldProcessEntry support function with new functions named IsComponentSelected and IsTaskSelected.
-
The Wizard* support functions now raise exceptions if you call them before the wizard has been initialized, instead of returning empty strings.
-
-
-
On a file that has the uninsrestartdelete flag the containing directory will now also be removed at uninstall time.
-
When extracting files, Setup now sets just the modification times instead of the creation and modification times.
-
/LOG improvement: Now logs permission setting on files/directories/registry keys.
-
The compiler now flags UXTHEME.DLL as an "unsafe" file.
-
Dropped the obsolete WizModernImage2.bmp and WizModernSmallImage2.bmp images.
-
Based on RemObjects Pascal Script SVN code revision 945.
-
The uninstall program's version is now 51.31.0.0.
-
Minor tweaks.
-
-
-
5.0.0-beta (2004-07-14)
-
-
The size of compiled installations has decreased by 22-26 KB from Inno Setup 4.2.7, primarily due to the merging of Setup and Uninstall into a single binary.
-
Pascal Scripting can now be used to customize Uninstall:
-
-
-
Added Uninstall specific event functions InitializeUninstall, DeinitializeUninstall, CurUninstallStepChanged and UninstallNeedRestart.
-
Added support functions IsUninstaller and UninstallSilent.
-
-
- Furthermore, the compiler IDE now supports Uninstall debugging. To debug Uninstall, first run Setup from the IDE, install your application, select Target Uninstall in the Run menu and finally use the debugger functions as normal.
- See the help file and the UninstallCodeExample1.iss example script for more information.
-
-
-
The custom wizard page support has been completely redesigned from the ground up. The new design uses an event-driven model just like standard wizard pages; no longer do you have to write complicated loops to handle sequences of custom pages.
-Any existing code utilizing custom wizard pages will need updating; all of the old functions have been replaced. Please see the new Using Custom Wizard Pages topic in the help file and the CodeDlg.iss and CodeClasses.iss example scripts for examples of how to use the new custom wizard page model.
-
-
-
Besides space separated lists, you may now also use boolean expressions as Components, Tasks, Languages and Check parameters. Supported operators include not, and, and or. For example:
-
-[Components]
-Name: a; Description: a
-Name: b; Description: b
-
-[Tasks]
-Name: p; Description: a or b; Components: a or b
-Name: q; Description: a and b; Components: a and b
-Name: r; Description: not a or b; Components: not a or b
-Name: s; Description: not (a or b); Components: not (a or b)
-Name: t; Description: a or b - old style; Components: a b
-
-
-
This syntax of function parameters in Check, BeforeInstall and AfterInstall parameters has changed to allow a list of multiple, comma separated, parameters and the use of Integer and Boolean parameter types besides String types. For example, you may now use:
-
-[Files]
-Source: MyProg.exe; DestDir: {app}; Check: MyCheck(1, True, 'Some text')
-
-[Code]
-function MyCheck(I: Integer; B: Boolean; S: String): Boolean;
-begin
- Result := (I > 0) and B and (S <> '');
-end;
-
-Also, there's one support function that may be called from within a parameter list: ExpandConstant. For example:
-
-Existing scripts using function parameters will need to be updated.
-
-
-
The functions specified by {code:...} constants and by Check, BeforeInstall and AfterInstall parameters may now refer to support functions too, for example:
-
Wizard-related event functions such as NextButtonClick are now called on silent installs as well. In fact, silent installs now function almost identically to non-silent ones with the exception that the Next button is automatically "clicked".
-
Logging improvements:
-
-
The filenames of programs spawned in the [Run] section are now logged.
-
The /LOG parameter is now also supported by Uninstall, which causes Uninstall to create a log file in the user's TEMP directory detailing file uninstallation and [UninstallRun] actions taken during the uninstallation process. This can be a helpful debugging aid. See the Uninstall Command Line Parameters topic in the help file for further details.
-
-
-
A new ShouldSkipPage event function has been added, which replaces SkipCurPage. Existing scripts that contain a SkipCurPage function will need to be updated. Note that unlike the old SkipCurPage event function, the page passed to the ShouldSkipPage function is not the current page.
-
Added support function Abort. Calling Abort throws an exception to abort the current operation. It does not terminate Setup or Uninstall unless it's still starting up.
-
When extracting a file, Setup now pre-allocates all of the bytes in the destination file on disk. This allows the system to know what the final size of the file will be before extraction begins, and avoid fragmenting it.
-
The compiler now fully supports script files that use Unix-style line breaks (LF only).
-
The Setup section directive UninstallIconFile is now deprecated and ignored. As Setup and Uninstall have been merged into a single executable, setting a custom icon for Uninstall is no longer possible.
-
The Setup section directive UninstallStyle is now deprecated and ignored. Only the "modern" uninstaller style is supported now.
-
Based on RemObjects Pascal Script SVN code revision 933.
-
The uninstall program's version is now 51.30.0.0.
-
A very large number of minor tweaks.
-
This version is derived from Inno Setup 4.2.7, and therefore includes all of the features and fixes from that version.
-
-
-
diff --git a/GreenshotBoxPlugin/BoxConfiguration.cs b/GreenshotBoxPlugin/BoxConfiguration.cs
index b75a3c2ae..4fb64cd2f 100644
--- a/GreenshotBoxPlugin/BoxConfiguration.cs
+++ b/GreenshotBoxPlugin/BoxConfiguration.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,30 +31,21 @@ namespace GreenshotBoxPlugin {
[IniSection("Box", Description = "Greenshot Box Plugin configuration")]
public class BoxConfiguration : IniSection {
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
- public OutputFormat UploadFormat;
+ public OutputFormat UploadFormat { get; set; }
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
- public int UploadJpegQuality;
+ public int UploadJpegQuality { get; set; }
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Box link to clipboard.", DefaultValue = "true")]
- public bool AfterUploadLinkToClipBoard;
+ public bool AfterUploadLinkToClipBoard { get; set; }
[IniProperty("UseSharedLink", Description = "Use the shared link, instead of the private, on the clipboard", DefaultValue = "True")]
- public bool UseSharedLink {
- get;
- set;
- }
+ public bool UseSharedLink { get; set; }
[IniProperty("FolderId", Description = "Folder ID to upload to, only change if you know what you are doing!", DefaultValue = "0")]
- public string FolderId {
- get;
- set;
- }
+ public string FolderId { get; set; }
[IniProperty("RefreshToken", Description = "Box authorization refresh Token", Encrypted = true)]
- public string RefreshToken {
- get;
- set;
- }
+ public string RefreshToken { get; set; }
///
/// Not stored
@@ -77,7 +68,7 @@ namespace GreenshotBoxPlugin {
///
/// bool true if OK was pressed, false if cancel
public bool ShowConfigDialog() {
- DialogResult result = new SettingsForm(this).ShowDialog();
+ DialogResult result = new SettingsForm().ShowDialog();
if (result == DialogResult.OK) {
return true;
}
diff --git a/GreenshotBoxPlugin/BoxCredentials.cs b/GreenshotBoxPlugin/BoxCredentials.cs
index 5d70729ed..c2c625889 100644
--- a/GreenshotBoxPlugin/BoxCredentials.cs
+++ b/GreenshotBoxPlugin/BoxCredentials.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,7 +18,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-using System;
namespace GreenshotBoxPlugin {
///
diff --git a/GreenshotBoxPlugin/BoxDestination.cs b/GreenshotBoxPlugin/BoxDestination.cs
index 6e2606fbd..f76a8bf96 100644
--- a/GreenshotBoxPlugin/BoxDestination.cs
+++ b/GreenshotBoxPlugin/BoxDestination.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,12 +22,9 @@ using System.ComponentModel;
using System.Drawing;
using Greenshot.Plugin;
using GreenshotPlugin.Core;
-using log4net;
namespace GreenshotBoxPlugin {
public class BoxDestination : AbstractDestination {
- private static ILog LOG = LogManager.GetLogger(typeof(BoxDestination));
-
private readonly BoxPlugin _plugin;
public BoxDestination(BoxPlugin plugin) {
_plugin = plugin;
diff --git a/GreenshotBoxPlugin/BoxEntities.cs b/GreenshotBoxPlugin/BoxEntities.cs
index afc567121..b07282adf 100644
--- a/GreenshotBoxPlugin/BoxEntities.cs
+++ b/GreenshotBoxPlugin/BoxEntities.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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/GreenshotBoxPlugin/BoxPlugin.cs b/GreenshotBoxPlugin/BoxPlugin.cs
index 717db960e..314d2a0d8 100644
--- a/GreenshotBoxPlugin/BoxPlugin.cs
+++ b/GreenshotBoxPlugin/BoxPlugin.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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
@@ -105,16 +105,6 @@ namespace GreenshotBoxPlugin {
_config.ShowConfigDialog();
}
- ///
- /// This will be called when Greenshot is shutting down
- ///
- ///
- ///
- public void Closing(object sender, FormClosingEventArgs e) {
- LOG.Debug("Application closing, de-registering Box Plugin!");
- Shutdown();
- }
-
public void ConfigMenuClick(object sender, EventArgs eventArgs) {
_config.ShowConfigDialog();
}
diff --git a/GreenshotBoxPlugin/BoxUtils.cs b/GreenshotBoxPlugin/BoxUtils.cs
index e0e1566d5..4f375a28c 100644
--- a/GreenshotBoxPlugin/BoxUtils.cs
+++ b/GreenshotBoxPlugin/BoxUtils.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,7 +33,7 @@ namespace GreenshotBoxPlugin {
/// Description of ImgurUtils.
///
public static class BoxUtils {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(BoxUtils));
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(BoxUtils));
private static readonly BoxConfiguration Config = IniConfig.GetIniSection();
private const string UploadFileUri = "https://upload.box.com/api/2.0/files/content";
private const string FilesUri = "https://www.box.com/api/2.0/files/{0}";
@@ -66,21 +66,23 @@ namespace GreenshotBoxPlugin {
public static string UploadToBox(SurfaceContainer image, string title, string filename) {
// Fill the OAuth2Settings
- OAuth2Settings settings = new OAuth2Settings();
+ var settings = new OAuth2Settings
+ {
+ AuthUrlPattern = "https://app.box.com/api/oauth2/authorize?client_id={ClientId}&response_type=code&state={State}&redirect_uri={RedirectUrl}",
+ TokenUrl = "https://api.box.com/oauth2/token",
+ CloudServiceName = "Box",
+ ClientId = BoxCredentials.ClientId,
+ ClientSecret = BoxCredentials.ClientSecret,
+ RedirectUrl = "https://www.box.com/home/",
+ BrowserSize = new Size(1060, 600),
+ AuthorizeMode = OAuth2AuthorizeMode.EmbeddedBrowser,
+ RefreshToken = Config.RefreshToken,
+ AccessToken = Config.AccessToken,
+ AccessTokenExpires = Config.AccessTokenExpires
+ };
- settings.AuthUrlPattern = "https://app.box.com/api/oauth2/authorize?client_id={ClientId}&response_type=code&state={State}&redirect_uri={RedirectUrl}";
- settings.TokenUrl = "https://api.box.com/oauth2/token";
- settings.CloudServiceName = "Box";
- settings.ClientId = BoxCredentials.ClientId;
- settings.ClientSecret = BoxCredentials.ClientSecret;
- settings.RedirectUrl = "https://www.box.com/home/";
- settings.BrowserSize = new Size(1060, 600);
- settings.AuthorizeMode = OAuth2AuthorizeMode.EmbeddedBrowser;
// Copy the settings from the config, which is kept in memory and on the disk
- settings.RefreshToken = Config.RefreshToken;
- settings.AccessToken = Config.AccessToken;
- settings.AccessTokenExpires = Config.AccessTokenExpires;
try {
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, UploadFileUri, settings);
@@ -92,17 +94,17 @@ namespace GreenshotBoxPlugin {
var response = NetworkHelper.GetResponseAsString(webRequest);
- LOG.DebugFormat("Box response: {0}", response);
+ Log.DebugFormat("Box response: {0}", response);
var upload = JsonSerializer.Deserialize(response);
- if (upload == null || upload.Entries == null || upload.Entries.Count == 0) return null;
+ if (upload?.Entries == null || upload.Entries.Count == 0) return null;
if (Config.UseSharedLink) {
string filesResponse = HttpPut(string.Format(FilesUri, upload.Entries[0].Id), "{\"shared_link\": {\"access\": \"open\"}}", settings);
var file = JsonSerializer.Deserialize(filesResponse);
return file.SharedLink.Url;
}
- return string.Format("http://www.box.com/files/0/f/0/1/f_{0}", upload.Entries[0].Id);
+ return $"http://www.box.com/files/0/f/0/1/f_{upload.Entries[0].Id}";
} finally {
// Copy the settings back to the config, so they are stored.
Config.RefreshToken = settings.RefreshToken;
diff --git a/GreenshotBoxPlugin/Forms/BoxForm.cs b/GreenshotBoxPlugin/Forms/BoxForm.cs
index dc1b5f22f..51473ad06 100644
--- a/GreenshotBoxPlugin/Forms/BoxForm.cs
+++ b/GreenshotBoxPlugin/Forms/BoxForm.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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/GreenshotBoxPlugin/Forms/SettingsForm.Designer.cs b/GreenshotBoxPlugin/Forms/SettingsForm.Designer.cs
index b91b206a1..2eaf2b790 100644
--- a/GreenshotBoxPlugin/Forms/SettingsForm.Designer.cs
+++ b/GreenshotBoxPlugin/Forms/SettingsForm.Designer.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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/GreenshotBoxPlugin/Forms/SettingsForm.cs b/GreenshotBoxPlugin/Forms/SettingsForm.cs
index 07b32373d..df1c50134 100644
--- a/GreenshotBoxPlugin/Forms/SettingsForm.cs
+++ b/GreenshotBoxPlugin/Forms/SettingsForm.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,21 +18,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-using System;
-using System.Drawing;
-using System.Windows.Forms;
using GreenshotBoxPlugin.Forms;
-using GreenshotPlugin.Core;
namespace GreenshotBoxPlugin {
///
/// Description of PasswordRequestForm.
///
public partial class SettingsForm : BoxForm {
- string boxTicket = string.Empty;
-
- public SettingsForm(BoxConfiguration config) {
+ public SettingsForm() {
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
diff --git a/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj b/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj
index 7bc39f15a..1df2862d1 100644
--- a/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj
+++ b/GreenshotBoxPlugin/GreenshotBoxPlugin.csproj
@@ -75,11 +75,11 @@
rename "$(ProjectDir)BoxCredentials.orig.cs" "BoxCredentials.cs"
)
-mkdir "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)"
-copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).dll" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
-copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\"
-mkdir "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
-copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).dll" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
if exist "$(ProjectDir)BoxCredentials.private.cs" (
diff --git a/GreenshotBoxPlugin/LanguageKeys.cs b/GreenshotBoxPlugin/LanguageKeys.cs
index ac3765582..a6e170688 100644
--- a/GreenshotBoxPlugin/LanguageKeys.cs
+++ b/GreenshotBoxPlugin/LanguageKeys.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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/GreenshotBoxPlugin/Properties/AssemblyInfo.cs b/GreenshotBoxPlugin/Properties/AssemblyInfo.cs
index 4dbee7804..2eda350e4 100644
--- a/GreenshotBoxPlugin/Properties/AssemblyInfo.cs
+++ b/GreenshotBoxPlugin/Properties/AssemblyInfo.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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.Plugin;
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/GreenshotConfluencePlugin/Confluence.cs b/GreenshotConfluencePlugin/Confluence.cs
index 05651949d..fdda7c31b 100644
--- a/GreenshotConfluencePlugin/Confluence.cs
+++ b/GreenshotConfluencePlugin/Confluence.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,22 +26,18 @@ using GreenshotConfluencePlugin;
using GreenshotConfluencePlugin.confluence;
using GreenshotPlugin.Core;
-///
-/// For details see the Confluence API site
-/// See: http://confluence.atlassian.com/display/CONFDEV/Remote+API+Specification
-///
namespace Confluence {
#region transport classes
public class Page {
public Page(RemotePage page) {
- id = page.id;
+ Id = page.id;
Title = page.title;
SpaceKey = page.space;
Url = page.url;
Content = page.content;
}
public Page(RemoteSearchResult searchResult, string space) {
- id = searchResult.id;
+ Id = searchResult.id;
Title = searchResult.title;
SpaceKey = space;
Url = searchResult.url;
@@ -49,12 +45,12 @@ namespace Confluence {
}
public Page(RemotePageSummary pageSummary) {
- id = pageSummary.id;
+ Id = pageSummary.id;
Title = pageSummary.title;
SpaceKey = pageSummary.space;
Url =pageSummary.url;
}
- public long id {
+ public long Id {
get;
set;
}
@@ -91,47 +87,53 @@ namespace Confluence {
}
#endregion
+ ///
+ /// For details see the Confluence API site
+ /// See: http://confluence.atlassian.com/display/CONFDEV/Remote+API+Specification
+ ///
public class ConfluenceConnector : IDisposable {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluenceConnector));
- private const string AUTH_FAILED_EXCEPTION_NAME = "com.atlassian.confluence.rpc.AuthenticationFailedException";
- private const string V2_FAILED = "AXIS";
- private static ConfluenceConfiguration config = IniConfig.GetIniSection();
- private string credentials = null;
- private DateTime loggedInTime = DateTime.Now;
- private bool loggedIn = false;
- private ConfluenceSoapServiceService confluence;
- private int timeout;
- private string url;
- private Cache pageCache = new Cache(60 * config.Timeout);
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceConnector));
+ private const string AuthFailedExceptionName = "com.atlassian.confluence.rpc.AuthenticationFailedException";
+ private const string V2Failed = "AXIS";
+ private static readonly ConfluenceConfiguration Config = IniConfig.GetIniSection();
+ private string _credentials;
+ private DateTime _loggedInTime = DateTime.Now;
+ private bool _loggedIn;
+ private ConfluenceSoapServiceService _confluence;
+ private readonly int _timeout;
+ private string _url;
+ private readonly Cache _pageCache = new Cache(60 * Config.Timeout);
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
- protected virtual void Dispose(bool disposing) {
- if (confluence != null) {
- logout();
+ protected void Dispose(bool disposing) {
+ if (_confluence != null) {
+ Logout();
}
if (disposing) {
- if (confluence != null) {
- confluence.Dispose();
- confluence = null;
+ if (_confluence != null) {
+ _confluence.Dispose();
+ _confluence = null;
}
}
}
public ConfluenceConnector(string url, int timeout) {
- this.timeout = timeout;
- init(url);
+ _timeout = timeout;
+ Init(url);
}
- private void init(string url) {
- this.url = url;
- confluence = new ConfluenceSoapServiceService();
- confluence.Url = url;
- confluence.Proxy = NetworkHelper.CreateProxy(new Uri(url));
- }
+ private void Init(string url) {
+ _url = url;
+ _confluence = new ConfluenceSoapServiceService
+ {
+ Url = url,
+ Proxy = NetworkHelper.CreateProxy(new Uri(url))
+ };
+ }
~ConfluenceConnector() {
Dispose(false);
@@ -141,41 +143,43 @@ namespace Confluence {
/// Internal login which catches the exceptions
///
/// true if login was done sucessfully
- private bool doLogin(string user, string password) {
+ private bool DoLogin(string user, string password) {
try {
- this.credentials = confluence.login(user, password);
- this.loggedInTime = DateTime.Now;
- this.loggedIn = true;
+ _credentials = _confluence.login(user, password);
+ _loggedInTime = DateTime.Now;
+ _loggedIn = true;
} catch (Exception e) {
- // Check if confluence-v2 caused an error, use v1 instead
- if (e.Message.Contains(V2_FAILED) && url.Contains("v2")) {
- init(url.Replace("v2", "v1"));
- return doLogin(user, password);
- }
+ // Check if confluence-v2 caused an error, use v1 instead
+ if (e.Message.Contains(V2Failed) && _url.Contains("v2")) {
+ Init(_url.Replace("v2", "v1"));
+ return DoLogin(user, password);
+ }
// check if auth failed
- if (e.Message.Contains(AUTH_FAILED_EXCEPTION_NAME)) {
+ if (e.Message.Contains(AuthFailedExceptionName)) {
return false;
}
// Not an authentication issue
- this.loggedIn = false;
- this.credentials = null;
+ _loggedIn = false;
+ _credentials = null;
e.Data.Add("user", user);
- e.Data.Add("url", url);
+ e.Data.Add("url", _url);
throw;
}
return true;
}
- public void login() {
- logout();
+ public void Login() {
+ Logout();
try {
// Get the system name, so the user knows where to login to
- string systemName = url.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX1,"");
- systemName = url.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX2, "");
- CredentialsDialog dialog = new CredentialsDialog(systemName);
- dialog.Name = null;
+ string systemName = _url.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX1,"");
+ systemName = systemName.Replace(ConfluenceConfiguration.DEFAULT_POSTFIX2, "");
+ CredentialsDialog dialog = new CredentialsDialog(systemName)
+ {
+ Name = null
+ };
while (dialog.Show(dialog.Name) == DialogResult.OK) {
- if (doLogin(dialog.Name, dialog.Password)) {
+ if (DoLogin(dialog.Name, dialog.Password)) {
if (dialog.SaveChecked) {
dialog.Confirm(true);
}
@@ -185,7 +189,7 @@ namespace Confluence {
dialog.Confirm(false);
} catch (ApplicationException e) {
// exception handling ...
- LOG.Error("Problem using the credentials dialog", e);
+ Log.Error("Problem using the credentials dialog", e);
}
// For every windows version after XP show an incorrect password baloon
dialog.IncorrectPassword = true;
@@ -195,124 +199,112 @@ namespace Confluence {
}
} catch (ApplicationException e) {
// exception handling ...
- LOG.Error("Problem using the credentials dialog", e);
+ Log.Error("Problem using the credentials dialog", e);
}
}
- public void logout() {
- if (credentials != null) {
- confluence.logout(credentials);
- credentials = null;
- loggedIn = false;
+ public void Logout() {
+ if (_credentials != null) {
+ _confluence.logout(_credentials);
+ _credentials = null;
+ _loggedIn = false;
}
}
- private void checkCredentials() {
- if (loggedIn) {
- if (loggedInTime.AddMinutes(timeout-1).CompareTo(DateTime.Now) < 0) {
- logout();
- login();
+ private void CheckCredentials() {
+ if (_loggedIn) {
+ if (_loggedInTime.AddMinutes(_timeout-1).CompareTo(DateTime.Now) < 0) {
+ Logout();
+ Login();
}
} else {
- login();
+ Login();
}
}
- public bool isLoggedIn {
- get {
- return loggedIn;
- }
- }
-
- public void addAttachment(long pageId, string mime, string comment, string filename, IBinaryContainer image) {
- checkCredentials();
- RemoteAttachment attachment = new RemoteAttachment();
+ public bool IsLoggedIn => _loggedIn;
+
+ public void AddAttachment(long pageId, string mime, string comment, string filename, IBinaryContainer image) {
+ CheckCredentials();
// Comment is ignored, see: http://jira.atlassian.com/browse/CONF-9395
- attachment.comment = comment;
- attachment.fileName = filename;
- attachment.contentType = mime;
- confluence.addAttachment(credentials, pageId, attachment, image.ToByteArray());
+ var attachment = new RemoteAttachment
+ {
+ comment = comment,
+ fileName = filename,
+ contentType = mime
+ };
+ _confluence.addAttachment(_credentials, pageId, attachment, image.ToByteArray());
}
- public Page getPage(string spaceKey, string pageTitle) {
+ public Page GetPage(string spaceKey, string pageTitle) {
RemotePage page = null;
string cacheKey = spaceKey + pageTitle;
- if (pageCache.Contains(cacheKey)) {
- page = pageCache[cacheKey];
+ if (_pageCache.Contains(cacheKey)) {
+ page = _pageCache[cacheKey];
}
if (page == null) {
- checkCredentials();
- page = confluence.getPage(credentials, spaceKey, pageTitle);
- pageCache.Add(cacheKey, page);
+ CheckCredentials();
+ page = _confluence.getPage(_credentials, spaceKey, pageTitle);
+ _pageCache.Add(cacheKey, page);
}
return new Page(page);
}
- public Page getPage(long pageId) {
+ public Page GetPage(long pageId) {
RemotePage page = null;
string cacheKey = "" + pageId;
- if (pageCache.Contains(cacheKey)) {
- page = pageCache[cacheKey];
+ if (_pageCache.Contains(cacheKey)) {
+ page = _pageCache[cacheKey];
}
if (page == null) {
- checkCredentials();
- page = confluence.getPage(credentials, pageId);
- pageCache.Add(cacheKey, page);
+ CheckCredentials();
+ page = _confluence.getPage(_credentials, pageId);
+ _pageCache.Add(cacheKey, page);
}
return new Page(page);
}
- public Page getSpaceHomepage(Space spaceSummary) {
- checkCredentials();
- RemoteSpace spaceDetail = confluence.getSpace(credentials, spaceSummary.Key);
- RemotePage page = confluence.getPage(credentials, spaceDetail.homePage);
+ public Page GetSpaceHomepage(Space spaceSummary) {
+ CheckCredentials();
+ RemoteSpace spaceDetail = _confluence.getSpace(_credentials, spaceSummary.Key);
+ RemotePage page = _confluence.getPage(_credentials, spaceDetail.homePage);
return new Page(page);
}
- public List getSpaceSummaries() {
- checkCredentials();
- RemoteSpaceSummary [] spaces = confluence.getSpaces(credentials);
- List returnSpaces = new List();
+ public IEnumerable GetSpaceSummaries() {
+ CheckCredentials();
+ RemoteSpaceSummary [] spaces = _confluence.getSpaces(_credentials);
foreach(RemoteSpaceSummary space in spaces) {
- returnSpaces.Add(new Space(space));
+ yield return new Space(space);
}
- returnSpaces.Sort((x, y) => string.Compare(x.Name, y.Name));
- return returnSpaces;
}
- public List getPageChildren(Page parentPage) {
- checkCredentials();
- List returnPages = new List();
- RemotePageSummary[] pages = confluence.getChildren(credentials, parentPage.id);
+ public IEnumerable GetPageChildren(Page parentPage) {
+ CheckCredentials();
+ RemotePageSummary[] pages = _confluence.getChildren(_credentials, parentPage.Id);
foreach(RemotePageSummary page in pages) {
- returnPages.Add(new Page(page));
+ yield return new Page(page);
}
- returnPages.Sort((x, y) => string.Compare(x.Title, y.Title));
- return returnPages;
}
- public List getPageSummaries(Space space) {
- checkCredentials();
- List returnPages = new List();
- RemotePageSummary[] pages = confluence.getPages(credentials, space.Key);
+ public IEnumerable GetPageSummaries(Space space) {
+ CheckCredentials();
+ RemotePageSummary[] pages = _confluence.getPages(_credentials, space.Key);
foreach(RemotePageSummary page in pages) {
- returnPages.Add(new Page(page));
+ yield return new Page(page);
}
- returnPages.Sort((x, y) => string.Compare(x.Title, y.Title));
- return returnPages;
}
- public List searchPages(string query, string space) {
- checkCredentials();
- List results = new List();
- foreach(RemoteSearchResult searchResult in confluence.search(credentials, query, 20)) {
- LOG.DebugFormat("Got result of type {0}", searchResult.type);
- if ("page".Equals(searchResult.type)) {
- results.Add(new Page(searchResult, space));
+ public IEnumerable SearchPages(string query, string space) {
+ CheckCredentials();
+ foreach(var searchResult in _confluence.search(_credentials, query, 20)) {
+ Log.DebugFormat("Got result of type {0}", searchResult.type);
+ if ("page".Equals(searchResult.type))
+ {
+ yield return new Page(searchResult, space);
}
}
- return results;
}
}
}
diff --git a/GreenshotConfluencePlugin/ConfluenceConfiguration.cs b/GreenshotConfluencePlugin/ConfluenceConfiguration.cs
index b8745054e..a64fbe8fd 100644
--- a/GreenshotConfluencePlugin/ConfluenceConfiguration.cs
+++ b/GreenshotConfluencePlugin/ConfluenceConfiguration.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/GreenshotConfluencePlugin/ConfluenceDestination.cs b/GreenshotConfluencePlugin/ConfluenceDestination.cs
index 10e212d5e..50330f109 100644
--- a/GreenshotConfluencePlugin/ConfluenceDestination.cs
+++ b/GreenshotConfluencePlugin/ConfluenceDestination.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,11 +36,12 @@ namespace GreenshotConfluencePlugin {
/// Description of ConfluenceDestination.
///
public class ConfluenceDestination : AbstractDestination {
- private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluenceDestination));
- private static readonly ConfluenceConfiguration config = IniConfig.GetIniSection();
- private static readonly CoreConfiguration coreConfig = IniConfig.GetIniSection();
- private static Image confluenceIcon = null;
- private Confluence.Page page;
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceDestination));
+ private static readonly ConfluenceConfiguration ConfluenceConfig = IniConfig.GetIniSection();
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private static readonly Image ConfluenceIcon;
+ private readonly Page _page;
+
public static bool IsInitialized {
get;
private set;
@@ -49,22 +50,22 @@ namespace GreenshotConfluencePlugin {
IsInitialized = false;
try {
Uri confluenceIconUri = new Uri("/GreenshotConfluencePlugin;component/Images/Confluence.ico", UriKind.Relative);
- using (Stream iconStream = Application.GetResourceStream(confluenceIconUri).Stream) {
- using (Image tmpImage = Image.FromStream(iconStream)) {
- confluenceIcon = ImageHelper.Clone(tmpImage);
- }
+ using (Stream iconStream = Application.GetResourceStream(confluenceIconUri)?.Stream)
+ {
+ // TODO: Check what to do with the IImage
+ ConfluenceIcon = ImageHelper.FromStream(iconStream);
}
IsInitialized = true;
} catch (Exception ex) {
- LOG.ErrorFormat("Problem in the confluence static initializer: {0}", ex.Message);
+ Log.ErrorFormat("Problem in the confluence static initializer: {0}", ex.Message);
}
}
public ConfluenceDestination() {
}
- public ConfluenceDestination(Confluence.Page page) {
- this.page = page;
+ public ConfluenceDestination(Page page) {
+ _page = page;
}
public override string Designation {
@@ -75,78 +76,83 @@ namespace GreenshotConfluencePlugin {
public override string Description {
get {
- if (page == null) {
+ if (_page == null) {
return Language.GetString("confluence", LangKey.upload_menu_item);
} else {
- return Language.GetString("confluence", LangKey.upload_menu_item) + ": \"" + page.Title + "\"";
+ return Language.GetString("confluence", LangKey.upload_menu_item) + ": \"" + _page.Title + "\"";
}
}
}
- public override bool isDynamic {
+ public override bool IsDynamic {
get {
return true;
}
}
- public override bool isActive {
+ public override bool IsActive {
get {
- return base.isActive && !string.IsNullOrEmpty(config.Url);
+ return base.IsActive && !string.IsNullOrEmpty(ConfluenceConfig.Url);
}
}
public override Image DisplayIcon {
get {
- return confluenceIcon;
+ return ConfluenceIcon;
}
}
public override IEnumerable DynamicDestinations() {
- if (ConfluencePlugin.ConfluenceConnectorNoLogin == null || !ConfluencePlugin.ConfluenceConnectorNoLogin.isLoggedIn) {
+ if (ConfluencePlugin.ConfluenceConnectorNoLogin == null || !ConfluencePlugin.ConfluenceConnectorNoLogin.IsLoggedIn) {
yield break;
}
- List currentPages = ConfluenceUtils.GetCurrentPages();
+ List currentPages = ConfluenceUtils.GetCurrentPages();
if (currentPages == null || currentPages.Count == 0) {
yield break;
}
- foreach(Confluence.Page currentPage in currentPages) {
+ foreach(Page currentPage in currentPages) {
yield return new ConfluenceDestination(currentPage);
}
}
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
- ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description);
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
// force password check to take place before the pages load
- if (!ConfluencePlugin.ConfluenceConnector.isLoggedIn) {
+ if (!ConfluencePlugin.ConfluenceConnector.IsLoggedIn) {
return exportInformation;
}
- Page selectedPage = page;
- bool openPage = (page == null) && config.OpenPageAfterUpload;
- string filename = FilenameHelper.GetFilenameWithoutExtensionFromPattern(coreConfig.OutputFileFilenamePattern, captureDetails);
+ Page selectedPage = _page;
+ bool openPage = (_page == null) && ConfluenceConfig.OpenPageAfterUpload;
+ string filename = FilenameHelper.GetFilenameWithoutExtensionFromPattern(CoreConfig.OutputFileFilenamePattern, captureDetails);
if (selectedPage == null) {
ConfluenceUpload confluenceUpload = new ConfluenceUpload(filename);
- Nullable dialogResult = confluenceUpload.ShowDialog();
+ bool? dialogResult = confluenceUpload.ShowDialog();
if (dialogResult.HasValue && dialogResult.Value) {
selectedPage = confluenceUpload.SelectedPage;
- if (confluenceUpload.isOpenPageSelected) {
+ if (confluenceUpload.IsOpenPageSelected) {
openPage = false;
}
filename = confluenceUpload.Filename;
}
}
- string extension = "." + config.UploadFormat;
+ string extension = "." + ConfluenceConfig.UploadFormat;
if (!filename.ToLower().EndsWith(extension)) {
filename = filename + extension;
}
if (selectedPage != null) {
string errorMessage;
- bool uploaded = upload(surface, selectedPage, filename, out errorMessage);
+ bool uploaded = Upload(surface, selectedPage, filename, out errorMessage);
if (uploaded) {
if (openPage) {
- try {
+ try
+ {
Process.Start(selectedPage.Url);
- } catch { }
+ }
+ catch
+ {
+ // Ignore
+ }
}
exportInformation.ExportMade = true;
exportInformation.Uri = selectedPage.Url;
@@ -158,31 +164,33 @@ namespace GreenshotConfluencePlugin {
return exportInformation;
}
- private bool upload(ISurface surfaceToUpload, Page page, string filename, out string errorMessage) {
- SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(config.UploadFormat, config.UploadJpegQuality, config.UploadReduceColors);
+ private bool Upload(ISurface surfaceToUpload, Page page, string filename, out string errorMessage) {
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(ConfluenceConfig.UploadFormat, ConfluenceConfig.UploadJpegQuality, ConfluenceConfig.UploadReduceColors);
errorMessage = null;
try {
new PleaseWaitForm().ShowAndWait(Description, Language.GetString("confluence", LangKey.communication_wait),
- delegate() {
- ConfluencePlugin.ConfluenceConnector.addAttachment(page.id, "image/" + config.UploadFormat.ToString().ToLower(), null, filename, new SurfaceContainer(surfaceToUpload, outputSettings, filename));
+ delegate {
+ ConfluencePlugin.ConfluenceConnector.AddAttachment(page.Id, "image/" + ConfluenceConfig.UploadFormat.ToString().ToLower(), null, filename, new SurfaceContainer(surfaceToUpload, outputSettings, filename));
}
);
- LOG.Debug("Uploaded to Confluence.");
- if (config.CopyWikiMarkupForImageToClipboard) {
- int retryCount = 2;
- while (retryCount >= 0) {
- try {
- Clipboard.SetText("!" + filename + "!");
- break;
- } catch (Exception ee) {
- if (retryCount == 0) {
- LOG.Error(ee);
- } else {
- Thread.Sleep(100);
- }
- } finally {
- --retryCount;
+ Log.Debug("Uploaded to Confluence.");
+ if (!ConfluenceConfig.CopyWikiMarkupForImageToClipboard)
+ {
+ return true;
+ }
+ int retryCount = 2;
+ while (retryCount >= 0) {
+ try {
+ Clipboard.SetText("!" + filename + "!");
+ break;
+ } catch (Exception ee) {
+ if (retryCount == 0) {
+ Log.Error(ee);
+ } else {
+ Thread.Sleep(100);
}
+ } finally {
+ --retryCount;
}
}
return true;
diff --git a/GreenshotConfluencePlugin/ConfluencePlugin.cs b/GreenshotConfluencePlugin/ConfluencePlugin.cs
index 9a3e459c7..eabc34b19 100644
--- a/GreenshotConfluencePlugin/ConfluencePlugin.cs
+++ b/GreenshotConfluencePlugin/ConfluencePlugin.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
@@ -68,8 +68,8 @@ namespace GreenshotConfluencePlugin {
CreateConfluenceConntector();
}
try {
- if (_confluenceConnector != null && !_confluenceConnector.isLoggedIn) {
- _confluenceConnector.login();
+ if (_confluenceConnector != null && !_confluenceConnector.IsLoggedIn) {
+ _confluenceConnector.Login();
}
} catch (Exception e) {
MessageBox.Show(Language.GetFormattedString("confluence", LangKey.login_error, e.Message));
@@ -112,7 +112,7 @@ namespace GreenshotConfluencePlugin {
public virtual void Shutdown() {
LOG.Debug("Confluence Plugin shutdown.");
if (_confluenceConnector != null) {
- _confluenceConnector.logout();
+ _confluenceConnector.Logout();
_confluenceConnector = null;
}
}
@@ -124,15 +124,15 @@ namespace GreenshotConfluencePlugin {
ConfluenceConfiguration clonedConfig = _config.Clone();
ConfluenceConfigurationForm configForm = new ConfluenceConfigurationForm(clonedConfig);
string url = _config.Url;
- Nullable dialogResult = configForm.ShowDialog();
+ bool? dialogResult = configForm.ShowDialog();
if (dialogResult.HasValue && dialogResult.Value) {
// copy the new object to the old...
clonedConfig.CloneTo(_config);
IniConfig.Save();
if (_confluenceConnector != null) {
if (!url.Equals(_config.Url)) {
- if (_confluenceConnector.isLoggedIn) {
- _confluenceConnector.logout();
+ if (_confluenceConnector.IsLoggedIn) {
+ _confluenceConnector.Logout();
}
_confluenceConnector = null;
}
diff --git a/GreenshotConfluencePlugin/ConfluenceUtils.cs b/GreenshotConfluencePlugin/ConfluenceUtils.cs
index 3ffafbfd6..19c417136 100644
--- a/GreenshotConfluencePlugin/ConfluenceUtils.cs
+++ b/GreenshotConfluencePlugin/ConfluenceUtils.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,7 +20,7 @@
*/
using System;
using System.Collections.Generic;
-using System.Diagnostics;
+using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Automation;
@@ -38,7 +38,7 @@ namespace GreenshotConfluencePlugin {
Regex pageIdRegex = new Regex(@"pageId=(\d+)");
Regex spacePageRegex = new Regex(@"\/display\/([^\/]+)\/([^#]+)");
foreach(string browserurl in GetBrowserUrls()) {
- string url = null;
+ string url;
try {
url = Uri.UnescapeDataString(browserurl).Replace("+", " ");
} catch {
@@ -51,14 +51,14 @@ namespace GreenshotConfluencePlugin {
try {
bool pageDouble = false;
foreach(Confluence.Page page in pages) {
- if (page.id == pageId) {
+ if (page.Id == pageId) {
pageDouble = true;
LOG.DebugFormat("Skipping double page with ID {0}", pageId);
break;
}
}
if (!pageDouble) {
- Confluence.Page page = ConfluencePlugin.ConfluenceConnector.getPage(pageId);
+ Confluence.Page page = ConfluencePlugin.ConfluenceConnector.GetPage(pageId);
LOG.DebugFormat("Adding page {0}", page.Title);
pages.Add(page);
}
@@ -90,12 +90,11 @@ namespace GreenshotConfluencePlugin {
}
}
if (!pageDouble) {
- Confluence.Page page = ConfluencePlugin.ConfluenceConnector.getPage(space, title);
+ Confluence.Page page = ConfluencePlugin.ConfluenceConnector.GetPage(space, title);
LOG.DebugFormat("Adding page {0}", page.Title);
pages.Add(page);
}
- continue;
} catch (Exception ex) {
// Preventing security problems
LOG.DebugFormat("Couldn't get page details for space {0} / title {1}", space, title);
@@ -133,7 +132,7 @@ namespace GreenshotConfluencePlugin {
if (pattern.ProgrammaticName != "ValuePatternIdentifiers.Pattern") {
continue;
}
- string url = (docElement.GetCurrentPattern(pattern) as ValuePattern).Current.Value.ToString();
+ string url = (docElement.GetCurrentPattern(pattern) as ValuePattern).Current.Value;
if (!string.IsNullOrEmpty(url)) {
urls.Add(url);
break;
@@ -141,7 +140,7 @@ namespace GreenshotConfluencePlugin {
}
}
- foreach(string url in IEHelper.GetIEUrls()) {
+ foreach(string url in IEHelper.GetIEUrls().Distinct()) {
urls.Add(url);
}
diff --git a/GreenshotConfluencePlugin/EnumDisplayer.cs b/GreenshotConfluencePlugin/EnumDisplayer.cs
index 102bf6732..ca55afa40 100644
--- a/GreenshotConfluencePlugin/EnumDisplayer.cs
+++ b/GreenshotConfluencePlugin/EnumDisplayer.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,61 +30,62 @@ using GreenshotPlugin.Core;
namespace GreenshotConfluencePlugin {
public class EnumDisplayer : IValueConverter {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(EnumDisplayer));
-
- private Type type;
- private IDictionary displayValues;
- private IDictionary reverseValues;
+ private Type _type;
+ private IDictionary _displayValues;
+ private IDictionary _reverseValues;
public EnumDisplayer() {
}
public EnumDisplayer(Type type) {
- this.Type = type;
+ Type = type;
}
public Type Type {
- get { return type; }
+ get { return _type; }
set {
if (!value.IsEnum) {
- throw new ArgumentException("parameter is not an Enumerated type", "value");
+ throw new ArgumentException("parameter is not an Enumerated type", nameof(value));
}
- this.type = value;
+ _type = value;
}
}
public ReadOnlyCollection DisplayNames {
get {
- this.reverseValues = (IDictionary) Activator.CreateInstance(typeof(Dictionary<,>).GetGenericTypeDefinition().MakeGenericType(typeof(string),type));
-
- this.displayValues = (IDictionary)Activator.CreateInstance(typeof(Dictionary<,>).GetGenericTypeDefinition().MakeGenericType(type, typeof(string)));
-
- var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static);
+ var genericTypeDefinition = typeof(Dictionary<,>).GetGenericTypeDefinition();
+ if (genericTypeDefinition != null)
+ {
+ _reverseValues = (IDictionary) Activator.CreateInstance(genericTypeDefinition.MakeGenericType(typeof(string),_type));
+ }
+
+ var typeDefinition = typeof(Dictionary<,>).GetGenericTypeDefinition();
+ if (typeDefinition != null)
+ {
+ _displayValues = (IDictionary)Activator.CreateInstance(typeDefinition.MakeGenericType(_type, typeof(string)));
+ }
+
+ var fields = _type.GetFields(BindingFlags.Public | BindingFlags.Static);
foreach (var field in fields) {
DisplayKeyAttribute[] a = (DisplayKeyAttribute[])field.GetCustomAttributes(typeof(DisplayKeyAttribute), false);
string displayKey = GetDisplayKeyValue(a);
object enumValue = field.GetValue(null);
- string displayString = null;
- if (displayKey != null && Language.hasKey(displayKey)) {
+ string displayString;
+ if (displayKey != null && Language.HasKey(displayKey)) {
displayString = Language.GetString(displayKey);
- } if (displayKey != null) {
- displayString = displayKey;
- } else {
- displayString = enumValue.ToString();
- }
-
- if (displayString != null) {
- displayValues.Add(enumValue, displayString);
- reverseValues.Add(displayString, enumValue);
}
+ displayString = displayKey ?? enumValue.ToString();
+
+ _displayValues.Add(enumValue, displayString);
+ _reverseValues.Add(displayString, enumValue);
}
- return new List((IEnumerable)displayValues.Values).AsReadOnly();
+ return new List((IEnumerable)_displayValues.Values).AsReadOnly();
}
}
- private string GetDisplayKeyValue(DisplayKeyAttribute[] a) {
+ private static string GetDisplayKeyValue(DisplayKeyAttribute[] a) {
if (a == null || a.Length == 0) {
return null;
}
@@ -93,11 +94,11 @@ namespace GreenshotConfluencePlugin {
}
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) {
- return displayValues[value];
+ return _displayValues[value];
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
- return reverseValues[value];
+ return _reverseValues[value];
}
}
}
diff --git a/GreenshotConfluencePlugin/Forms/ConfluenceConfigurationForm.xaml.cs b/GreenshotConfluencePlugin/Forms/ConfluenceConfigurationForm.xaml.cs
index 63b72292d..4ce336f3c 100644
--- a/GreenshotConfluencePlugin/Forms/ConfluenceConfigurationForm.xaml.cs
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceConfigurationForm.xaml.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,7 +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.Windows;
namespace GreenshotConfluencePlugin {
@@ -26,20 +26,15 @@ namespace GreenshotConfluencePlugin {
/// Interaction logic for ConfluenceConfigurationForm.xaml
///
public partial class ConfluenceConfigurationForm : Window {
- private ConfluenceConfiguration config;
- public ConfluenceConfiguration Config {
- get {
- return config;
- }
- }
-
+ public ConfluenceConfiguration Config { get; }
+
public ConfluenceConfigurationForm(ConfluenceConfiguration config) {
- this.DataContext = config;
- this.config = config;
+ DataContext = config;
+ Config = config;
InitializeComponent();
}
-
- void Button_OK_Click(object sender, RoutedEventArgs e) {
+
+ private void Button_OK_Click(object sender, RoutedEventArgs e) {
DialogResult = true;
}
}
diff --git a/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml b/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml
index 4fe9f18e6..6455e86b5 100644
--- a/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml
+++ b/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml
@@ -1,7 +1,7 @@
+ Loaded="Page_Loaded">
diff --git a/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml.cs b/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml.cs
index a8ddec0dd..0d5f78bfb 100644
--- a/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml.cs
+++ b/GreenshotConfluencePlugin/Forms/ConfluencePagePicker.xaml.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,7 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-using System;
+
using Confluence;
using System.Collections.Generic;
@@ -26,31 +26,31 @@ namespace GreenshotConfluencePlugin {
///
/// Interaction logic for ConfluencePagePicker.xaml
///
- public partial class ConfluencePagePicker : System.Windows.Controls.Page {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluencePagePicker));
- private ConfluenceUpload confluenceUpload = null;
+ public partial class ConfluencePagePicker
+ {
+ private readonly ConfluenceUpload _confluenceUpload;
public ConfluencePagePicker(ConfluenceUpload confluenceUpload, List pagesToPick) {
- this.confluenceUpload = confluenceUpload;
- this.DataContext = pagesToPick;
+ _confluenceUpload = confluenceUpload;
+ DataContext = pagesToPick;
InitializeComponent();
}
-
- void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
+
+ private void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
SelectionChanged();
}
-
- void SelectionChanged() {
+
+ private void SelectionChanged() {
if (PageListView.HasItems && PageListView.SelectedItems.Count > 0) {
- confluenceUpload.SelectedPage = (Page)PageListView.SelectedItem;
+ _confluenceUpload.SelectedPage = (Page)PageListView.SelectedItem;
// Make sure the uploader knows we selected an already opened page
- confluenceUpload.isOpenPageSelected = true;
+ _confluenceUpload.IsOpenPageSelected = true;
} else {
- confluenceUpload.SelectedPage = null;
+ _confluenceUpload.SelectedPage = null;
}
}
-
- void Page_Loaded(object sender, System.Windows.RoutedEventArgs e) {
+
+ private void Page_Loaded(object sender, System.Windows.RoutedEventArgs e) {
SelectionChanged();
}
}
diff --git a/GreenshotConfluencePlugin/Forms/ConfluenceSearch.xaml.cs b/GreenshotConfluencePlugin/Forms/ConfluenceSearch.xaml.cs
index 3c816a2f9..815222ef7 100644
--- a/GreenshotConfluencePlugin/Forms/ConfluenceSearch.xaml.cs
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceSearch.xaml.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,83 +18,71 @@
* 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.Collections.ObjectModel;
+using System.Linq;
using System.Windows;
-
-using Confluence;
-using GreenshotPlugin.Core;
using Greenshot.IniFile;
namespace GreenshotConfluencePlugin {
- public partial class ConfluenceSearch : System.Windows.Controls.Page {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluenceSearch));
- private static ConfluenceConfiguration config = IniConfig.GetIniSection();
- private ConfluenceUpload confluenceUpload;
+ public partial class ConfluenceSearch
+ {
+ private static readonly ConfluenceConfiguration ConfluenceConfig = IniConfig.GetIniSection();
+ private readonly ConfluenceUpload _confluenceUpload;
- public List Spaces {
- get {
- return confluenceUpload.Spaces;
- }
- }
+ public IEnumerable Spaces => _confluenceUpload.Spaces;
- private ObservableCollection pages = new ObservableCollection();
- public ObservableCollection Pages {
- get {
- return pages;
- }
- }
+ public ObservableCollection Pages { get; } = new ObservableCollection();
public ConfluenceSearch(ConfluenceUpload confluenceUpload) {
- this.confluenceUpload = confluenceUpload;
- this.DataContext = this;
+ _confluenceUpload = confluenceUpload;
+ DataContext = this;
InitializeComponent();
- if (config.SearchSpaceKey == null) {
- this.SpaceComboBox.SelectedItem = Spaces[0];
+ if (ConfluenceConfig.SearchSpaceKey == null) {
+ SpaceComboBox.SelectedItem = Spaces.FirstOrDefault();
} else {
- foreach(Confluence.Space space in Spaces) {
- if (space.Key.Equals(config.SearchSpaceKey)) {
- this.SpaceComboBox.SelectedItem = space;
+ foreach(var space in Spaces) {
+ if (space.Key.Equals(ConfluenceConfig.SearchSpaceKey)) {
+ SpaceComboBox.SelectedItem = space;
}
}
}
}
- void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
+ private void PageListView_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
SelectionChanged();
}
-
- void SelectionChanged() {
+
+ private void SelectionChanged() {
if (PageListView.HasItems && PageListView.SelectedItems.Count > 0) {
- confluenceUpload.SelectedPage = (Confluence.Page)PageListView.SelectedItem;
+ _confluenceUpload.SelectedPage = (Confluence.Page)PageListView.SelectedItem;
} else {
- confluenceUpload.SelectedPage = null;
+ _confluenceUpload.SelectedPage = null;
}
}
-
- void Search_Click(object sender, RoutedEventArgs e) {
- doSearch();
+
+ private void Search_Click(object sender, RoutedEventArgs e) {
+ DoSearch();
}
- void doSearch() {
+ private void DoSearch() {
string spaceKey = (string)SpaceComboBox.SelectedValue;
- config.SearchSpaceKey = spaceKey;
- List searchResult = ConfluencePlugin.ConfluenceConnector.searchPages(searchText.Text, spaceKey);
- pages.Clear();
- foreach(Confluence.Page page in searchResult) {
- pages.Add(page);
+ ConfluenceConfig.SearchSpaceKey = spaceKey;
+ Pages.Clear();
+ foreach(var page in ConfluencePlugin.ConfluenceConnector.SearchPages(searchText.Text, spaceKey).OrderBy(p => p.Title)) {
+ Pages.Add(page);
}
}
- void SearchText_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) {
+ private void SearchText_KeyDown(object sender, System.Windows.Input.KeyEventArgs e) {
if (e.Key == System.Windows.Input.Key.Return && Search.IsEnabled) {
- doSearch();
- e.Handled = true;
+ DoSearch();
+ e.Handled = true;
}
}
-
- void Page_Loaded(object sender, System.Windows.RoutedEventArgs e) {
+
+ private void Page_Loaded(object sender, RoutedEventArgs e) {
SelectionChanged();
}
diff --git a/GreenshotConfluencePlugin/Forms/ConfluenceTreePicker.xaml.cs b/GreenshotConfluencePlugin/Forms/ConfluenceTreePicker.xaml.cs
index b639a5f98..6d3768973 100644
--- a/GreenshotConfluencePlugin/Forms/ConfluenceTreePicker.xaml.cs
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceTreePicker.xaml.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,8 +18,9 @@
* 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.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
@@ -27,102 +28,104 @@ using System.Windows.Input;
using System.Windows.Threading;
using Confluence;
-using GreenshotPlugin.Core;
namespace GreenshotConfluencePlugin {
///
/// Interaction logic for ConfluenceTreePicker.xaml
///
- public partial class ConfluenceTreePicker : System.Windows.Controls.Page {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ConfluenceTreePicker));
- private ConfluenceConnector confluenceConnector;
- private ConfluenceUpload confluenceUpload;
- private bool isInitDone = false;
+ public partial class ConfluenceTreePicker
+ {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ConfluenceTreePicker));
+ private readonly ConfluenceConnector _confluenceConnector;
+ private readonly ConfluenceUpload _confluenceUpload;
+ private bool _isInitDone;
public ConfluenceTreePicker(ConfluenceUpload confluenceUpload) {
- this.confluenceConnector = ConfluencePlugin.ConfluenceConnector;
- this.confluenceUpload = confluenceUpload;
+ _confluenceConnector = ConfluencePlugin.ConfluenceConnector;
+ _confluenceUpload = confluenceUpload;
InitializeComponent();
}
- void pageTreeViewItem_DoubleClick(object sender, MouseButtonEventArgs eventArgs) {
- LOG.Debug("spaceTreeViewItem_MouseLeftButtonDown is called!");
+ private void pageTreeViewItem_DoubleClick(object sender, MouseButtonEventArgs eventArgs) {
+ Log.Debug("spaceTreeViewItem_MouseLeftButtonDown is called!");
TreeViewItem clickedItem = eventArgs.Source as TreeViewItem;
- if (clickedItem ==null) {
- return;
- }
- Confluence.Page page = clickedItem.Tag as Confluence.Page;
+ Confluence.Page page = clickedItem?.Tag as Confluence.Page;
if (page == null) {
return;
}
- if (!clickedItem.HasItems) {
- LOG.Debug("Loading pages for page: " + page.Title);
- (new Thread(() => {
- Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {ShowBusy.Visibility = Visibility.Visible;}));
- List pages = confluenceConnector.getPageChildren(page);
- Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {
- foreach(Confluence.Page childPage in pages) {
- LOG.Debug("Adding page: " + childPage.Title);
- TreeViewItem pageTreeViewItem = new TreeViewItem();
- pageTreeViewItem.Header = childPage.Title;
- pageTreeViewItem.Tag = childPage;
- clickedItem.Items.Add(pageTreeViewItem);
- pageTreeViewItem.PreviewMouseDoubleClick += new MouseButtonEventHandler(pageTreeViewItem_DoubleClick);
- pageTreeViewItem.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(pageTreeViewItem_Click);
- }
- ShowBusy.Visibility = Visibility.Collapsed;
- }));
- }
- ) { Name = "Loading childpages for confluence page " + page.Title }).Start();
+ if (clickedItem.HasItems)
+ {
+ return;
}
+ Log.Debug("Loading pages for page: " + page.Title);
+ new Thread(() => {
+ Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {ShowBusy.Visibility = Visibility.Visible;}));
+ var pages = _confluenceConnector.GetPageChildren(page).OrderBy(p => p.Title);
+ Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {
+ foreach(var childPage in pages) {
+ Log.Debug("Adding page: " + childPage.Title);
+ var pageTreeViewItem = new TreeViewItem
+ {
+ Header = childPage.Title,
+ Tag = childPage
+ };
+ clickedItem.Items.Add(pageTreeViewItem);
+ pageTreeViewItem.PreviewMouseDoubleClick += pageTreeViewItem_DoubleClick;
+ pageTreeViewItem.PreviewMouseLeftButtonDown += pageTreeViewItem_Click;
+ }
+ ShowBusy.Visibility = Visibility.Collapsed;
+ }));
+ }) { Name = "Loading childpages for confluence page " + page.Title }.Start();
}
-
- void pageTreeViewItem_Click(object sender, MouseButtonEventArgs eventArgs) {
- LOG.Debug("pageTreeViewItem_PreviewMouseDoubleClick is called!");
+
+ private void pageTreeViewItem_Click(object sender, MouseButtonEventArgs eventArgs) {
+ Log.Debug("pageTreeViewItem_PreviewMouseDoubleClick is called!");
TreeViewItem clickedItem = eventArgs.Source as TreeViewItem;
if (clickedItem ==null) {
return;
}
Confluence.Page page = clickedItem.Tag as Confluence.Page;
- confluenceUpload.SelectedPage = page;
+ _confluenceUpload.SelectedPage = page;
if (page != null) {
- LOG.Debug("Page selected: " + page.Title);
+ Log.Debug("Page selected: " + page.Title);
}
}
- void Page_Loaded(object sender, RoutedEventArgs e) {
- confluenceUpload.SelectedPage = null;
- if (isInitDone) {
+ private void Page_Loaded(object sender, RoutedEventArgs e) {
+ _confluenceUpload.SelectedPage = null;
+ if (_isInitDone) {
return;
}
ShowBusy.Visibility = Visibility.Visible;
- (new Thread(() => {
+ new Thread(() => {
Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)(() => {
- List spaces = confluenceUpload.Spaces;
- foreach (Space space in spaces) {
- TreeViewItem spaceTreeViewItem = new TreeViewItem();
- spaceTreeViewItem.Header = space.Name;
- spaceTreeViewItem.Tag = space;
-
+ foreach (Space space in _confluenceUpload.Spaces) {
+ TreeViewItem spaceTreeViewItem = new TreeViewItem
+ {
+ Header = space.Name,
+ Tag = space
+ };
+
// Get homepage
try {
- Confluence.Page page = confluenceConnector.getSpaceHomepage(space);
- TreeViewItem pageTreeViewItem = new TreeViewItem();
- pageTreeViewItem.Header = page.Title;
- pageTreeViewItem.Tag = page;
- pageTreeViewItem.PreviewMouseDoubleClick += new MouseButtonEventHandler(pageTreeViewItem_DoubleClick);
- pageTreeViewItem.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(pageTreeViewItem_Click);
+ Confluence.Page page = _confluenceConnector.GetSpaceHomepage(space);
+ TreeViewItem pageTreeViewItem = new TreeViewItem
+ {
+ Header = page.Title,
+ Tag = page
+ };
+ pageTreeViewItem.PreviewMouseDoubleClick += pageTreeViewItem_DoubleClick;
+ pageTreeViewItem.PreviewMouseLeftButtonDown += pageTreeViewItem_Click;
spaceTreeViewItem.Items.Add(pageTreeViewItem);
ConfluenceTreeView.Items.Add(spaceTreeViewItem);
} catch (Exception ex) {
- LOG.Error("Can't get homepage for space : " + space.Name + " (" + ex.Message + ")");
+ Log.Error("Can't get homepage for space : " + space.Name + " (" + ex.Message + ")");
}
}
ShowBusy.Visibility = Visibility.Collapsed;
- isInitDone = true;
+ _isInitDone = true;
}));
- }
- ) { Name = "Loading spaces for confluence"}).Start();
+ }) { Name = "Loading spaces for confluence"}.Start();
}
}
}
\ No newline at end of file
diff --git a/GreenshotConfluencePlugin/Forms/ConfluenceUpload.xaml.cs b/GreenshotConfluencePlugin/Forms/ConfluenceUpload.xaml.cs
index 3c3d9442e..82424d5c7 100644
--- a/GreenshotConfluencePlugin/Forms/ConfluenceUpload.xaml.cs
+++ b/GreenshotConfluencePlugin/Forms/ConfluenceUpload.xaml.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 System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
@@ -29,56 +30,56 @@ namespace GreenshotConfluencePlugin {
/// Interaction logic for ConfluenceUpload.xaml
///
public partial class ConfluenceUpload : Window {
- private Page pickerPage = null;
+ private Page _pickerPage;
public Page PickerPage {
get {
- if (pickerPage == null) {
+ if (_pickerPage == null) {
List pages = ConfluenceUtils.GetCurrentPages();
if (pages != null && pages.Count > 0) {
- pickerPage = new ConfluencePagePicker(this, pages);
+ _pickerPage = new ConfluencePagePicker(this, pages);
}
}
- return pickerPage;
+ return _pickerPage;
}
}
- private Page searchPage = null;
+ private Page _searchPage;
public Page SearchPage {
get {
- if (searchPage == null) {
- searchPage = new ConfluenceSearch(this);
+ if (_searchPage == null) {
+ _searchPage = new ConfluenceSearch(this);
}
- return searchPage;
+ return _searchPage;
}
}
- private Page browsePage = null;
+ private Page _browsePage;
public Page BrowsePage {
get {
- if (browsePage == null) {
- browsePage = new ConfluenceTreePicker(this);
+ if (_browsePage == null) {
+ _browsePage = new ConfluenceTreePicker(this);
}
- return browsePage;
+ return _browsePage;
}
}
- private Confluence.Page selectedPage = null;
+ private Confluence.Page _selectedPage;
public Confluence.Page SelectedPage {
get {
- return selectedPage;
+ return _selectedPage;
}
set {
- selectedPage = value;
- if (selectedPage != null) {
+ _selectedPage = value;
+ if (_selectedPage != null) {
Upload.IsEnabled = true;
} else {
Upload.IsEnabled = false;
}
- isOpenPageSelected = false;
+ IsOpenPageSelected = false;
}
}
- public bool isOpenPageSelected {
+ public bool IsOpenPageSelected {
get;
set;
}
@@ -87,44 +88,44 @@ namespace GreenshotConfluencePlugin {
set;
}
- private static DateTime lastLoad = DateTime.Now;
- private static List spaces;
- public List Spaces {
+ private static DateTime _lastLoad = DateTime.Now;
+ private static IList _spaces;
+ public IList Spaces {
get {
- updateSpaces();
- while (spaces == null) {
+ UpdateSpaces();
+ while (_spaces == null) {
Thread.Sleep(300);
}
- return spaces;
+ return _spaces;
}
}
public ConfluenceUpload(string filename) {
- this.Filename = filename;
+ Filename = filename;
InitializeComponent();
- this.DataContext = this;
- updateSpaces();
+ DataContext = this;
+ UpdateSpaces();
if (PickerPage == null) {
- PickerTab.Visibility = System.Windows.Visibility.Collapsed;
+ PickerTab.Visibility = Visibility.Collapsed;
SearchTab.IsSelected = true;
}
}
-
- void updateSpaces() {
- if (spaces != null && DateTime.Now.AddMinutes(-60).CompareTo(lastLoad) > 0) {
+
+ private void UpdateSpaces() {
+ if (_spaces != null && DateTime.Now.AddMinutes(-60).CompareTo(_lastLoad) > 0) {
// Reset
- spaces = null;
+ _spaces = null;
}
// Check if load is needed
- if (spaces == null) {
+ if (_spaces == null) {
(new Thread(() => {
- spaces = ConfluencePlugin.ConfluenceConnector.getSpaceSummaries();
- lastLoad = DateTime.Now;
+ _spaces = ConfluencePlugin.ConfluenceConnector.GetSpaceSummaries().OrderBy(s => s.Name).ToList();
+ _lastLoad = DateTime.Now;
}) { Name = "Loading spaces for confluence"}).Start();
}
}
- void Upload_Click(object sender, RoutedEventArgs e) {
+ private void Upload_Click(object sender, RoutedEventArgs e) {
DialogResult = true;
}
}
diff --git a/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj b/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj
index b0535116e..c531a3499 100644
--- a/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj
+++ b/GreenshotConfluencePlugin/GreenshotConfluencePlugin.csproj
@@ -143,10 +143,10 @@
- mkdir "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)"
-copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
-copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\"
-mkdir "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
-copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+ mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
\ No newline at end of file
diff --git a/GreenshotConfluencePlugin/LanguageKeys.cs b/GreenshotConfluencePlugin/LanguageKeys.cs
index 3936ac398..5f4213764 100644
--- a/GreenshotConfluencePlugin/LanguageKeys.cs
+++ b/GreenshotConfluencePlugin/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
diff --git a/GreenshotConfluencePlugin/Properties/AssemblyInfo.cs b/GreenshotConfluencePlugin/Properties/AssemblyInfo.cs
index b9720505b..17d53dec2 100644
--- a/GreenshotConfluencePlugin/Properties/AssemblyInfo.cs
+++ b/GreenshotConfluencePlugin/Properties/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
@@ -32,7 +32,7 @@ using System.Security;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Greenshot")]
[assembly: AssemblyProduct("Confluence Plugin")]
-[assembly: AssemblyCopyright("Copyright (C) 2007-2015")]
+[assembly: AssemblyCopyright("Copyright (C) 2007-2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The PluginAttribute describes the "entryType" and if the plugin is configurable
diff --git a/GreenshotConfluencePlugin/Support/ITranslationProvider.cs b/GreenshotConfluencePlugin/Support/ITranslationProvider.cs
index 6bd4bf402..79efd538c 100644
--- a/GreenshotConfluencePlugin/Support/ITranslationProvider.cs
+++ b/GreenshotConfluencePlugin/Support/ITranslationProvider.cs
@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-
-namespace TranslationByMarkupExtension {
+namespace TranslationByMarkupExtension {
public interface ITranslationProvider {
///
/// Translates the specified key.
@@ -10,11 +6,5 @@ namespace TranslationByMarkupExtension {
/// The key.
///
object Translate(string key);
-
- ///
- /// Gets the available languages.
- ///
- /// The available languages.
- //IEnumerable Languages { get; }
}
}
diff --git a/GreenshotConfluencePlugin/Support/LanguageChangedEventManager.cs b/GreenshotConfluencePlugin/Support/LanguageChangedEventManager.cs
index 056f9dfb0..8fe9289d3 100644
--- a/GreenshotConfluencePlugin/Support/LanguageChangedEventManager.cs
+++ b/GreenshotConfluencePlugin/Support/LanguageChangedEventManager.cs
@@ -26,7 +26,7 @@ namespace TranslationByMarkupExtension
manager.LanguageChanged += OnLanguageChanged;
}
- protected override void StopListening(Object source)
+ protected override void StopListening(object source)
{
var manager = (TranslationManager)source;
manager.LanguageChanged -= OnLanguageChanged;
diff --git a/GreenshotConfluencePlugin/Support/LanguageXMLTranslationProvider.cs b/GreenshotConfluencePlugin/Support/LanguageXMLTranslationProvider.cs
index 75d952e76..e5cf3bfe8 100644
--- a/GreenshotConfluencePlugin/Support/LanguageXMLTranslationProvider.cs
+++ b/GreenshotConfluencePlugin/Support/LanguageXMLTranslationProvider.cs
@@ -1,58 +1,30 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-
-using GreenshotConfluencePlugin;
-using GreenshotPlugin.Core;
+using GreenshotPlugin.Core;
namespace TranslationByMarkupExtension {
- ///
- ///
- ///
- public class LanguageXMLTranslationProvider : ITranslationProvider {
- #region Private Members
+ ///
+ ///
+ ///
+ public class LanguageXMLTranslationProvider : ITranslationProvider {
+ #region Private Members
- #endregion
+ #endregion
- #region Construction
+ #region Construction
- ///
- /// Initializes a new instance of the class.
- ///
- /// Name of the base.
- /// The assembly.
- public LanguageXMLTranslationProvider() {
- }
+ #endregion
- #endregion
+ #region ITranslationProvider Members
- #region ITranslationProvider Members
-
- ///
- /// See
- ///
- public object Translate(string key) {
- if (Language.hasKey("confluence", key)) {
+ ///
+ /// See
+ ///
+ public object Translate(string key) {
+ if (Language.HasKey("confluence", key)) {
return Language.GetString("confluence", key);
- }
- return key;
- }
+ }
+ return key;
+ }
- #endregion
-
- #region ITranslationProvider Members
-
- ///
- /// See
- ///
- /*public IEnumerable Languages {
- get {
- foreach (LanguageFile supportedLanguage in Language.SupportedLanguages) {
- yield return new CultureInfo(supportedLanguage.Ietf);
- }
- }
- }*/
-
- #endregion
- }
+ #endregion
+ }
}
diff --git a/GreenshotConfluencePlugin/Support/TranslationData.cs b/GreenshotConfluencePlugin/Support/TranslationData.cs
index b47fe4a65..287cca4c0 100644
--- a/GreenshotConfluencePlugin/Support/TranslationData.cs
+++ b/GreenshotConfluencePlugin/Support/TranslationData.cs
@@ -3,62 +3,55 @@ using System.ComponentModel;
using System.Windows;
namespace TranslationByMarkupExtension {
- public class TranslationData : IWeakEventListener, INotifyPropertyChanged {
- #region Private Members
+ public class TranslationData : IWeakEventListener, INotifyPropertyChanged {
+ #region Private Members
- private string _key;
+ private readonly string _key;
- #endregion
+ #endregion
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- public TranslationData( string key) {
- _key = key;
- LanguageChangedEventManager.AddListener(TranslationManager.Instance, this);
- }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ public TranslationData( string key) {
+ _key = key;
+ LanguageChangedEventManager.AddListener(TranslationManager.Instance, this);
+ }
- ///
- /// Releases unmanaged resources and performs other cleanup operations before the
- /// is reclaimed by garbage collection.
- ///
- ~TranslationData() {
- LanguageChangedEventManager.RemoveListener(TranslationManager.Instance, this);
- }
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~TranslationData() {
+ LanguageChangedEventManager.RemoveListener(TranslationManager.Instance, this);
+ }
- public object Value {
- get {
- return TranslationManager.Instance.Translate(_key);
- }
- }
+ public object Value => TranslationManager.Instance.Translate(_key);
- #region IWeakEventListener Members
+ #region IWeakEventListener Members
- public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
- {
- if (managerType == typeof(LanguageChangedEventManager))
- {
- OnLanguageChanged(sender, e);
- return true;
- }
- return false;
- }
+ public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
+ {
+ if (managerType == typeof(LanguageChangedEventManager))
+ {
+ OnLanguageChanged(sender, e);
+ return true;
+ }
+ return false;
+ }
- private void OnLanguageChanged(object sender, EventArgs e)
- {
- if( PropertyChanged != null )
- {
- PropertyChanged( this, new PropertyChangedEventArgs("Value"));
- }
- }
+ private void OnLanguageChanged(object sender, EventArgs e)
+ {
+ PropertyChanged?.Invoke( this, new PropertyChangedEventArgs("Value"));
+ }
- #endregion
+ #endregion
- #region INotifyPropertyChanged Members
+ #region INotifyPropertyChanged Members
- public event PropertyChangedEventHandler PropertyChanged;
+ public event PropertyChangedEventHandler PropertyChanged;
- #endregion
- }
+ #endregion
+ }
}
diff --git a/GreenshotConfluencePlugin/Support/TranslationManager.cs b/GreenshotConfluencePlugin/Support/TranslationManager.cs
index fa801d3d2..bf315a5d5 100644
--- a/GreenshotConfluencePlugin/Support/TranslationManager.cs
+++ b/GreenshotConfluencePlugin/Support/TranslationManager.cs
@@ -1,59 +1,45 @@
using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Threading;
namespace TranslationByMarkupExtension {
- public class TranslationManager {
- private static TranslationManager _translationManager;
+ public class TranslationManager {
+ private static TranslationManager _translationManager;
- public event EventHandler LanguageChanged;
+ public event EventHandler LanguageChanged;
- /*public CultureInfo CurrentLanguage {
- get { return Thread.CurrentThread.CurrentUICulture; }
- set {
- if( value != Thread.CurrentThread.CurrentUICulture) {
- Thread.CurrentThread.CurrentUICulture = value;
- OnLanguageChanged();
- }
- }
- }
-
- public IEnumerable Languages {
- get {
- if( TranslationProvider != null) {
- return TranslationProvider.Languages;
- }
- return Enumerable.Empty();
- }
- }*/
-
- public static TranslationManager Instance {
- get {
- if (_translationManager == null) {
- _translationManager = new TranslationManager();
+ /*public CultureInfo CurrentLanguage {
+ get { return Thread.CurrentThread.CurrentUICulture; }
+ set {
+ if( value != Thread.CurrentThread.CurrentUICulture) {
+ Thread.CurrentThread.CurrentUICulture = value;
+ OnLanguageChanged();
}
- return _translationManager;
- }
- }
+ }
+ }
- public ITranslationProvider TranslationProvider { get; set; }
+ public IEnumerable Languages {
+ get {
+ if( TranslationProvider != null) {
+ return TranslationProvider.Languages;
+ }
+ return Enumerable.Empty();
+ }
+ }*/
- private void OnLanguageChanged() {
- if (LanguageChanged != null) {
- LanguageChanged(this, EventArgs.Empty);
- }
- }
+ public static TranslationManager Instance => _translationManager ?? (_translationManager = new TranslationManager());
- public object Translate(string key) {
- if( TranslationProvider != null) {
- object translatedValue = TranslationProvider.Translate(key);
- if( translatedValue != null) {
- return translatedValue;
- }
- }
- return string.Format("!{0}!", key);
- }
- }
+ public ITranslationProvider TranslationProvider { get; set; }
+
+ private void OnLanguageChanged()
+ {
+ LanguageChanged?.Invoke(this, EventArgs.Empty);
+ }
+
+ public object Translate(string key) {
+ object translatedValue = TranslationProvider?.Translate(key);
+ if( translatedValue != null) {
+ return translatedValue;
+ }
+ return $"!{key}!";
+ }
+ }
}
diff --git a/GreenshotDropboxPlugin/DropBoxCredentials.cs b/GreenshotDropboxPlugin/DropBoxCredentials.cs
index bd6f17366..c02e848ca 100644
--- a/GreenshotDropboxPlugin/DropBoxCredentials.cs
+++ b/GreenshotDropboxPlugin/DropBoxCredentials.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/GreenshotDropboxPlugin/DropboxDestination.cs b/GreenshotDropboxPlugin/DropboxDestination.cs
index c4f79732f..1e378a7a1 100644
--- a/GreenshotDropboxPlugin/DropboxDestination.cs
+++ b/GreenshotDropboxPlugin/DropboxDestination.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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
@@ -23,27 +23,19 @@ using System.Drawing;
using Greenshot.IniFile;
using Greenshot.Plugin;
using GreenshotPlugin.Core;
-namespace GreenshotDropboxPlugin {
- class DropboxDestination : AbstractDestination {
- private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(DropboxDestination));
- private static DropboxPluginConfiguration config = IniConfig.GetIniSection();
- private DropboxPlugin plugin = null;
+namespace GreenshotDropboxPlugin {
+ internal class DropboxDestination : AbstractDestination {
+ private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection();
+
+ private readonly DropboxPlugin _plugin;
public DropboxDestination(DropboxPlugin plugin) {
- this.plugin = plugin;
+ _plugin = plugin;
}
- public override string Designation {
- get {
- return "Dropbox";
- }
- }
+ public override string Designation => "Dropbox";
- public override string Description {
- get {
- return Language.GetString("dropbox", LangKey.upload_menu_item);
- }
- }
+ public override string Description => Language.GetString("dropbox", LangKey.upload_menu_item);
public override Image DisplayIcon {
get {
@@ -53,14 +45,14 @@ namespace GreenshotDropboxPlugin {
}
public override ExportInformation ExportCapture(bool manually, ISurface surface, ICaptureDetails captureDetails) {
- ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description);
- string uploadURL = null;
- bool uploaded = plugin.Upload(captureDetails, surface, out uploadURL);
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string uploadUrl;
+ bool uploaded = _plugin.Upload(captureDetails, surface, out uploadUrl);
if (uploaded) {
- exportInformation.Uri = uploadURL;
+ exportInformation.Uri = uploadUrl;
exportInformation.ExportMade = true;
- if (config.AfterUploadLinkToClipBoard) {
- ClipboardHelper.SetClipboardData(uploadURL);
+ if (DropboxConfig.AfterUploadLinkToClipBoard) {
+ ClipboardHelper.SetClipboardData(uploadUrl);
}
}
ProcessExport(exportInformation, surface);
diff --git a/GreenshotDropboxPlugin/DropboxPlugin.cs b/GreenshotDropboxPlugin/DropboxPlugin.cs
index 772545395..9bd6115c5 100644
--- a/GreenshotDropboxPlugin/DropboxPlugin.cs
+++ b/GreenshotDropboxPlugin/DropboxPlugin.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,12 +34,12 @@ namespace GreenshotDropboxPlugin {
/// This is the Dropbox base code
///
public class DropboxPlugin : IGreenshotPlugin {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(DropboxPlugin));
- private static DropboxPluginConfiguration config;
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxPlugin));
+ private static DropboxPluginConfiguration _config;
public static PluginAttribute Attributes;
- private IGreenshotHost host;
- private ComponentResourceManager resources;
- private ToolStripMenuItem itemPlugInConfig;
+ private IGreenshotHost _host;
+ private ComponentResourceManager _resources;
+ private ToolStripMenuItem _itemPlugInConfig;
public void Dispose() {
Dispose(true);
@@ -48,16 +48,13 @@ namespace GreenshotDropboxPlugin {
protected virtual void Dispose(bool disposing) {
if (disposing) {
- if (itemPlugInConfig != null) {
- itemPlugInConfig.Dispose();
- itemPlugInConfig = null;
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Dispose();
+ _itemPlugInConfig = null;
}
}
}
- public DropboxPlugin() {
- }
-
public IEnumerable Destinations() {
yield return new DropboxDestination(this);
}
@@ -70,56 +67,48 @@ namespace GreenshotDropboxPlugin {
///
/// Implementation of the IGreenshotPlugin.Initialize
///
- /// Use the IGreenshotPluginHost interface to register events
- /// My own attributes
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
- this.host = (IGreenshotHost)pluginHost;
+ _host = pluginHost;
Attributes = myAttributes;
// Register configuration (don't need the configuration itself)
- config = IniConfig.GetIniSection();
- resources = new ComponentResourceManager(typeof(DropboxPlugin));
+ _config = IniConfig.GetIniSection();
+ _resources = new ComponentResourceManager(typeof(DropboxPlugin));
- itemPlugInConfig = new ToolStripMenuItem();
- itemPlugInConfig.Text = Language.GetString("dropbox", LangKey.Configure);
- itemPlugInConfig.Tag = host;
- itemPlugInConfig.Click += new System.EventHandler(ConfigMenuClick);
- itemPlugInConfig.Image = (Image)resources.GetObject("Dropbox");
+ _itemPlugInConfig = new ToolStripMenuItem
+ {
+ Text = Language.GetString("dropbox", LangKey.Configure),
+ Tag = _host,
+ Image = (Image)_resources.GetObject("Dropbox")
+ };
+ _itemPlugInConfig.Click += ConfigMenuClick;
- PluginUtils.AddToContextMenu(host, itemPlugInConfig);
- Language.LanguageChanged += new LanguageChangedHandler(OnLanguageChanged);
+ PluginUtils.AddToContextMenu(_host, _itemPlugInConfig);
+ Language.LanguageChanged += OnLanguageChanged;
return true;
}
public void OnLanguageChanged(object sender, EventArgs e) {
- if (itemPlugInConfig != null) {
- itemPlugInConfig.Text = Language.GetString("dropbox", LangKey.Configure);
+ if (_itemPlugInConfig != null) {
+ _itemPlugInConfig.Text = Language.GetString("dropbox", LangKey.Configure);
}
}
public virtual void Shutdown() {
- LOG.Debug("Dropbox Plugin shutdown.");
+ Log.Debug("Dropbox Plugin shutdown.");
}
///
/// Implementation of the IPlugin.Configure
///
public virtual void Configure() {
- config.ShowConfigDialog();
- }
-
- ///
- /// This will be called when Greenshot is shutting down
- ///
- ///
- ///
- public void Closing(object sender, FormClosingEventArgs e) {
- LOG.Debug("Application closing, de-registering Dropbox Plugin!");
- Shutdown();
+ _config.ShowConfigDialog();
}
public void ConfigMenuClick(object sender, EventArgs eventArgs) {
- config.ShowConfigDialog();
+ _config.ShowConfigDialog();
}
///
@@ -127,12 +116,13 @@ namespace GreenshotDropboxPlugin {
///
public bool Upload(ICaptureDetails captureDetails, ISurface surfaceToUpload, out string uploadUrl) {
uploadUrl = null;
- SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(config.UploadFormat, config.UploadJpegQuality, false);
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(_config.UploadFormat, _config.UploadJpegQuality, false);
try {
string dropboxUrl = null;
new PleaseWaitForm().ShowAndWait(Attributes.Name, Language.GetString("dropbox", LangKey.communication_wait),
- delegate() {
- string filename = Path.GetFileName(FilenameHelper.GetFilename(config.UploadFormat, captureDetails));
+ delegate
+ {
+ string filename = Path.GetFileName(FilenameHelper.GetFilename(_config.UploadFormat, captureDetails));
dropboxUrl = DropboxUtils.UploadToDropbox(surfaceToUpload, outputSettings, filename);
}
);
@@ -142,7 +132,7 @@ namespace GreenshotDropboxPlugin {
uploadUrl = dropboxUrl;
return true;
} catch (Exception e) {
- LOG.Error(e);
+ Log.Error(e);
MessageBox.Show(Language.GetString("dropbox", LangKey.upload_failure) + " " + e.Message);
return false;
}
diff --git a/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs b/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs
index 090fdccbf..a484deb7b 100644
--- a/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs
+++ b/GreenshotDropboxPlugin/DropboxPluginConfiguration.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,19 +30,19 @@ namespace GreenshotDropboxPlugin {
[IniSection("Dropbox", Description = "Greenshot Dropbox Plugin configuration")]
public class DropboxPluginConfiguration : IniSection {
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
- public OutputFormat UploadFormat;
+ public OutputFormat UploadFormat { get; set; }
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
- public int UploadJpegQuality;
+ public int UploadJpegQuality { get; set; }
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send Dropbox link to clipboard.", DefaultValue = "true")]
- public bool AfterUploadLinkToClipBoard;
+ public bool AfterUploadLinkToClipBoard { get; set; }
[IniProperty("DropboxToken", Description = "The Dropbox token", Encrypted = true, ExcludeIfNull = true)]
- public string DropboxToken;
+ public string DropboxToken { get; set; }
[IniProperty("DropboxTokenSecret", Description = "The Dropbox token secret", Encrypted = true, ExcludeIfNull = true)]
- public string DropboxTokenSecret;
-
+ public string DropboxTokenSecret { get; set; }
+
///
/// A form for token
///
diff --git a/GreenshotDropboxPlugin/DropboxUtils.cs b/GreenshotDropboxPlugin/DropboxUtils.cs
index 126a41cd3..f8a180f4c 100644
--- a/GreenshotDropboxPlugin/DropboxUtils.cs
+++ b/GreenshotDropboxPlugin/DropboxUtils.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,36 +30,38 @@ namespace GreenshotDropboxPlugin {
/// Description of DropboxUtils.
///
public class DropboxUtils {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(DropboxUtils));
- private static DropboxPluginConfiguration config = IniConfig.GetIniSection();
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(DropboxUtils));
+ private static readonly DropboxPluginConfiguration DropboxConfig = IniConfig.GetIniSection();
private DropboxUtils() {
}
public static string UploadToDropbox(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string filename) {
- OAuthSession oAuth = new OAuthSession(DropBoxCredentials.CONSUMER_KEY, DropBoxCredentials.CONSUMER_SECRET);
- oAuth.BrowserSize = new Size(1080, 650);
- oAuth.CheckVerifier = false;
- oAuth.AccessTokenUrl = "https://api.dropbox.com/1/oauth/access_token";
- oAuth.AuthorizeUrl = "https://api.dropbox.com/1/oauth/authorize";
- oAuth.RequestTokenUrl = "https://api.dropbox.com/1/oauth/request_token";
- oAuth.LoginTitle = "Dropbox authorization";
- oAuth.Token = config.DropboxToken;
- oAuth.TokenSecret = config.DropboxTokenSecret;
+ var oAuth = new OAuthSession(DropBoxCredentials.CONSUMER_KEY, DropBoxCredentials.CONSUMER_SECRET)
+ {
+ BrowserSize = new Size(1080, 650),
+ CheckVerifier = false,
+ AccessTokenUrl = "https://api.dropbox.com/1/oauth/access_token",
+ AuthorizeUrl = "https://api.dropbox.com/1/oauth/authorize",
+ RequestTokenUrl = "https://api.dropbox.com/1/oauth/request_token",
+ LoginTitle = "Dropbox authorization",
+ Token = DropboxConfig.DropboxToken,
+ TokenSecret = DropboxConfig.DropboxTokenSecret
+ };
try {
SurfaceContainer imageToUpload = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
string uploadResponse = oAuth.MakeOAuthRequest(HTTPMethod.POST, "https://api-content.dropbox.com/1/files_put/sandbox/" + OAuthSession.UrlEncode3986(filename), null, null, imageToUpload);
- LOG.DebugFormat("Upload response: {0}", uploadResponse);
+ Log.DebugFormat("Upload response: {0}", uploadResponse);
} catch (Exception ex) {
- LOG.Error("Upload error: ", ex);
+ Log.Error("Upload error: ", ex);
throw;
} finally {
if (!string.IsNullOrEmpty(oAuth.Token)) {
- config.DropboxToken = oAuth.Token;
+ DropboxConfig.DropboxToken = oAuth.Token;
}
if (!string.IsNullOrEmpty(oAuth.TokenSecret)) {
- config.DropboxTokenSecret = oAuth.TokenSecret;
+ DropboxConfig.DropboxTokenSecret = oAuth.TokenSecret;
}
}
@@ -67,16 +69,16 @@ namespace GreenshotDropboxPlugin {
try {
string responseString = oAuth.MakeOAuthRequest(HTTPMethod.GET, "https://api.dropbox.com/1/shares/sandbox/" + OAuthSession.UrlEncode3986(filename), null, null, null);
if (responseString != null) {
- LOG.DebugFormat("Parsing output: {0}", responseString);
+ Log.DebugFormat("Parsing output: {0}", responseString);
IDictionary returnValues = JSONHelper.JsonDecode(responseString);
if (returnValues.ContainsKey("url")) {
return returnValues["url"] as string;
}
}
} catch (Exception ex) {
- LOG.Error("Can't parse response.", ex);
+ Log.Error("Can't parse response.", ex);
}
return null;
- }
+ }
}
}
diff --git a/GreenshotDropboxPlugin/Forms/DropboxForm.cs b/GreenshotDropboxPlugin/Forms/DropboxForm.cs
index b2c87ec61..c526d67d1 100644
--- a/GreenshotDropboxPlugin/Forms/DropboxForm.cs
+++ b/GreenshotDropboxPlugin/Forms/DropboxForm.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,7 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-using System;
+
using GreenshotPlugin.Controls;
namespace GreenshotDropboxPlugin.Forms {
diff --git a/GreenshotDropboxPlugin/Forms/SettingsForm.Designer.cs b/GreenshotDropboxPlugin/Forms/SettingsForm.Designer.cs
index 2549c2018..3e8226dc9 100644
--- a/GreenshotDropboxPlugin/Forms/SettingsForm.Designer.cs
+++ b/GreenshotDropboxPlugin/Forms/SettingsForm.Designer.cs
@@ -3,7 +3,7 @@
* Copyright (C) 2007-2011 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/GreenshotDropboxPlugin/Forms/SettingsForm.cs b/GreenshotDropboxPlugin/Forms/SettingsForm.cs
index 280ded7f1..d057b10dc 100644
--- a/GreenshotDropboxPlugin/Forms/SettingsForm.cs
+++ b/GreenshotDropboxPlugin/Forms/SettingsForm.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,20 +19,13 @@
* along with this program. If not, see .
*/
-using System;
-using System.Windows.Forms;
using GreenshotDropboxPlugin.Forms;
-using GreenshotPlugin.Core;
-using Greenshot.IniFile;
namespace GreenshotDropboxPlugin {
///
/// Description of PasswordRequestForm.
///
public partial class SettingsForm : DropboxForm {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(SettingsForm));
- private static DropboxPluginConfiguration config = IniConfig.GetIniSection();
-
public SettingsForm() {
//
// The InitializeComponent() call is required for Windows Forms designer support.
diff --git a/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj b/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj
index 58f8f231e..7721478a4 100644
--- a/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj
+++ b/GreenshotDropboxPlugin/GreenshotDropboxPlugin.csproj
@@ -67,11 +67,11 @@
rename "$(ProjectDir)DropBoxCredentials.cs" "DropBoxCredentials.private.cs"
rename "$(ProjectDir)DropBoxCredentials.orig.cs" "DropBoxCredentials.cs"
)
-mkdir "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)"
-copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
-copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\"
-mkdir "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
-copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
if exist "$(ProjectDir)DropBoxCredentials.private.cs" (
diff --git a/GreenshotDropboxPlugin/LanguageKeys.cs b/GreenshotDropboxPlugin/LanguageKeys.cs
index daa6fb14c..0cc9c5204 100644
--- a/GreenshotDropboxPlugin/LanguageKeys.cs
+++ b/GreenshotDropboxPlugin/LanguageKeys.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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/GreenshotDropboxPlugin/Properties/AssemblyInfo.cs b/GreenshotDropboxPlugin/Properties/AssemblyInfo.cs
index 67d20ede5..44f4a108a 100644
--- a/GreenshotDropboxPlugin/Properties/AssemblyInfo.cs
+++ b/GreenshotDropboxPlugin/Properties/AssemblyInfo.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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.Plugin;
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/GreenshotExternalCommandPlugin/ExternalCommandConfiguration.cs b/GreenshotExternalCommandPlugin/ExternalCommandConfiguration.cs
index f83bc9370..d6aae0d1f 100644
--- a/GreenshotExternalCommandPlugin/ExternalCommandConfiguration.cs
+++ b/GreenshotExternalCommandPlugin/ExternalCommandConfiguration.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,49 +31,106 @@ namespace ExternalCommand {
[IniSection("ExternalCommand", Description="Greenshot ExternalCommand Plugin configuration")]
public class ExternalCommandConfiguration : IniSection {
[IniProperty("Commands", Description="The commands that are available.")]
- public List commands;
+ public List Commands { get; set; }
[IniProperty("RedirectStandardError", Description = "Redirect the standard error of all external commands, used to output as warning to the greenshot.log.", DefaultValue = "true")]
- public bool RedirectStandardError;
+ public bool RedirectStandardError { get; set; }
[IniProperty("RedirectStandardOutput", Description = "Redirect the standard output of all external commands, used for different other functions (more below).", DefaultValue = "true")]
- public bool RedirectStandardOutput;
+ public bool RedirectStandardOutput { get; set; }
[IniProperty("ShowStandardOutputInLog", Description = "Depends on 'RedirectStandardOutput': Show standard output of all external commands to the Greenshot log, this can be usefull for debugging.", DefaultValue = "false")]
- public bool ShowStandardOutputInLog;
+ public bool ShowStandardOutputInLog { get; set; }
[IniProperty("ParseForUri", Description = "Depends on 'RedirectStandardOutput': Parse the output and take the first found URI, if a URI is found than clicking on the notify bubble goes there.", DefaultValue = "true")]
- public bool ParseOutputForUri;
+ public bool ParseOutputForUri { get; set; }
[IniProperty("OutputToClipboard", Description = "Depends on 'RedirectStandardOutput': Place the standard output on the clipboard.", DefaultValue = "false")]
- public bool OutputToClipboard;
+ public bool OutputToClipboard { get; set; }
[IniProperty("UriToClipboard", Description = "Depends on 'RedirectStandardOutput' & 'ParseForUri': If an URI is found in the standard input, place it on the clipboard. (This overwrites the output from OutputToClipboard setting.)", DefaultValue = "true")]
- public bool UriToClipboard;
+ public bool UriToClipboard { get; set; }
[IniProperty("Commandline", Description="The commandline for the output command.")]
- public Dictionary commandlines;
+ public Dictionary Commandline { get; set; }
[IniProperty("Argument", Description="The arguments for the output command.")]
- public Dictionary arguments;
+ public Dictionary Argument { get; set; }
[IniProperty("RunInbackground", Description = "Should the command be started in the background.")]
- public Dictionary runInbackground;
+ public Dictionary RunInbackground { get; set; }
- private const string MSPAINT = "MS Paint";
- private static string paintPath;
- private static bool hasPaint = false;
+ [IniProperty("DeletedBuildInCommands", Description = "If a build in command was deleted manually, it should not be recreated.")]
+ public List DeletedBuildInCommands { get; set; }
- private const string PAINTDOTNET = "Paint.NET";
- private static string paintDotNetPath;
- private static bool hasPaintDotNet = false;
+ private const string MsPaint = "MS Paint";
+ private static readonly string PaintPath;
+ private static readonly bool HasPaint;
+
+ private const string PaintDotNet = "Paint.NET";
+ private static readonly string PaintDotNetPath;
+ private static readonly bool HasPaintDotNet;
static ExternalCommandConfiguration() {
try {
- paintPath = PluginUtils.GetExePath("pbrush.exe");
- hasPaint = !string.IsNullOrEmpty(paintPath) && File.Exists(paintPath);
- paintDotNetPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Paint.NET\PaintDotNet.exe");
- hasPaintDotNet = !string.IsNullOrEmpty(paintDotNetPath) && File.Exists(paintDotNetPath);
+ PaintPath = PluginUtils.GetExePath("pbrush.exe");
+ HasPaint = !string.IsNullOrEmpty(PaintPath) && File.Exists(PaintPath);
} catch {
+ // Ignore
+ }
+ try
+ {
+ PaintDotNetPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Paint.NET\PaintDotNet.exe");
+ HasPaintDotNet = !string.IsNullOrEmpty(PaintDotNetPath) && File.Exists(PaintDotNetPath);
+ }
+ catch
+ {
+ // Ignore
+ }
+ }
+
+ ///
+ /// Delete the configuration for the specified command
+ ///
+ /// string with command
+ public void Delete(string command)
+ {
+ if (string.IsNullOrEmpty(command))
+ {
+ return;
+ }
+ Commands.Remove(command);
+ Commandline.Remove(command);
+ Argument.Remove(command);
+ RunInbackground.Remove(command);
+ if (MsPaint.Equals(command) || PaintDotNet.Equals(command))
+ {
+ if (!DeletedBuildInCommands.Contains(command))
+ {
+ DeletedBuildInCommands.Add(command);
+ }
+ }
+ }
+
+ public override void AfterLoad()
+ {
+ base.AfterLoad();
+
+ // Check if we need to add MsPaint
+ if (HasPaint && !Commands.Contains(MsPaint) && !DeletedBuildInCommands.Contains(MsPaint))
+ {
+ Commands.Add(MsPaint);
+ Commandline.Add(MsPaint, PaintPath);
+ Argument.Add(MsPaint, "\"{0}\"");
+ RunInbackground.Add(MsPaint, true);
+ }
+
+ // Check if we need to add Paint.NET
+ if (HasPaintDotNet && !Commands.Contains(PaintDotNet) && !DeletedBuildInCommands.Contains(PaintDotNet))
+ {
+ Commands.Add(PaintDotNet);
+ Commandline.Add(PaintDotNet, PaintDotNetPath);
+ Argument.Add(PaintDotNet, "\"{0}\"");
+ RunInbackground.Add(PaintDotNet, true);
}
}
@@ -84,42 +141,16 @@ namespace ExternalCommand {
/// object with the default value for the supplied property
public override object GetDefault(string property) {
switch(property) {
- case "Commands":
- List commandDefaults = new List();
- if (hasPaintDotNet) {
- commandDefaults.Add(PAINTDOTNET);
- }
- if (hasPaint) {
- commandDefaults.Add(MSPAINT);
- }
- return commandDefaults;
- case "Commandline":
- Dictionary commandlineDefaults = new Dictionary();
- if (hasPaintDotNet) {
- commandlineDefaults.Add(PAINTDOTNET, paintDotNetPath);
- }
- if (hasPaint) {
- commandlineDefaults.Add(MSPAINT, paintPath);
- }
- return commandlineDefaults;
- case "Argument":
- Dictionary argumentDefaults = new Dictionary();
- if (hasPaintDotNet) {
- argumentDefaults.Add(PAINTDOTNET, "\"{0}\"");
- }
- if (hasPaint) {
- argumentDefaults.Add(MSPAINT, "\"{0}\"");
- }
- return argumentDefaults;
- case "RunInbackground":
- Dictionary runInBackground = new Dictionary();
- if (hasPaintDotNet) {
- runInBackground.Add(PAINTDOTNET, true);
- }
- if (hasPaint) {
- runInBackground.Add(MSPAINT, true);
- }
- return runInBackground;
+ case nameof(DeletedBuildInCommands):
+ return new List();
+ case nameof(Commands):
+ return new List();
+ case nameof(Commandline):
+ return new Dictionary();
+ case nameof(Argument):
+ return new Dictionary();
+ case nameof(RunInbackground):
+ return new Dictionary();
}
return null;
}
diff --git a/GreenshotExternalCommandPlugin/ExternalCommandDestination.cs b/GreenshotExternalCommandPlugin/ExternalCommandDestination.cs
index ee13f6eee..654c2051a 100644
--- a/GreenshotExternalCommandPlugin/ExternalCommandDestination.cs
+++ b/GreenshotExternalCommandPlugin/ExternalCommandDestination.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,24 +34,24 @@ namespace ExternalCommand {
/// Description of OCRDestination.
///
public class ExternalCommandDestination : AbstractDestination {
- private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ExternalCommandDestination));
- private static Regex URI_REGEXP = new Regex(@"((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)");
- private static ExternalCommandConfiguration config = IniConfig.GetIniSection();
- private string presetCommand;
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ExternalCommandDestination));
+ private static readonly Regex URI_REGEXP = new Regex(@"((([A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=\+\$,\w]+@)?[A-Za-z0-9\.\-]+|(?:www\.|[\-;:&=\+\$,\w]+@)[A-Za-z0-9\.\-]+)((?:\/[\+~%\/\.\w\-_]*)?\??(?:[\-\+=&;%@\.\w_]*)#?(?:[\.\!\/\\\w]*))?)");
+ private static readonly ExternalCommandConfiguration config = IniConfig.GetIniSection();
+ private readonly string _presetCommand;
public ExternalCommandDestination(string commando) {
- this.presetCommand = commando;
+ _presetCommand = commando;
}
public override string Designation {
get {
- return "External " + presetCommand.Replace(',','_');
+ return "External " + _presetCommand.Replace(',','_');
}
}
public override string Description {
get {
- return presetCommand;
+ return _presetCommand;
}
}
@@ -61,20 +61,20 @@ namespace ExternalCommand {
public override Image DisplayIcon {
get {
- return IconCache.IconForCommand(presetCommand);
+ return IconCache.IconForCommand(_presetCommand);
}
}
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
- ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description);
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings();
- if (presetCommand != null) {
- if (!config.runInbackground.ContainsKey(presetCommand)) {
- config.runInbackground.Add(presetCommand, true);
+ if (_presetCommand != null) {
+ if (!config.RunInbackground.ContainsKey(_presetCommand)) {
+ config.RunInbackground.Add(_presetCommand, true);
}
- bool runInBackground = config.runInbackground[presetCommand];
+ bool runInBackground = config.RunInbackground[_presetCommand];
string fullPath = captureDetails.Filename;
if (fullPath == null) {
fullPath = ImageOutput.SaveNamedTmpFile(surface, captureDetails, outputSettings);
@@ -83,17 +83,20 @@ namespace ExternalCommand {
string output;
string error;
if (runInBackground) {
- Thread commandThread = new Thread(delegate() {
- CallExternalCommand(exportInformation, presetCommand, fullPath, out output, out error);
+ Thread commandThread = new Thread(delegate()
+ {
+ CallExternalCommand(exportInformation, fullPath, out output, out error);
ProcessExport(exportInformation, surface);
- });
- commandThread.Name = "Running " + presetCommand;
- commandThread.IsBackground = true;
+ })
+ {
+ Name = "Running " + _presetCommand,
+ IsBackground = true
+ };
commandThread.SetApartmentState(ApartmentState.STA);
commandThread.Start();
exportInformation.ExportMade = true;
} else {
- CallExternalCommand(exportInformation, presetCommand, fullPath, out output, out error);
+ CallExternalCommand(exportInformation, fullPath, out output, out error);
ProcessExport(exportInformation, surface);
}
}
@@ -105,15 +108,14 @@ namespace ExternalCommand {
/// Call the external command, parse for URI, place to clipboard and set the export information
///
///
- ///
///
///
///
- private void CallExternalCommand(ExportInformation exportInformation, string commando, string fullPath, out string output, out string error) {
+ private void CallExternalCommand(ExportInformation exportInformation, string fullPath, out string output, out string error) {
output = null;
error = null;
try {
- if (CallExternalCommand(presetCommand, fullPath, out output, out error) == 0) {
+ if (CallExternalCommand(_presetCommand, fullPath, out output, out error) == 0) {
exportInformation.ExportMade = true;
if (!string.IsNullOrEmpty(output)) {
MatchCollection uriMatches = URI_REGEXP.Matches(output);
@@ -121,7 +123,7 @@ namespace ExternalCommand {
if (config.OutputToClipboard) {
ClipboardHelper.SetClipboardData(output);
}
- if (uriMatches != null && uriMatches.Count > 0) {
+ if (uriMatches.Count > 0) {
exportInformation.Uri = uriMatches[0].Groups[1].Value;
LOG.InfoFormat("Got URI : {0} ", exportInformation.Uri);
if (config.UriToClipboard) {
@@ -137,7 +139,7 @@ namespace ExternalCommand {
} catch (Exception ex) {
exportInformation.ExportMade = false;
exportInformation.ErrorMessage = ex.Message;
- LOG.WarnFormat("Error calling external command: {0} ", exportInformation.ErrorMessage);
+ LOG.WarnFormat("Error calling external command: {0} ", exportInformation.ErrorMessage);
}
}
@@ -156,13 +158,13 @@ namespace ExternalCommand {
try {
return CallExternalCommand(commando, fullPath, "runas", out output, out error);
} catch {
- w32ex.Data.Add("commandline", config.commandlines[presetCommand]);
- w32ex.Data.Add("arguments", config.arguments[presetCommand]);
+ w32ex.Data.Add("commandline", config.Commandline[_presetCommand]);
+ w32ex.Data.Add("arguments", config.Argument[_presetCommand]);
throw;
}
} catch (Exception ex) {
- ex.Data.Add("commandline", config.commandlines[presetCommand]);
- ex.Data.Add("arguments", config.arguments[presetCommand]);
+ ex.Data.Add("commandline", config.Commandline[_presetCommand]);
+ ex.Data.Add("arguments", config.Argument[_presetCommand]);
throw;
}
}
@@ -177,13 +179,21 @@ namespace ExternalCommand {
///
///
private int CallExternalCommand(string commando, string fullPath, string verb, out string output, out string error) {
- string commandline = config.commandlines[commando];
- string arguments = config.arguments[commando];
+ string commandline = config.Commandline[commando];
+ string arguments = config.Argument[commando];
output = null;
error = null;
if (!string.IsNullOrEmpty(commandline)) {
- using (Process process = new Process()) {
- process.StartInfo.FileName = commandline;
+ using (Process process = new Process())
+ {
+ // Fix variables
+ commandline = FilenameHelper.FillVariables(commandline, true);
+ commandline = FilenameHelper.FillCmdVariables(commandline, true);
+
+ arguments = FilenameHelper.FillVariables(arguments, false);
+ arguments = FilenameHelper.FillCmdVariables(arguments, false);
+
+ process.StartInfo.FileName = FilenameHelper.FillCmdVariables(commandline, true);
process.StartInfo.Arguments = FormatArguments(arguments, fullPath);
process.StartInfo.UseShellExecute = false;
if (config.RedirectStandardOutput) {
@@ -200,13 +210,13 @@ namespace ExternalCommand {
process.WaitForExit();
if (config.RedirectStandardOutput) {
output = process.StandardOutput.ReadToEnd();
- if (config.ShowStandardOutputInLog && output != null && output.Trim().Length > 0) {
+ if (config.ShowStandardOutputInLog && output.Trim().Length > 0) {
LOG.InfoFormat("Output:\n{0}", output);
}
}
if (config.RedirectStandardError) {
error = process.StandardError.ReadToEnd();
- if (error != null && error.Trim().Length > 0) {
+ if (error.Trim().Length > 0) {
LOG.WarnFormat("Error:\n{0}", error);
}
}
@@ -217,9 +227,9 @@ namespace ExternalCommand {
return -1;
}
- public static string FormatArguments(string arguments, string fullpath)
- {
- return String.Format(arguments, fullpath);
- }
- }
+ public static string FormatArguments(string arguments, string fullpath)
+ {
+ return string.Format(arguments, fullpath);
+ }
+ }
}
diff --git a/GreenshotExternalCommandPlugin/ExternalCommandForm.cs b/GreenshotExternalCommandPlugin/ExternalCommandForm.cs
index 29441232a..b7971baaa 100644
--- a/GreenshotExternalCommandPlugin/ExternalCommandForm.cs
+++ b/GreenshotExternalCommandPlugin/ExternalCommandForm.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/GreenshotExternalCommandPlugin/ExternalCommandPlugin.cs b/GreenshotExternalCommandPlugin/ExternalCommandPlugin.cs
index 9531b0066..670b17106 100644
--- a/GreenshotExternalCommandPlugin/ExternalCommandPlugin.cs
+++ b/GreenshotExternalCommandPlugin/ExternalCommandPlugin.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,12 +33,12 @@ namespace ExternalCommand {
/// An Plugin to run commands after an image was written
///
public class ExternalCommandPlugin : IGreenshotPlugin {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ExternalCommandPlugin));
- private static CoreConfiguration coreConfig = IniConfig.GetIniSection();
- private static ExternalCommandConfiguration config = IniConfig.GetIniSection();
- private IGreenshotHost host;
- private PluginAttribute myAttributes;
- private ToolStripMenuItem itemPlugInRoot;
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ExternalCommandPlugin));
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection();
+ private IGreenshotHost _host;
+ private PluginAttribute _myAttributes;
+ private ToolStripMenuItem _itemPlugInRoot;
public void Dispose() {
Dispose(true);
@@ -47,18 +47,15 @@ namespace ExternalCommand {
protected virtual void Dispose(bool disposing) {
if (disposing) {
- if (itemPlugInRoot != null) {
- itemPlugInRoot.Dispose();
- itemPlugInRoot = null;
+ if (_itemPlugInRoot != null) {
+ _itemPlugInRoot.Dispose();
+ _itemPlugInRoot = null;
}
}
}
- public ExternalCommandPlugin() {
- }
-
public IEnumerable Destinations() {
- foreach(string command in config.commands) {
+ foreach(string command in ExternalCommandConfig.Commands) {
yield return new ExternalCommandDestination(command);
}
}
@@ -72,23 +69,26 @@ namespace ExternalCommand {
///
///
/// false if the command is not correctly configured
- private bool isCommandValid(string command) {
- if (!config.runInbackground.ContainsKey(command)) {
- LOG.WarnFormat("Found missing runInbackground for {0}", command);
+ private bool IsCommandValid(string command) {
+ if (!ExternalCommandConfig.RunInbackground.ContainsKey(command)) {
+ Log.WarnFormat("Found missing runInbackground for {0}", command);
// Fix it
- config.runInbackground.Add(command, true);
+ ExternalCommandConfig.RunInbackground.Add(command, true);
}
- if (!config.arguments.ContainsKey(command)) {
- LOG.WarnFormat("Found missing argument for {0}", command);
+ if (!ExternalCommandConfig.Argument.ContainsKey(command)) {
+ Log.WarnFormat("Found missing argument for {0}", command);
// Fix it
- config.arguments.Add(command, "{0}");
+ ExternalCommandConfig.Argument.Add(command, "{0}");
}
- if (!config.commandlines.ContainsKey(command)) {
- LOG.WarnFormat("Found missing commandline for {0}", command);
+ if (!ExternalCommandConfig.Commandline.ContainsKey(command)) {
+ Log.WarnFormat("Found missing commandline for {0}", command);
return false;
}
- if (!File.Exists(config.commandlines[command])) {
- LOG.WarnFormat("Found 'invalid' commandline {0} for command {1}", config.commandlines[command], command);
+ string commandline = FilenameHelper.FillVariables(ExternalCommandConfig.Commandline[command], true);
+ commandline = FilenameHelper.FillCmdVariables(commandline, true);
+
+ if (!File.Exists(commandline)) {
+ Log.WarnFormat("Found 'invalid' commandline {0} for command {1}", ExternalCommandConfig.Commandline[command], command);
return false;
}
return true;
@@ -96,41 +96,36 @@ namespace ExternalCommand {
///
/// Implementation of the IGreenshotPlugin.Initialize
///
- /// Use the IGreenshotPluginHost interface to register events
- /// Use the ICaptureHost interface to register in the MainContextMenu
- /// My own attributes
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
- LOG.DebugFormat("Initialize called of {0}", myAttributes.Name);
+ Log.DebugFormat("Initialize called of {0}", myAttributes.Name);
List commandsToDelete = new List();
// Check configuration
- foreach(string command in config.commands) {
- if (!isCommandValid(command)) {
+ foreach(string command in ExternalCommandConfig.Commands) {
+ if (!IsCommandValid(command)) {
commandsToDelete.Add(command);
}
}
// cleanup
foreach (string command in commandsToDelete) {
- config.runInbackground.Remove(command);
- config.commandlines.Remove(command);
- config.arguments.Remove(command);
- config.commands.Remove(command);
+ ExternalCommandConfig.Delete(command);
}
- this.host = pluginHost;
- this.myAttributes = myAttributes;
+ _host = pluginHost;
+ _myAttributes = myAttributes;
- itemPlugInRoot = new ToolStripMenuItem();
- itemPlugInRoot.Tag = host;
+ _itemPlugInRoot = new ToolStripMenuItem {Tag = _host};
OnIconSizeChanged(this, new PropertyChangedEventArgs("IconSize"));
OnLanguageChanged(this, null);
- itemPlugInRoot.Click += new System.EventHandler(ConfigMenuClick);
+ _itemPlugInRoot.Click += ConfigMenuClick;
- PluginUtils.AddToContextMenu(host, itemPlugInRoot);
+ PluginUtils.AddToContextMenu(_host, _itemPlugInRoot);
Language.LanguageChanged += OnLanguageChanged;
- coreConfig.PropertyChanged += OnIconSizeChanged;
+ CoreConfig.PropertyChanged += OnIconSizeChanged;
return true;
}
@@ -144,22 +139,22 @@ namespace ExternalCommand {
try {
string exePath = PluginUtils.GetExePath("cmd.exe");
if (exePath != null && File.Exists(exePath)) {
- itemPlugInRoot.Image = PluginUtils.GetCachedExeIcon(exePath, 0);
+ _itemPlugInRoot.Image = PluginUtils.GetCachedExeIcon(exePath, 0);
}
} catch (Exception ex) {
- LOG.Warn("Couldn't get the cmd.exe image", ex);
+ Log.Warn("Couldn't get the cmd.exe image", ex);
}
}
}
private void OnLanguageChanged(object sender, EventArgs e) {
- if (itemPlugInRoot != null) {
- itemPlugInRoot.Text = Language.GetString("externalcommand", "contextmenu_configure");
+ if (_itemPlugInRoot != null) {
+ _itemPlugInRoot.Text = Language.GetString("externalcommand", "contextmenu_configure");
}
}
public virtual void Shutdown() {
- LOG.Debug("Shutdown of " + myAttributes.Name);
+ Log.Debug("Shutdown of " + _myAttributes.Name);
}
private void ConfigMenuClick(object sender, EventArgs eventArgs) {
@@ -170,7 +165,7 @@ namespace ExternalCommand {
/// Implementation of the IPlugin.Configure
///
public virtual void Configure() {
- LOG.Debug("Configure called");
+ Log.Debug("Configure called");
new SettingsForm().ShowDialog();
}
}
diff --git a/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj b/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj
index 2f534d1b4..8be1f0a81 100644
--- a/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj
+++ b/GreenshotExternalCommandPlugin/GreenshotExternalCommandPlugin.csproj
@@ -63,11 +63,11 @@
- mkdir "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)"
-copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
-copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)"
-mkdir "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
-copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+ mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"False
diff --git a/GreenshotExternalCommandPlugin/IconCache.cs b/GreenshotExternalCommandPlugin/IconCache.cs
index c3e3f16bd..fdff5815e 100644
--- a/GreenshotExternalCommandPlugin/IconCache.cs
+++ b/GreenshotExternalCommandPlugin/IconCache.cs
@@ -1,5 +1,25 @@
-using System;
-using System.Collections.Generic;
+/*
+ * 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 System;
using System.Drawing;
using System.IO;
using Greenshot.IniFile;
@@ -7,17 +27,17 @@ using GreenshotPlugin.Core;
namespace ExternalCommand {
public static class IconCache {
- private static ExternalCommandConfiguration config = IniConfig.GetIniSection();
- private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IconCache));
+ private static readonly ExternalCommandConfiguration config = IniConfig.GetIniSection();
+ private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(IconCache));
public static Image IconForCommand(string commandName) {
Image icon = null;
if (commandName != null) {
- if (config.commandlines.ContainsKey(commandName) && File.Exists(config.commandlines[commandName])) {
+ if (config.Commandline.ContainsKey(commandName) && File.Exists(config.Commandline[commandName])) {
try {
- icon = PluginUtils.GetCachedExeIcon(config.commandlines[commandName], 0);
+ icon = PluginUtils.GetCachedExeIcon(config.Commandline[commandName], 0);
} catch (Exception ex) {
- LOG.Warn("Problem loading icon for " + config.commandlines[commandName], ex);
+ LOG.Warn("Problem loading icon for " + config.Commandline[commandName], ex);
}
}
}
diff --git a/GreenshotExternalCommandPlugin/Properties/AssemblyInfo.cs b/GreenshotExternalCommandPlugin/Properties/AssemblyInfo.cs
index 812fd723c..61259677a 100644
--- a/GreenshotExternalCommandPlugin/Properties/AssemblyInfo.cs
+++ b/GreenshotExternalCommandPlugin/Properties/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
@@ -22,7 +22,6 @@
using Greenshot.Plugin;
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
@@ -32,7 +31,7 @@ using System.Security;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Greenshot")]
[assembly: AssemblyProduct("External command Plugin")]
-[assembly: AssemblyCopyright("Copyright (C) 2007-2015")]
+[assembly: AssemblyCopyright("Copyright (C) 2007-2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The PluginAttribute describes the "entryType" and if the plugin is configurable
diff --git a/GreenshotExternalCommandPlugin/SettingsForm.Designer.cs b/GreenshotExternalCommandPlugin/SettingsForm.Designer.cs
index c0a9d3043..7119086ff 100644
--- a/GreenshotExternalCommandPlugin/SettingsForm.Designer.cs
+++ b/GreenshotExternalCommandPlugin/SettingsForm.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/GreenshotExternalCommandPlugin/SettingsForm.cs b/GreenshotExternalCommandPlugin/SettingsForm.cs
index 247e38b59..e5721749b 100644
--- a/GreenshotExternalCommandPlugin/SettingsForm.cs
+++ b/GreenshotExternalCommandPlugin/SettingsForm.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,8 +29,7 @@ namespace ExternalCommand {
/// Description of SettingsForm.
///
public partial class SettingsForm : ExternalCommandForm {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(SettingsForm));
- private static ExternalCommandConfiguration config = IniConfig.GetIniSection();
+ private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection();
public SettingsForm() {
//
@@ -42,36 +41,35 @@ namespace ExternalCommand {
UpdateView();
}
- void ButtonOkClick(object sender, EventArgs e) {
+ private void ButtonOkClick(object sender, EventArgs e) {
IniConfig.Save();
}
- void ButtonAddClick(object sender, EventArgs e) {
- SettingsFormDetail form = new SettingsFormDetail(null);
+ private void ButtonAddClick(object sender, EventArgs e) {
+ var form = new SettingsFormDetail(null);
form.ShowDialog();
UpdateView();
}
- void ButtonDeleteClick(object sender, EventArgs e) {
+ private void ButtonDeleteClick(object sender, EventArgs e) {
foreach(ListViewItem item in listView1.SelectedItems) {
string commando = item.Tag as string;
- config.commands.Remove(commando);
- config.commandlines.Remove(commando);
- config.arguments.Remove(commando);
+
+ ExternalCommandConfig.Delete(commando);
}
UpdateView();
}
- void UpdateView() {
+ private void UpdateView() {
listView1.Items.Clear();
- if(config.commands != null) {
+ if(ExternalCommandConfig.Commands != null) {
listView1.ListViewItemSorter = new ListviewComparer();
ImageList imageList = new ImageList();
listView1.SmallImageList = imageList;
int imageNr = 0;
- foreach(string commando in config.commands) {
- ListViewItem item = null;
+ foreach(string commando in ExternalCommandConfig.Commands) {
+ ListViewItem item;
Image iconForExe = IconCache.IconForCommand(commando);
if(iconForExe != null) {
imageList.Images.Add(iconForExe);
@@ -87,15 +85,15 @@ namespace ExternalCommand {
button_edit.Enabled = listView1.SelectedItems.Count > 0;
}
- void ListView1ItemSelectionChanged(object sender, EventArgs e) {
+ private void ListView1ItemSelectionChanged(object sender, EventArgs e) {
button_edit.Enabled = listView1.SelectedItems.Count > 0;
}
- void ButtonEditClick(object sender, EventArgs e) {
+ private void ButtonEditClick(object sender, EventArgs e) {
ListView1DoubleClick(sender, e);
}
- void ListView1DoubleClick(object sender, EventArgs e) {
+ private void ListView1DoubleClick(object sender, EventArgs e) {
// Safety check for bug #1484
bool selectionActive = listView1.SelectedItems.Count > 0;
if(!selectionActive) {
@@ -104,7 +102,7 @@ namespace ExternalCommand {
}
string commando = listView1.SelectedItems[0].Tag as string;
- SettingsFormDetail form = new SettingsFormDetail(commando);
+ var form = new SettingsFormDetail(commando);
form.ShowDialog();
UpdateView();
@@ -120,12 +118,9 @@ namespace ExternalCommand {
return (0);
}
- ListViewItem l1 = (ListViewItem)x;
- ListViewItem l2 = (ListViewItem)y;
- if(l2 == null) {
- return 1;
- }
- return l1.Text.CompareTo(l2.Text);
+ var l1 = (ListViewItem)x;
+ var l2 = (ListViewItem)y;
+ return string.Compare(l1.Text, l2.Text, StringComparison.Ordinal);
}
}
}
diff --git a/GreenshotExternalCommandPlugin/SettingsFormDetail.Designer.cs b/GreenshotExternalCommandPlugin/SettingsFormDetail.Designer.cs
index 96efa4063..2a34a4cf0 100644
--- a/GreenshotExternalCommandPlugin/SettingsFormDetail.Designer.cs
+++ b/GreenshotExternalCommandPlugin/SettingsFormDetail.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/GreenshotExternalCommandPlugin/SettingsFormDetail.cs b/GreenshotExternalCommandPlugin/SettingsFormDetail.cs
index ae9d4b030..00a306a6d 100644
--- a/GreenshotExternalCommandPlugin/SettingsFormDetail.cs
+++ b/GreenshotExternalCommandPlugin/SettingsFormDetail.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,86 +24,95 @@ using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
+using GreenshotPlugin.Core;
namespace ExternalCommand {
///
/// Description of SettingsFormDetail.
///
public partial class SettingsFormDetail : ExternalCommandForm {
- private string commando;
- private int commandIndex;
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(SettingsFormDetail));
+ private static readonly ExternalCommandConfiguration ExternalCommandConfig = IniConfig.GetIniSection();
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(SettingsFormDetail));
- private static ExternalCommandConfiguration config = IniConfig.GetIniSection();
+ private readonly string _commando;
+ private readonly int _commandIndex;
public SettingsFormDetail(string commando) {
InitializeComponent();
AcceptButton = buttonOk;
CancelButton = buttonCancel;
- this.commando = commando;
+ _commando = commando;
if(commando != null) {
textBox_name.Text = commando;
- textBox_commandline.Text = config.commandlines[commando];
- textBox_arguments.Text = config.arguments[commando];
- commandIndex = config.commands.FindIndex(delegate(string s) { return s == commando; });
+ textBox_commandline.Text = ExternalCommandConfig.Commandline[commando];
+ textBox_arguments.Text = ExternalCommandConfig.Argument[commando];
+ _commandIndex = ExternalCommandConfig.Commands.FindIndex(s => s == commando);
} else {
textBox_arguments.Text = "\"{0}\"";
}
- OKButtonState();
+ OkButtonState();
}
- void ButtonOkClick(object sender, EventArgs e) {
+ private void ButtonOkClick(object sender, EventArgs e) {
string commandName = textBox_name.Text;
string commandLine = textBox_commandline.Text;
string arguments = textBox_arguments.Text;
- if(commando != null) {
- config.commands[commandIndex] = commandName;
- config.commandlines.Remove(commando);
- config.commandlines.Add(commandName, commandLine);
- config.arguments.Remove(commando);
- config.arguments.Add(commandName, arguments);
+ if(_commando != null) {
+ ExternalCommandConfig.Commands[_commandIndex] = commandName;
+ ExternalCommandConfig.Commandline.Remove(_commando);
+ ExternalCommandConfig.Commandline.Add(commandName, commandLine);
+ ExternalCommandConfig.Argument.Remove(_commando);
+ ExternalCommandConfig.Argument.Add(commandName, arguments);
} else {
- config.commands.Add(commandName);
- config.commandlines.Add(commandName, commandLine);
- config.arguments.Add(commandName, arguments);
+ ExternalCommandConfig.Commands.Add(commandName);
+ ExternalCommandConfig.Commandline.Add(commandName, commandLine);
+ ExternalCommandConfig.Argument.Add(commandName, arguments);
}
}
- void Button3Click(object sender, EventArgs e) {
- OpenFileDialog openFileDialog = new OpenFileDialog();
- openFileDialog.Filter = "Executables (*.exe, *.bat, *.com)|*.exe; *.bat; *.com|All files (*)|*";
- openFileDialog.FilterIndex = 1;
- openFileDialog.CheckFileExists = true;
- openFileDialog.Multiselect = false;
+ private void Button3Click(object sender, EventArgs e) {
+ var openFileDialog = new OpenFileDialog
+ {
+ Filter = "Executables (*.exe, *.bat, *.com)|*.exe; *.bat; *.com|All files (*)|*",
+ FilterIndex = 1,
+ CheckFileExists = true,
+ Multiselect = false
+ };
string initialPath = null;
- try {
+ try
+ {
initialPath = Path.GetDirectoryName(textBox_commandline.Text);
- } catch { }
+ }
+ catch (Exception ex)
+ {
+ Log.WarnFormat("Can't get the initial path via {0}", textBox_commandline.Text);
+ Log.Warn("Exception: ", ex);
+ }
if(initialPath != null && Directory.Exists(initialPath)) {
openFileDialog.InitialDirectory = initialPath;
} else {
initialPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
openFileDialog.InitialDirectory = initialPath;
}
- LOG.DebugFormat("Starting OpenFileDialog at {0}", initialPath);
+ Log.DebugFormat("Starting OpenFileDialog at {0}", initialPath);
if(openFileDialog.ShowDialog() == DialogResult.OK) {
textBox_commandline.Text = openFileDialog.FileName;
}
}
- private void OKButtonState() {
+ private void OkButtonState() {
// Assume OK
buttonOk.Enabled = true;
textBox_name.BackColor = Color.White;
textBox_commandline.BackColor = Color.White;
- textBox_arguments.BackColor = Color.White;
+ textBox_arguments.BackColor = Color.White;
// Is there a text in the name field
if(string.IsNullOrEmpty(textBox_name.Text)) {
buttonOk.Enabled = false;
}
// Check if commandname is unique
- if(commando == null && !string.IsNullOrEmpty(textBox_name.Text) && config.commands.Contains(textBox_name.Text)) {
+ if(_commando == null && !string.IsNullOrEmpty(textBox_name.Text) && ExternalCommandConfig.Commands.Contains(textBox_name.Text)) {
buttonOk.Enabled = false;
textBox_name.BackColor = Color.Red;
}
@@ -111,35 +120,47 @@ namespace ExternalCommand {
if(string.IsNullOrEmpty(textBox_commandline.Text)) {
buttonOk.Enabled = false;
}
- // Is the command available?
- if(!string.IsNullOrEmpty(textBox_commandline.Text) && !File.Exists(textBox_commandline.Text)) {
- buttonOk.Enabled = false;
- textBox_commandline.BackColor = Color.Red;
+
+ if (!string.IsNullOrEmpty(textBox_commandline.Text))
+ {
+ // Added this to be more flexible, using the Greenshot var format
+ string cmdPath = FilenameHelper.FillVariables(textBox_commandline.Text, true);
+ // And also replace the "DOS" Variables
+ cmdPath = FilenameHelper.FillCmdVariables(cmdPath, true);
+ // Is the command available?
+ if (!File.Exists(cmdPath))
+ {
+ buttonOk.Enabled = false;
+ textBox_commandline.BackColor = Color.Red;
+ }
}
- // Are the arguments in a valid format?
- try
- {
- ExternalCommandDestination.FormatArguments(textBox_arguments.Text, string.Empty);
- }
- catch
- {
- buttonOk.Enabled = false;
- textBox_arguments.BackColor = Color.Red;
- }
+ // Are the arguments in a valid format?
+ try
+ {
+ string arguments = FilenameHelper.FillVariables(textBox_arguments.Text, false);
+ arguments = FilenameHelper.FillCmdVariables(arguments, false);
+
+ ExternalCommandDestination.FormatArguments(arguments, string.Empty);
+ }
+ catch
+ {
+ buttonOk.Enabled = false;
+ textBox_arguments.BackColor = Color.Red;
+ }
}
private void textBox_name_TextChanged(object sender, EventArgs e) {
- OKButtonState();
+ OkButtonState();
}
private void textBox_commandline_TextChanged(object sender, EventArgs e) {
- OKButtonState();
+ OkButtonState();
}
- private void textBox_arguments_TextChanged(object sender, EventArgs e)
- {
- OKButtonState();
- }
+ private void textBox_arguments_TextChanged(object sender, EventArgs e)
+ {
+ OkButtonState();
+ }
}
}
diff --git a/GreenshotFlickrPlugin/FlickrConfiguration.cs b/GreenshotFlickrPlugin/FlickrConfiguration.cs
index 94e767698..0d6ad0574 100644
--- a/GreenshotFlickrPlugin/FlickrConfiguration.cs
+++ b/GreenshotFlickrPlugin/FlickrConfiguration.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,43 +34,43 @@ namespace GreenshotFlickrPlugin {
[IniSection("Flickr", Description = "Greenshot Flickr Plugin configuration")]
public class FlickrConfiguration : IniSection {
[IniProperty("flickrIsPublic", Description = "IsPublic.", DefaultValue = "true")]
- public bool IsPublic;
+ public bool IsPublic { get; set; }
[IniProperty("flickrIsFamily", Description = "IsFamily.", DefaultValue = "true")]
- public bool IsFamily;
+ public bool IsFamily { get; set; }
[IniProperty("flickrIsFriend", Description = "IsFriend.", DefaultValue = "true")]
- public bool IsFriend;
+ public bool IsFriend { get; set; }
[IniProperty("SafetyLevel", Description = "Safety level", DefaultValue = "Safe")]
- public SafetyLevel SafetyLevel;
+ public SafetyLevel SafetyLevel { get; set; }
[IniProperty("HiddenFromSearch", Description = "Hidden from search", DefaultValue = "false")]
- public bool HiddenFromSearch;
-
+ public bool HiddenFromSearch { get; set; }
+
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
- public OutputFormat UploadFormat;
+ public OutputFormat UploadFormat { get; set; }
[IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
- public int UploadJpegQuality;
+ public int UploadJpegQuality { get; set; }
[IniProperty("AfterUploadLinkToClipBoard", Description = "After upload send flickr link to clipboard.", DefaultValue = "true")]
- public bool AfterUploadLinkToClipBoard;
+ public bool AfterUploadLinkToClipBoard { get; set; }
[IniProperty("UsePageLink", Description = "Use pagelink instead of direct link on the clipboard", DefaultValue = "False")]
- public bool UsePageLink;
-
+ public bool UsePageLink { get; set; }
+
[IniProperty("FlickrToken", Description = "The Flickr token", Encrypted = true, ExcludeIfNull = true)]
- public string FlickrToken;
+ public string FlickrToken { get; set; }
[IniProperty("FlickrTokenSecret", Description = "The Flickr token secret", Encrypted = true, ExcludeIfNull = true)]
- public string FlickrTokenSecret;
+ public string FlickrTokenSecret { get; set; }
///
/// A form for token
///
/// bool true if OK was pressed, false if cancel
public bool ShowConfigDialog() {
- DialogResult result = new SettingsForm(this).ShowDialog();
+ DialogResult result = new SettingsForm().ShowDialog();
if (result == DialogResult.OK) {
return true;
}
diff --git a/GreenshotFlickrPlugin/FlickrCredentials.cs b/GreenshotFlickrPlugin/FlickrCredentials.cs
index 75d888219..2eb6aea2a 100644
--- a/GreenshotFlickrPlugin/FlickrCredentials.cs
+++ b/GreenshotFlickrPlugin/FlickrCredentials.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/GreenshotFlickrPlugin/FlickrDestination.cs b/GreenshotFlickrPlugin/FlickrDestination.cs
index 7155937aa..70778e1f7 100644
--- a/GreenshotFlickrPlugin/FlickrDestination.cs
+++ b/GreenshotFlickrPlugin/FlickrDestination.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,27 +22,17 @@ using System.ComponentModel;
using System.Drawing;
using Greenshot.Plugin;
using GreenshotPlugin.Core;
-using log4net;
namespace GreenshotFlickrPlugin {
public class FlickrDestination : AbstractDestination {
- private static ILog LOG = LogManager.GetLogger(typeof(FlickrDestination));
- private FlickrPlugin plugin;
+ private readonly FlickrPlugin _plugin;
public FlickrDestination(FlickrPlugin plugin) {
- this.plugin = plugin;
+ _plugin = plugin;
}
- public override string Designation {
- get {
- return "Flickr";
- }
- }
+ public override string Designation => "Flickr";
- public override string Description {
- get {
- return Language.GetString("flickr", LangKey.upload_menu_item);
- }
- }
+ public override string Description => Language.GetString("flickr", LangKey.upload_menu_item);
public override Image DisplayIcon {
get {
@@ -53,11 +43,11 @@ namespace GreenshotFlickrPlugin {
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) {
ExportInformation exportInformation = new ExportInformation(Designation, Description);
- string uploadURL;
- bool uploaded = plugin.Upload(captureDetails, surface, out uploadURL);
+ string uploadUrl;
+ bool uploaded = _plugin.Upload(captureDetails, surface, out uploadUrl);
if (uploaded) {
exportInformation.ExportMade = true;
- exportInformation.Uri = uploadURL;
+ exportInformation.Uri = uploadUrl;
}
ProcessExport(exportInformation, surface);
return exportInformation;
diff --git a/GreenshotFlickrPlugin/FlickrPlugin.cs b/GreenshotFlickrPlugin/FlickrPlugin.cs
index ba6210b6e..5533ba643 100644
--- a/GreenshotFlickrPlugin/FlickrPlugin.cs
+++ b/GreenshotFlickrPlugin/FlickrPlugin.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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 GreenshotFlickrPlugin
/// This is the Flickr base code
///
public class FlickrPlugin : IGreenshotPlugin {
- private static readonly ILog LOG = LogManager.GetLogger(typeof(FlickrPlugin));
+ private static readonly ILog Log = LogManager.GetLogger(typeof(FlickrPlugin));
private static FlickrConfiguration _config;
public static PluginAttribute Attributes;
private IGreenshotHost _host;
@@ -83,10 +83,12 @@ namespace GreenshotFlickrPlugin
_config = IniConfig.GetIniSection();
_resources = new ComponentResourceManager(typeof(FlickrPlugin));
- _itemPlugInConfig = new ToolStripMenuItem();
- _itemPlugInConfig.Text = Language.GetString("flickr", LangKey.Configure);
- _itemPlugInConfig.Tag = _host;
- _itemPlugInConfig.Image = (Image)_resources.GetObject("flickr");
+ _itemPlugInConfig = new ToolStripMenuItem
+ {
+ Text = Language.GetString("flickr", LangKey.Configure),
+ Tag = _host,
+ Image = (Image) _resources.GetObject("flickr")
+ };
_itemPlugInConfig.Click += ConfigMenuClick;
PluginUtils.AddToContextMenu(_host, _itemPlugInConfig);
@@ -101,7 +103,7 @@ namespace GreenshotFlickrPlugin
}
public virtual void Shutdown() {
- LOG.Debug("Flickr Plugin shutdown.");
+ Log.Debug("Flickr Plugin shutdown.");
}
///
@@ -111,16 +113,6 @@ namespace GreenshotFlickrPlugin
_config.ShowConfigDialog();
}
- ///
- /// This will be called when Greenshot is shutting down
- ///
- ///
- ///
- public void Closing(object sender, FormClosingEventArgs e) {
- LOG.Debug("Application closing, de-registering Flickr Plugin!");
- Shutdown();
- }
-
public void ConfigMenuClick(object sender, EventArgs eventArgs) {
_config.ShowConfigDialog();
}
@@ -147,7 +139,7 @@ namespace GreenshotFlickrPlugin
}
return true;
} catch (Exception e) {
- LOG.Error("Error uploading.", e);
+ Log.Error("Error uploading.", e);
MessageBox.Show(Language.GetString("flickr", LangKey.upload_failure) + " " + e.Message);
}
return false;
diff --git a/GreenshotFlickrPlugin/FlickrUtils.cs b/GreenshotFlickrPlugin/FlickrUtils.cs
index 8737f85e0..00cb56ed4 100644
--- a/GreenshotFlickrPlugin/FlickrUtils.cs
+++ b/GreenshotFlickrPlugin/FlickrUtils.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,7 +34,7 @@ namespace GreenshotFlickrPlugin {
///
public class FlickrUtils {
private static readonly ILog LOG = LogManager.GetLogger(typeof(FlickrUtils));
- private static FlickrConfiguration config = IniConfig.GetIniSection();
+ private static readonly FlickrConfiguration config = IniConfig.GetIniSection();
private const string FLICKR_API_BASE_URL = "https://api.flickr.com/services/";
private const string FLICKR_UPLOAD_URL = FLICKR_API_BASE_URL + "upload/";
// OAUTH
@@ -57,15 +57,17 @@ namespace GreenshotFlickrPlugin {
///
/// url to image
public static string UploadToFlickr(ISurface surfaceToUpload, SurfaceOutputSettings outputSettings, string title, string filename) {
- OAuthSession oAuth = new OAuthSession(FlickrCredentials.ConsumerKey, FlickrCredentials.ConsumerSecret);
- oAuth.BrowserSize = new Size(520, 800);
- oAuth.CheckVerifier = false;
- oAuth.AccessTokenUrl = FLICKR_ACCESS_TOKEN_URL;
- oAuth.AuthorizeUrl = FLICKR_AUTHORIZE_URL;
- oAuth.RequestTokenUrl = FLICKR_REQUEST_TOKEN_URL;
- oAuth.LoginTitle = "Flickr authorization";
- oAuth.Token = config.FlickrToken;
- oAuth.TokenSecret = config.FlickrTokenSecret;
+ var oAuth = new OAuthSession(FlickrCredentials.ConsumerKey, FlickrCredentials.ConsumerSecret)
+ {
+ BrowserSize = new Size(520, 800),
+ CheckVerifier = false,
+ AccessTokenUrl = FLICKR_ACCESS_TOKEN_URL,
+ AuthorizeUrl = FLICKR_AUTHORIZE_URL,
+ RequestTokenUrl = FLICKR_REQUEST_TOKEN_URL,
+ LoginTitle = "Flickr authorization",
+ Token = config.FlickrToken,
+ TokenSecret = config.FlickrTokenSecret
+ };
if (string.IsNullOrEmpty(oAuth.Token)) {
if (!oAuth.Authorize()) {
return null;
@@ -85,7 +87,7 @@ namespace GreenshotFlickrPlugin {
signedParameters.Add("is_public", config.IsPublic ? "1" : "0");
signedParameters.Add("is_friend", config.IsFriend ? "1" : "0");
signedParameters.Add("is_family", config.IsFamily ? "1" : "0");
- signedParameters.Add("safety_level", string.Format("{0}", (int)config.SafetyLevel));
+ signedParameters.Add("safety_level", $"{(int) config.SafetyLevel}");
signedParameters.Add("hidden", config.HiddenFromSearch ? "1" : "2");
IDictionary otherParameters = new Dictionary();
otherParameters.Add("photo", new SurfaceContainer(surfaceToUpload, outputSettings, filename));
@@ -125,16 +127,13 @@ namespace GreenshotFlickrPlugin {
XmlNodeList nodes = doc.GetElementsByTagName("photo");
if (nodes.Count > 0) {
var item = nodes.Item(0);
- if (item != null) {
- if (item.Attributes != null) {
- string farmId = item.Attributes["farm"].Value;
- string serverId = item.Attributes["server"].Value;
- string photoId = item.Attributes["id"].Value;
- string secret = item.Attributes["secret"].Value;
- return string.Format(FLICKR_FARM_URL, farmId, serverId, photoId, secret);
- }
+ if (item?.Attributes != null) {
+ string farmId = item.Attributes["farm"].Value;
+ string serverId = item.Attributes["server"].Value;
+ string photoId = item.Attributes["id"].Value;
+ string secret = item.Attributes["secret"].Value;
+ return string.Format(FLICKR_FARM_URL, farmId, serverId, photoId, secret);
}
-
}
}
} catch (Exception ex) {
diff --git a/GreenshotFlickrPlugin/Forms/FlickrForm.cs b/GreenshotFlickrPlugin/Forms/FlickrForm.cs
index 59358436e..be50a03ca 100644
--- a/GreenshotFlickrPlugin/Forms/FlickrForm.cs
+++ b/GreenshotFlickrPlugin/Forms/FlickrForm.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,6 @@
* along with this program. If not, see .
*/
-using System;
using GreenshotPlugin.Controls;
namespace GreenshotFlickrPlugin.Forms {
diff --git a/GreenshotFlickrPlugin/Forms/SettingsForm.Designer.cs b/GreenshotFlickrPlugin/Forms/SettingsForm.Designer.cs
index 3f47f6b31..f87792173 100644
--- a/GreenshotFlickrPlugin/Forms/SettingsForm.Designer.cs
+++ b/GreenshotFlickrPlugin/Forms/SettingsForm.Designer.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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/GreenshotFlickrPlugin/Forms/SettingsForm.cs b/GreenshotFlickrPlugin/Forms/SettingsForm.cs
index 0835e2ea5..5c1e24551 100644
--- a/GreenshotFlickrPlugin/Forms/SettingsForm.cs
+++ b/GreenshotFlickrPlugin/Forms/SettingsForm.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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,21 +18,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-using System;
-using System.Drawing;
-using System.Windows.Forms;
using GreenshotFlickrPlugin.Forms;
-using GreenshotPlugin.Core;
namespace GreenshotFlickrPlugin {
///
/// Description of PasswordRequestForm.
///
public partial class SettingsForm : FlickrForm {
- private string flickrFrob = string.Empty;
-
- public SettingsForm(FlickrConfiguration config) {
+ public SettingsForm() {
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
diff --git a/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj b/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj
index 5c3c047e0..69d67f146 100644
--- a/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj
+++ b/GreenshotFlickrPlugin/GreenshotFlickrPlugin.csproj
@@ -71,11 +71,11 @@
rename "$(ProjectDir)FlickrCredentials.orig.cs" "FlickrCredentials.cs"
)
-mkdir "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)"
-copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
-copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\"
-mkdir "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
-copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
if exist "$(ProjectDir)FlickrCredentials.private.cs" (
rename "$(ProjectDir)FlickrCredentials.cs" "FlickrCredentials.orig.cs"
diff --git a/GreenshotFlickrPlugin/LanguageKeys.cs b/GreenshotFlickrPlugin/LanguageKeys.cs
index 63849aa3c..77590dc7c 100644
--- a/GreenshotFlickrPlugin/LanguageKeys.cs
+++ b/GreenshotFlickrPlugin/LanguageKeys.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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/GreenshotFlickrPlugin/Properties/AssemblyInfo.cs b/GreenshotFlickrPlugin/Properties/AssemblyInfo.cs
index 810171a92..e507ea606 100644
--- a/GreenshotFlickrPlugin/Properties/AssemblyInfo.cs
+++ b/GreenshotFlickrPlugin/Properties/AssemblyInfo.cs
@@ -1,9 +1,9 @@
/*
* Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
+ * Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom, Francis Noel
*
* 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.Plugin;
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/GreenshotImgurPlugin/Forms/ImgurHistory.cs b/GreenshotImgurPlugin/Forms/ImgurHistory.cs
index 4d67ab528..517bb165f 100644
--- a/GreenshotImgurPlugin/Forms/ImgurHistory.cs
+++ b/GreenshotImgurPlugin/Forms/ImgurHistory.cs
@@ -29,22 +29,37 @@ using Greenshot.IniFile;
namespace GreenshotImgurPlugin {
///
- /// Description of ImgurHistory.
+ /// Imgur history form
///
public sealed partial class ImgurHistory : ImgurForm {
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurHistory));
private readonly GreenshotColumnSorter _columnSorter;
+ private static readonly object Lock = new object();
private static readonly ImgurConfiguration Config = IniConfig.GetIniSection();
private static ImgurHistory _instance;
public static void ShowHistory() {
- // Make sure the history is loaded, will be done only once
- ImgurUtils.LoadHistory();
- if (_instance == null) {
- _instance = new ImgurHistory();
+ lock (Lock)
+ {
+ if (ImgurUtils.IsHistoryLoadingNeeded())
+ {
+ // Run upload in the background
+ new PleaseWaitForm().ShowAndWait("Imgur " + Language.GetString("imgur", LangKey.history), Language.GetString("imgur", LangKey.communication_wait),
+ ImgurUtils.LoadHistory
+ );
+ }
+
+ // Make sure the history is loaded, will be done only once
+ if (_instance == null)
+ {
+ _instance = new ImgurHistory();
+ }
+ if (!_instance.Visible)
+ {
+ _instance.Show();
+ }
+ _instance.Redraw();
}
- _instance.Show();
- _instance.Redraw();
}
private ImgurHistory() {
diff --git a/GreenshotImgurPlugin/Forms/SettingsForm.cs b/GreenshotImgurPlugin/Forms/SettingsForm.cs
index e7afda70c..f68a50794 100644
--- a/GreenshotImgurPlugin/Forms/SettingsForm.cs
+++ b/GreenshotImgurPlugin/Forms/SettingsForm.cs
@@ -25,7 +25,7 @@ namespace GreenshotImgurPlugin {
/// Description of PasswordRequestForm.
///
public partial class SettingsForm : ImgurForm {
- public SettingsForm(ImgurConfiguration config)
+ public SettingsForm()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
@@ -34,9 +34,7 @@ namespace GreenshotImgurPlugin {
CancelButton = buttonCancel;
AcceptButton = buttonOK;
- ImgurUtils.LoadHistory();
-
- historyButton.Enabled = config.runtimeImgurHistory.Count > 0;
+ historyButton.Enabled = ImgurUtils.IsHistoryLoadingNeeded();
}
private void ButtonHistoryClick(object sender, EventArgs e) {
diff --git a/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj b/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj
index 6dea91f73..6e4f81932 100644
--- a/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj
+++ b/GreenshotImgurPlugin/GreenshotImgurPlugin.csproj
@@ -22,6 +22,10 @@
+
+ ..\packages\LinqBridge.1.3.0\lib\net20\LinqBridge.dll
+ True
+ ..\Greenshot\Lib\log4net.dll
@@ -70,6 +74,7 @@
ImgurPlugin.cs
+
@@ -88,10 +93,10 @@ if exist "$(ProjectDir)ImgurCredentials.private.cs" (
rename "$(ProjectDir)ImgurCredentials.orig.cs" "ImgurCredentials.cs"
)
-mkdir "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)"
-copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
-copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\"
-mkdir "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
-copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
\ No newline at end of file
diff --git a/GreenshotImgurPlugin/ImgurConfiguration.cs b/GreenshotImgurPlugin/ImgurConfiguration.cs
index 2889c9501..a65c3e7b2 100644
--- a/GreenshotImgurPlugin/ImgurConfiguration.cs
+++ b/GreenshotImgurPlugin/ImgurConfiguration.cs
@@ -23,7 +23,6 @@ using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Greenshot.IniFile;
-using GreenshotPlugin.Controls;
using GreenshotPlugin.Core;
namespace GreenshotImgurPlugin {
@@ -95,18 +94,9 @@ namespace GreenshotImgurPlugin {
///
/// bool true if OK was pressed, false if cancel
public bool ShowConfigDialog() {
- SettingsForm settingsForm = null;
-
- new PleaseWaitForm().ShowAndWait(ImgurPlugin.Attributes.Name, Language.GetString("imgur", LangKey.communication_wait),
- delegate {
- settingsForm = new SettingsForm(this);
- }
- );
+ SettingsForm settingsForm = new SettingsForm();
DialogResult result = settingsForm.ShowDialog();
- if (result == DialogResult.OK) {
- return true;
- }
- return false;
+ return result == DialogResult.OK;
}
}
}
diff --git a/GreenshotImgurPlugin/ImgurPlugin.cs b/GreenshotImgurPlugin/ImgurPlugin.cs
index 93b8ede40..ec1d41b9e 100644
--- a/GreenshotImgurPlugin/ImgurPlugin.cs
+++ b/GreenshotImgurPlugin/ImgurPlugin.cs
@@ -23,7 +23,6 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
-using System.Threading;
using System.Windows.Forms;
using Greenshot.IniFile;
using Greenshot.Plugin;
@@ -75,7 +74,7 @@ namespace GreenshotImgurPlugin {
/// Use the IGreenshotPluginHost interface to register events
/// My own attributes
/// true if plugin is initialized, false if not (doesn't show)
- public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
+ public bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
_host = pluginHost;
Attributes = myAttributes;
@@ -109,14 +108,8 @@ namespace GreenshotImgurPlugin {
PluginUtils.AddToContextMenu(_host, itemPlugInRoot);
Language.LanguageChanged += OnLanguageChanged;
- // retrieve history in the background
- Thread backgroundTask = new Thread(CheckHistory)
- {
- Name = "Imgur History",
- IsBackground = true
- };
- backgroundTask.SetApartmentState(ApartmentState.STA);
- backgroundTask.Start();
+ // Enable history if there are items available
+ UpdateHistoryMenuItem();
return true;
}
@@ -129,9 +122,8 @@ namespace GreenshotImgurPlugin {
}
}
- private void CheckHistory() {
+ private void UpdateHistoryMenuItem() {
try {
- ImgurUtils.LoadHistory();
_host.GreenshotForm.BeginInvoke((MethodInvoker)delegate {
if (_config.ImgurUploadHistory.Count > 0) {
_historyMenuItem.Enabled = true;
@@ -178,7 +170,7 @@ namespace GreenshotImgurPlugin {
Log.InfoFormat("Storing imgur upload for hash {0} and delete hash {1}", imgurInfo.Hash, imgurInfo.DeleteHash);
_config.ImgurUploadHistory.Add(imgurInfo.Hash, imgurInfo.DeleteHash);
_config.runtimeImgurHistory.Add(imgurInfo.Hash, imgurInfo);
- CheckHistory();
+ UpdateHistoryMenuItem();
}
}
);
diff --git a/GreenshotImgurPlugin/ImgurUtils.cs b/GreenshotImgurPlugin/ImgurUtils.cs
index c32c0afba..95bbfc806 100644
--- a/GreenshotImgurPlugin/ImgurUtils.cs
+++ b/GreenshotImgurPlugin/ImgurUtils.cs
@@ -22,6 +22,7 @@ using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
+using System.Linq;
using System.Net;
using Greenshot.IniFile;
using Greenshot.Plugin;
@@ -29,7 +30,7 @@ using GreenshotPlugin.Core;
namespace GreenshotImgurPlugin {
///
- /// Description of ImgurUtils.
+ /// A collection of Imgur helper methods
///
public static class ImgurUtils {
private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(ImgurUtils));
@@ -38,44 +39,62 @@ namespace GreenshotImgurPlugin {
private const string AuthUrlPattern = "https://api.imgur.com/oauth2/authorize?response_type=code&client_id={ClientId}&redirect_uri={RedirectUrl}&state={State}";
private const string TokenUrl = "https://api.imgur.com/oauth2/token";
+ ///
+ /// Check if we need to load the history
+ ///
+ ///
+ public static bool IsHistoryLoadingNeeded()
+ {
+ Log.InfoFormat("Checking if imgur cache loading needed, configuration has {0} imgur hashes, loaded are {1} hashes.", Config.ImgurUploadHistory.Count, Config.runtimeImgurHistory.Count);
+ return Config.runtimeImgurHistory.Count != Config.ImgurUploadHistory.Count;
+ }
+
///
/// Load the complete history of the imgur uploads, with the corresponding information
///
public static void LoadHistory() {
- if (Config.runtimeImgurHistory.Count == Config.ImgurUploadHistory.Count) {
+ if (!IsHistoryLoadingNeeded())
+ {
return;
}
- // Load the ImUr history
- List hashes = new List();
- foreach(string hash in Config.ImgurUploadHistory.Keys) {
- hashes.Add(hash);
- }
-
+
bool saveNeeded = false;
- foreach(string hash in hashes) {
+ // Load the ImUr history
+ foreach (string hash in Config.ImgurUploadHistory.Keys.ToList()) {
if (Config.runtimeImgurHistory.ContainsKey(hash)) {
// Already loaded
continue;
}
- try {
- ImgurInfo imgurInfo = RetrieveImgurInfo(hash, Config.ImgurUploadHistory[hash]);
+
+ try
+ {
+ var deleteHash = Config.ImgurUploadHistory[hash];
+ ImgurInfo imgurInfo = RetrieveImgurInfo(hash, deleteHash);
if (imgurInfo != null) {
RetrieveImgurThumbnail(imgurInfo);
- Config.runtimeImgurHistory.Add(hash, imgurInfo);
+ Config.runtimeImgurHistory[hash] = imgurInfo;
} else {
- Log.DebugFormat("Deleting not found ImgUr {0} from config.", hash);
+ Log.InfoFormat("Deleting unknown ImgUr {0} from config, delete hash was {1}.", hash, deleteHash);
Config.ImgurUploadHistory.Remove(hash);
+ Config.runtimeImgurHistory.Remove(hash);
saveNeeded = true;
}
} catch (WebException wE) {
bool redirected = false;
if (wE.Status == WebExceptionStatus.ProtocolError) {
- HttpWebResponse response = ((HttpWebResponse)wE.Response);
- // Image no longer available
+ HttpWebResponse response = (HttpWebResponse)wE.Response;
+
+ if (response.StatusCode == HttpStatusCode.Forbidden)
+ {
+ Log.Error("Imgur loading forbidden", wE);
+ break;
+ }
+ // Image no longer available?
if (response.StatusCode == HttpStatusCode.Redirect) {
- Log.InfoFormat("ImgUr image for hash {0} is no longer available", hash);
+ Log.InfoFormat("ImgUr image for hash {0} is no longer available, removing it from the history", hash);
Config.ImgurUploadHistory.Remove(hash);
+ Config.runtimeImgurHistory.Remove(hash);
redirected = true;
}
}
@@ -113,11 +132,11 @@ namespace GreenshotImgurPlugin {
IDictionary otherParameters = new Dictionary();
// add title
if (title != null && Config.AddTitle) {
- otherParameters.Add("title", title);
+ otherParameters["title"]= title;
}
// add filename
if (filename != null && Config.AddFilename) {
- otherParameters.Add("name", filename);
+ otherParameters["name"] = filename;
}
string responseString = null;
if (Config.AnonymousAccess) {
@@ -171,7 +190,7 @@ namespace GreenshotImgurPlugin {
try
{
var webRequest = OAuth2Helper.CreateOAuth2WebRequest(HTTPMethod.POST, Config.ImgurApi3Url + "/upload.xml", oauth2Settings);
- otherParameters.Add("image", new SurfaceContainer(surfaceToUpload, outputSettings, filename));
+ otherParameters["image"] = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
NetworkHelper.WriteMultipartFormData(webRequest, otherParameters);
@@ -307,7 +326,7 @@ namespace GreenshotImgurPlugin {
///
private static void LogHeader(IDictionary nameValues, string key) {
if (nameValues.ContainsKey(key)) {
- Log.InfoFormat("key={0}", nameValues[key]);
+ Log.InfoFormat("{0}={1}", key, nameValues[key]);
}
}
diff --git a/GreenshotImgurPlugin/packages.config b/GreenshotImgurPlugin/packages.config
new file mode 100644
index 000000000..6003a80e6
--- /dev/null
+++ b/GreenshotImgurPlugin/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/AsyncMemoryCache.cs b/GreenshotJiraPlugin/AsyncMemoryCache.cs
new file mode 100644
index 000000000..f7d029750
--- /dev/null
+++ b/GreenshotJiraPlugin/AsyncMemoryCache.cs
@@ -0,0 +1,246 @@
+#region Dapplo 2016 - GNU Lesser General Public License
+
+// Dapplo - building blocks for .NET applications
+// Copyright (C) 2016 Dapplo
+//
+// For more information see: http://dapplo.net/
+// Dapplo repositories are hosted on GitHub: https://github.com/dapplo
+//
+// This file is part of Dapplo.Utils
+//
+// Dapplo.Utils is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Dapplo.Utils 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 Lesser General Public License for more details.
+//
+// You should have a copy of the GNU Lesser General Public License
+// along with Dapplo.Utils. If not, see .
+
+#endregion
+
+#region Usings
+
+using System;
+using System.Runtime.Caching;
+using System.Threading;
+using System.Threading.Tasks;
+using Dapplo.Log.Facade;
+
+#endregion
+
+
+namespace GreenshotJiraPlugin
+{
+ ///
+ /// This abstract class builds a base for a simple async memory cache.
+ ///
+ /// Type for the key
+ /// Type for the stored value
+ public abstract class AsyncMemoryCache where TResult : class
+ {
+ private static readonly Task EmptyValueTask = Task.FromResult(null);
+ private readonly SemaphoreSlim _semaphoreSlim = new SemaphoreSlim(1, 1);
+ private readonly MemoryCache _cache = new MemoryCache(Guid.NewGuid().ToString());
+ private readonly LogSource _log = new LogSource();
+
+ ///
+ /// Set the timespan for items to expire.
+ ///
+ public TimeSpan? ExpireTimeSpan { get; set; }
+
+ ///
+ /// Set the timespan for items to slide.
+ ///
+ public TimeSpan? SlidingTimeSpan { get; set; }
+
+ ///
+ /// Specifies if the RemovedCallback needs to be called
+ /// If this is active, ActivateUpdateCallback should be false
+ ///
+ protected bool ActivateRemovedCallback { get; set; } = true;
+
+ ///
+ /// Specifies if the UpdateCallback needs to be called.
+ /// If this is active, ActivateRemovedCallback should be false
+ ///
+ protected bool ActivateUpdateCallback { get; set; } = false;
+
+ ///
+ /// Implement this method, it should create an instance of TResult via the supplied TKey.
+ ///
+ /// TKey
+ /// CancellationToken
+ /// TResult
+ protected abstract Task CreateAsync(TKey key, CancellationToken cancellationToken = default(CancellationToken));
+
+ ///
+ /// Creates a key under which the object is stored or retrieved, default is a toString on the object.
+ ///
+ /// TKey
+ /// string
+ protected virtual string CreateKey(TKey keyObject)
+ {
+ return keyObject.ToString();
+ }
+
+ ///
+ /// Get an element from the cache, if this is not available call the create function.
+ ///
+ /// object for the key
+ /// CancellationToken
+ /// TResult
+ public async Task DeleteAsync(TKey keyObject, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var key = CreateKey(keyObject);
+ await _semaphoreSlim.WaitAsync(cancellationToken).ConfigureAwait(false);
+ try
+ {
+ _cache.Remove(key);
+ }
+ finally
+ {
+ _semaphoreSlim.Release();
+ }
+ }
+
+ ///
+ /// Get a task element from the cache, if this is not available return null.
+ /// You probably want to call GetOrCreateAsync
+ ///
+ /// object for the key
+ /// Task with TResult, null if no value
+ public Task GetAsync(TKey keyObject)
+ {
+ var key = CreateKey(keyObject);
+ return _cache.Get(key) as Task ?? EmptyValueTask;
+ }
+
+ ///
+ /// Get a task element from the cache, if this is not available call the create function.
+ ///
+ /// object for the key
+ /// CancellationToken
+ /// Task with TResult
+ public Task GetOrCreateAsync(TKey keyObject, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var key = CreateKey(keyObject);
+ return _cache.Get(key) as Task ?? GetOrCreateInternalAsync(keyObject, null, cancellationToken);
+ }
+
+ ///
+ /// Get a task element from the cache, if this is not available call the create function.
+ ///
+ /// object for the key
+ /// CacheItemPolicy for when you want more control over the item
+ /// CancellationToken
+ /// Task with TResult
+ public Task GetOrCreateAsync(TKey keyObject, CacheItemPolicy cacheItemPolicy, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var key = CreateKey(keyObject);
+ return _cache.Get(key) as Task ?? GetOrCreateInternalAsync(keyObject, cacheItemPolicy, cancellationToken);
+ }
+
+ ///
+ /// This takes care of the real async part of the code.
+ ///
+ ///
+ /// CacheItemPolicy for when you want more control over the item
+ /// CancellationToken
+ /// TResult
+ private async Task GetOrCreateInternalAsync(TKey keyObject, CacheItemPolicy cacheItemPolicy = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ var key = CreateKey(keyObject);
+ var completionSource = new TaskCompletionSource();
+
+ if (cacheItemPolicy == null)
+ {
+ cacheItemPolicy = new CacheItemPolicy
+ {
+ AbsoluteExpiration = ExpireTimeSpan.HasValue ? DateTimeOffset.Now.Add(ExpireTimeSpan.Value) : ObjectCache.InfiniteAbsoluteExpiration,
+ SlidingExpiration = SlidingTimeSpan ?? ObjectCache.NoSlidingExpiration
+ };
+ if (ActivateUpdateCallback)
+ {
+ cacheItemPolicy.UpdateCallback = UpdateCallback;
+ }
+ if (ActivateRemovedCallback)
+ {
+ cacheItemPolicy.RemovedCallback = RemovedCallback;
+ }
+ }
+
+ var result = _cache.AddOrGetExisting(key, completionSource.Task, cacheItemPolicy) as Task;
+ // Test if we got an existing object or our own
+ if (result != null && !completionSource.Task.Equals(result))
+ {
+ return await result.ConfigureAwait(false);
+ }
+
+ await _semaphoreSlim.WaitAsync(cancellationToken).ConfigureAwait(false);
+ try
+ {
+ result = _cache.AddOrGetExisting(key, completionSource.Task, cacheItemPolicy) as Task;
+ if (result != null && !completionSource.Task.Equals(result))
+ {
+ return await result.ConfigureAwait(false);
+ }
+
+ // Now, start the background task, which will set the completionSource with the correct response
+ // ReSharper disable once MethodSupportsCancellation
+ // ReSharper disable once UnusedVariable
+ var ignoreBackgroundTask = Task.Run(async () =>
+ {
+ try
+ {
+ var backgroundResult = await CreateAsync(keyObject, cancellationToken).ConfigureAwait(false);
+ completionSource.TrySetResult(backgroundResult);
+ }
+ catch (TaskCanceledException)
+ {
+ completionSource.TrySetCanceled();
+ }
+ catch (Exception ex)
+ {
+ completionSource.TrySetException(ex);
+ }
+ });
+ }
+ finally
+ {
+ _semaphoreSlim.Release();
+ }
+
+ return await completionSource.Task.ConfigureAwait(false);
+ }
+
+ ///
+ /// Override to know when an item is removed, make sure to configure ActivateUpdateCallback / ActivateRemovedCallback
+ ///
+ /// CacheEntryRemovedArguments
+ protected virtual void RemovedCallback(CacheEntryRemovedArguments cacheEntryRemovedArguments)
+ {
+ _log.Verbose().WriteLine("Item {0} removed due to {1}.", cacheEntryRemovedArguments.CacheItem.Key, cacheEntryRemovedArguments.RemovedReason);
+ var disposable = cacheEntryRemovedArguments.CacheItem.Value as IDisposable;
+ if (disposable != null)
+ {
+ _log.Debug().WriteLine("Disposed cached item.");
+ disposable.Dispose();
+ }
+ }
+
+ ///
+ /// Override to modify the cache behaviour when an item is about to be removed, make sure to configure
+ /// ActivateUpdateCallback / ActivateRemovedCallback
+ ///
+ /// CacheEntryUpdateArguments
+ protected virtual void UpdateCallback(CacheEntryUpdateArguments cacheEntryUpdateArguments)
+ {
+ _log.Verbose().WriteLine("Update request for {0} due to {1}.", cacheEntryUpdateArguments.Key, cacheEntryUpdateArguments.RemovedReason);
+ }
+ }
+}
diff --git a/GreenshotJiraPlugin/Forms/JiraForm.Designer.cs b/GreenshotJiraPlugin/Forms/JiraForm.Designer.cs
index 8b60e5c4c..c19bf181d 100644
--- a/GreenshotJiraPlugin/Forms/JiraForm.Designer.cs
+++ b/GreenshotJiraPlugin/Forms/JiraForm.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
@@ -18,7 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-namespace GreenshotJiraPlugin {
+namespace GreenshotJiraPlugin.Forms {
partial class JiraForm {
///
/// Required designer variable.
@@ -67,7 +67,7 @@ namespace GreenshotJiraPlugin {
this.jiraFilterBox.Name = "jiraFilterBox";
this.jiraFilterBox.Size = new System.Drawing.Size(604, 21);
this.jiraFilterBox.TabIndex = 5;
- this.jiraFilterBox.SelectedIndexChanged += new System.EventHandler(this.jiraFilterBox_SelectedIndexChanged);
+ this.jiraFilterBox.SelectedIndexChanged += new System.EventHandler(this.JiraFilterBox_SelectedIndexChanged);
//
// label_jirafilter
//
@@ -112,8 +112,8 @@ namespace GreenshotJiraPlugin {
this.jiraListView.TabIndex = 4;
this.jiraListView.UseCompatibleStateImageBehavior = false;
this.jiraListView.View = System.Windows.Forms.View.Details;
- this.jiraListView.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.jiraListView_ColumnClick);
- this.jiraListView.SelectedIndexChanged += new System.EventHandler(this.jiraListView_SelectedIndexChanged);
+ this.jiraListView.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.JiraListView_ColumnClick);
+ this.jiraListView.SelectedIndexChanged += new System.EventHandler(this.JiraListView_SelectedIndexChanged);
//
// jiraFilenameBox
//
diff --git a/GreenshotJiraPlugin/Forms/JiraForm.cs b/GreenshotJiraPlugin/Forms/JiraForm.cs
index 535a039bf..cfd5183e6 100644
--- a/GreenshotJiraPlugin/Forms/JiraForm.cs
+++ b/GreenshotJiraPlugin/Forms/JiraForm.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,186 +18,208 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
+
using System;
using System.Globalization;
using System.Windows.Forms;
-
+using Dapplo.Jira.Entities;
+using Greenshot.IniFile;
using GreenshotPlugin.Controls;
using GreenshotPlugin.Core;
-using Greenshot.IniFile;
-using Jira;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
-namespace GreenshotJiraPlugin {
+namespace GreenshotJiraPlugin.Forms {
public partial class JiraForm : Form {
- private JiraConnector jiraConnector;
- private JiraIssue selectedIssue;
- private GreenshotColumnSorter columnSorter;
- private JiraConfiguration config = IniConfig.GetIniSection();
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraForm));
+ private readonly JiraConnector _jiraConnector;
+ private Issue _selectedIssue;
+ private readonly GreenshotColumnSorter _columnSorter;
+ private static readonly JiraConfiguration JiraConfig = IniConfig.GetIniSection();
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
public JiraForm(JiraConnector jiraConnector) {
InitializeComponent();
- this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon();
+ Icon = GreenshotResources.getGreenshotIcon();
AcceptButton = uploadButton;
CancelButton = cancelButton;
- initializeComponentText();
+ InitializeComponentText();
- this.columnSorter = new GreenshotColumnSorter();
- this.jiraListView.ListViewItemSorter = columnSorter;
+ _columnSorter = new GreenshotColumnSorter();
+ jiraListView.ListViewItemSorter = _columnSorter;
- this.jiraConnector = jiraConnector;
+ _jiraConnector = jiraConnector;
- changeModus(false);
- try {
- if (!jiraConnector.isLoggedIn) {
- jiraConnector.login();
+ ChangeModus(false);
+
+ uploadButton.Enabled = false;
+ Load += OnLoad;
+ }
+
+ private async void OnLoad(object sender, EventArgs eventArgs)
+ {
+ try
+ {
+ if (!_jiraConnector.IsLoggedIn)
+ {
+ await _jiraConnector.LoginAsync();
}
- } catch (Exception e) {
+ }
+ catch (Exception e)
+ {
MessageBox.Show(Language.GetFormattedString("jira", LangKey.login_error, e.Message));
}
- uploadButton.Enabled = false;
- updateForm();
- }
-
- private void initializeComponentText() {
- this.label_jirafilter.Text = Language.GetString("jira", LangKey.label_jirafilter);
- this.label_comment.Text = Language.GetString("jira", LangKey.label_comment);
- this.label_filename.Text = Language.GetString("jira", LangKey.label_filename);
- }
-
- private void updateForm() {
- if (jiraConnector.isLoggedIn) {
- JiraFilter[] filters = jiraConnector.getFilters();
- if (filters.Length > 0) {
- foreach (JiraFilter filter in filters) {
+ if (_jiraConnector.IsLoggedIn)
+ {
+ var filters = await _jiraConnector.GetFavoriteFiltersAsync();
+ if (filters.Count > 0)
+ {
+ foreach (var filter in filters)
+ {
jiraFilterBox.Items.Add(filter);
}
jiraFilterBox.SelectedIndex = 0;
}
- changeModus(true);
- if (config.LastUsedJira != null) {
- selectedIssue = jiraConnector.getIssue(config.LastUsedJira);
- if (selectedIssue != null) {
- jiraKey.Text = config.LastUsedJira;
- uploadButton.Enabled = true;
- }
+ ChangeModus(true);
+ if (_jiraConnector.Monitor.RecentJiras.Any())
+ {
+ _selectedIssue = _jiraConnector.Monitor.RecentJiras.First().JiraIssue;
+ jiraKey.Text = _selectedIssue.Key;
+ uploadButton.Enabled = true;
}
}
}
- private void changeModus(bool enabled) {
+ private void InitializeComponentText() {
+ label_jirafilter.Text = Language.GetString("jira", LangKey.label_jirafilter);
+ label_comment.Text = Language.GetString("jira", LangKey.label_comment);
+ label_filename.Text = Language.GetString("jira", LangKey.label_filename);
+ }
+
+ private void ChangeModus(bool enabled) {
jiraFilterBox.Enabled = enabled;
jiraListView.Enabled = enabled;
jiraFilenameBox.Enabled = enabled;
jiraCommentBox.Enabled = enabled;
}
- public void setFilename(string filename) {
+ public void SetFilename(string filename) {
jiraFilenameBox.Text = filename;
}
- public void setComment(string comment) {
- jiraCommentBox.Text = comment;
+ public Issue GetJiraIssue() {
+ return _selectedIssue;
}
- public JiraIssue getJiraIssue() {
- return selectedIssue;
- }
-
- public void upload(IBinaryContainer attachment) {
- config.LastUsedJira = selectedIssue.Key;
- jiraConnector.addAttachment(selectedIssue.Key, jiraFilenameBox.Text, attachment);
- if (jiraCommentBox.Text != null && jiraCommentBox.Text.Length > 0) {
- jiraConnector.addComment(selectedIssue.Key, jiraCommentBox.Text);
+ public async Task UploadAsync(IBinaryContainer attachment) {
+ attachment.Filename = jiraFilenameBox.Text;
+ await _jiraConnector.AttachAsync(_selectedIssue.Key, attachment);
+
+ if (!string.IsNullOrEmpty(jiraCommentBox.Text)) {
+ await _jiraConnector.AddCommentAsync(_selectedIssue.Key, jiraCommentBox.Text);
}
}
- public void logout() {
- jiraConnector.logout();
- }
+ private async void JiraFilterBox_SelectedIndexChanged(object sender, EventArgs e) {
+ if (_jiraConnector.IsLoggedIn) {
- private void selectJiraToolStripMenuItem_Click(object sender, EventArgs e) {
- ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender;
- selectedIssue = (JiraIssue)clickedItem.Tag;
- jiraKey.Text = selectedIssue.Key;
- }
-
- private void jiraFilterBox_SelectedIndexChanged(object sender, EventArgs e) {
- if (jiraConnector.isLoggedIn) {
- JiraIssue[] issues = null;
uploadButton.Enabled = false;
- JiraFilter filter = (JiraFilter)jiraFilterBox.SelectedItem;
+ var filter = (Filter)jiraFilterBox.SelectedItem;
if (filter == null) {
return;
}
- // Run upload in the background
- new PleaseWaitForm().ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait),
- delegate() {
- issues = jiraConnector.getIssuesForFilter(filter.Id);
- }
- );
- jiraListView.BeginUpdate();
- jiraListView.Items.Clear();
- if (issues.Length > 0) {
- jiraListView.Columns.Clear();
- LangKey[] columns = { LangKey.column_id, LangKey.column_created, LangKey.column_assignee, LangKey.column_reporter, LangKey.column_summary };
- foreach (LangKey column in columns) {
- jiraListView.Columns.Add(Language.GetString("jira", column));
- }
- foreach (JiraIssue issue in issues) {
- ListViewItem item = new ListViewItem(issue.Key);
- item.Tag = issue;
- item.SubItems.Add(issue.Created.Value.ToString("d", DateTimeFormatInfo.InvariantInfo));
- item.SubItems.Add(issue.Assignee);
- item.SubItems.Add(issue.Reporter);
- item.SubItems.Add(issue.Summary);
- jiraListView.Items.Add(item);
- }
- for (int i = 0; i < columns.Length; i++) {
- jiraListView.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent);
- }
+ IList issues = null;
+ try
+ {
+ issues = await _jiraConnector.SearchAsync(filter);
+ }
+ catch (Exception ex)
+ {
+ Log.Error(ex);
+ MessageBox.Show(this, ex.Message, "Error in filter", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+
+ jiraListView.Items.Clear();
+ if (issues?.Count > 0) {
+ jiraListView.Columns.Clear();
+ LangKey[] columns = { LangKey.column_issueType, LangKey.column_id, LangKey.column_created, LangKey.column_assignee, LangKey.column_reporter, LangKey.column_summary };
+ foreach (LangKey column in columns)
+ {
+ string translation;
+ if (!Language.TryGetString("jira", column, out translation))
+ {
+ translation = "";
+ }
+ jiraListView.Columns.Add(translation);
+ }
+ var imageList = new ImageList {
+ ImageSize = CoreConfig.IconSize
+ };
+ jiraListView.SmallImageList = imageList;
+ jiraListView.LargeImageList = imageList;
+
+ foreach (var issue in issues) {
+ var issueIcon = await _jiraConnector.GetIssueTypeBitmapAsync(issue);
+ imageList.Images.Add(issueIcon);
+
+ var item = new ListViewItem
+ {
+ Tag = issue,
+ ImageIndex = imageList.Images.Count - 1
+ };
+ item.SubItems.Add(issue.Key);
+ item.SubItems.Add(issue.Fields.Created.ToString("d", DateTimeFormatInfo.InvariantInfo));
+ item.SubItems.Add(issue.Fields.Assignee?.DisplayName);
+ item.SubItems.Add(issue.Fields.Reporter?.DisplayName);
+ item.SubItems.Add(issue.Fields.Summary);
+ jiraListView.Items.Add(item);
+ for (int i = 0; i < columns.Length; i++)
+ {
+ jiraListView.AutoResizeColumn(i, ColumnHeaderAutoResizeStyle.ColumnContent);
+ }
+ jiraListView.Invalidate();
+ jiraListView.Update();
+ }
+
+ jiraListView.Refresh();
}
- jiraListView.EndUpdate();
- jiraListView.Refresh();
}
}
- private void jiraListView_SelectedIndexChanged(object sender, EventArgs e) {
- if (jiraListView.SelectedItems != null && jiraListView.SelectedItems.Count > 0) {
- selectedIssue = (JiraIssue)jiraListView.SelectedItems[0].Tag;
- jiraKey.Text = selectedIssue.Key;
+ private void JiraListView_SelectedIndexChanged(object sender, EventArgs e) {
+ if (jiraListView.SelectedItems.Count > 0) {
+ _selectedIssue = (Issue)jiraListView.SelectedItems[0].Tag;
+ jiraKey.Text = _selectedIssue.Key;
uploadButton.Enabled = true;
} else {
uploadButton.Enabled = false;
}
}
- private void jiraListView_ColumnClick(object sender, ColumnClickEventArgs e) {
+ private void JiraListView_ColumnClick(object sender, ColumnClickEventArgs e) {
// Determine if clicked column is already the column that is being sorted.
- if (e.Column == columnSorter.SortColumn) {
+ if (e.Column == _columnSorter.SortColumn) {
// Reverse the current sort direction for this column.
- if (columnSorter.Order == SortOrder.Ascending) {
- columnSorter.Order = SortOrder.Descending;
- } else {
- columnSorter.Order = SortOrder.Ascending;
- }
+ _columnSorter.Order = _columnSorter.Order == SortOrder.Ascending ? SortOrder.Descending : SortOrder.Ascending;
} else {
// Set the column number that is to be sorted; default to ascending.
- columnSorter.SortColumn = e.Column;
- columnSorter.Order = SortOrder.Ascending;
+ _columnSorter.SortColumn = e.Column;
+ _columnSorter.Order = SortOrder.Ascending;
}
// Perform the sort with these new sort options.
- this.jiraListView.Sort();
+ jiraListView.Sort();
}
- void JiraKeyTextChanged(object sender, EventArgs e) {
+ private async void JiraKeyTextChanged(object sender, EventArgs e) {
string jiranumber = jiraKey.Text;
uploadButton.Enabled = false;
int dashIndex = jiranumber.IndexOf('-');
if (dashIndex > 0 && jiranumber.Length > dashIndex+1) {
- selectedIssue = jiraConnector.getIssue(jiraKey.Text);
- if (selectedIssue != null) {
+ _selectedIssue = await _jiraConnector.GetIssueAsync(jiraKey.Text);
+ if (_selectedIssue != null) {
uploadButton.Enabled = true;
}
}
diff --git a/GreenshotJiraPlugin/Forms/JiraFormBase.cs b/GreenshotJiraPlugin/Forms/JiraFormBase.cs
index 6cba807a3..503304e66 100644
--- a/GreenshotJiraPlugin/Forms/JiraFormBase.cs
+++ b/GreenshotJiraPlugin/Forms/JiraFormBase.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,10 +18,10 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-using System;
+
using GreenshotPlugin.Controls;
-namespace GreenshotJiraPlugin {
+namespace GreenshotJiraPlugin.Forms {
public class JiraFormBase : GreenshotForm {
}
}
diff --git a/GreenshotJiraPlugin/Forms/SettingsForm.Designer.cs b/GreenshotJiraPlugin/Forms/SettingsForm.Designer.cs
index ab6257839..10e184dc4 100644
--- a/GreenshotJiraPlugin/Forms/SettingsForm.Designer.cs
+++ b/GreenshotJiraPlugin/Forms/SettingsForm.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
@@ -18,7 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-namespace GreenshotJiraPlugin {
+namespace GreenshotJiraPlugin.Forms {
partial class SettingsForm {
///
/// Designer variable used to keep track of non-visual components.
diff --git a/GreenshotJiraPlugin/Forms/SettingsForm.cs b/GreenshotJiraPlugin/Forms/SettingsForm.cs
index 1ecaecfbf..7d128ea8a 100644
--- a/GreenshotJiraPlugin/Forms/SettingsForm.cs
+++ b/GreenshotJiraPlugin/Forms/SettingsForm.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,16 +18,14 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-using System;
-using System.Windows.Forms;
-using GreenshotPlugin.Core;
-namespace GreenshotJiraPlugin {
+namespace GreenshotJiraPlugin.Forms {
///
/// Description of PasswordRequestForm.
///
public partial class SettingsForm : JiraFormBase {
- public SettingsForm(JiraConfiguration config) :base () {
+ public SettingsForm()
+ {
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
diff --git a/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj b/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj
index 671d710a9..fe5838095 100644
--- a/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj
+++ b/GreenshotJiraPlugin/GreenshotJiraPlugin.csproj
@@ -6,7 +6,7 @@
LibraryGreenshotJiraPluginGreenshotJiraPlugin
- v2.0
+ v4.5PropertiesFalseFalse
@@ -20,18 +20,49 @@
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ ..\packages\Dapplo.HttpExtensions.0.5.43\lib\net45\Dapplo.HttpExtensions.dll
+ True
+
+
+ ..\packages\Dapplo.Jira.0.1.65\lib\net45\Dapplo.Jira.dll
+ True
+
+
+ ..\packages\Dapplo.Log.Facade.0.5.4\lib\net45\Dapplo.Log.Facade.dll
+ True
+ ..\Greenshot\Lib\log4net.dll
+
+ ..\packages\Svg.2.2.2\lib\net35\Svg.dll
+ True
+
+
+
+ Form
@@ -47,18 +78,24 @@
SettingsForm.cs
-
+
+
+
+
+
+
+
+
+
+
-
+
-
- True
- True
- Reference.map
-
+
+ Always
@@ -72,34 +109,39 @@
Always
-
-
- MSDiscoCodeGenerator
- Reference.cs
-
+ JiraPlugin.cs
-
-
- Static
- http://jira/rpc/soap/jirasoapservice-v2%3fwsdl
- Web References\JiraSoap
- Jira
- {5B924697-4DCD-4F98-85F1-105CB84B7341}GreenshotPlugin
+
+ {CD642BF4-D815-4D67-A0B5-C69F0B8231AF}
+ Greenshot
+
- mkdir "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)"
-copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
-copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)bin\$(Configuration)\Plugins\$(ProjectName)\"
-mkdir "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
-copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"
+ mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"
+"$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+del /q /s "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)"\*
+
+if "$(ConfigurationName)" == "Release" (
+ ..\..\..\packages\LibZ.Tool.1.2.0.0\tools\libz.exe inject-dll --assembly $(ProjectDir)bin\$(Configuration)\$(TargetFileName) --include $(ProjectDir)bin\$(Configuration)\dapplo*.dll --include $(ProjectDir)bin\$(Configuration)\svg.dll --move
+)
+copy "$(ProjectDir)bin\$(Configuration)\$(TargetFileName)" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\*.gsp"
+
+if "$(ConfigurationName)" == "Debug" (
+ copy "$(ProjectDir)bin\$(Configuration)\Dapplo.*" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+ copy "$(ProjectDir)bin\$(Configuration)\Svg.dll" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+ copy "$(ProjectDir)bin\$(Configuration)\$(ProjectName).pdb" "$(SolutionDir)Greenshot\bin\$(Configuration)\Plugins\$(ProjectName)\"
+)
+
+mkdir "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)"
+copy "$(ProjectDir)\Languages\*.xml" "$(SolutionDir)Greenshot\bin\$(Configuration)\Languages\Plugins\$(ProjectName)\"False
diff --git a/GreenshotJiraPlugin/Hooking/TitleChangeEventArgs.cs b/GreenshotJiraPlugin/Hooking/TitleChangeEventArgs.cs
new file mode 100644
index 000000000..6ec8878fd
--- /dev/null
+++ b/GreenshotJiraPlugin/Hooking/TitleChangeEventArgs.cs
@@ -0,0 +1,50 @@
+/*
+ * dapplo - building blocks for desktop applications
+ * Copyright (C) Dapplo 2015-2016
+ *
+ * For more information see: http://dapplo.net/
+ * dapplo repositories are hosted on GitHub: https://github.com/dapplo
+ *
+ * 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;
+
+namespace GreenshotJiraPlugin.Hooking
+{
+ ///
+ /// Event arguments for the TitleChangeEvent
+ ///
+ public class TitleChangeEventArgs : EventArgs
+ {
+ ///
+ /// HWnd of the window which has a changed title
+ ///
+ public IntPtr HWnd
+ {
+ get;
+ set;
+ }
+
+ ///
+ /// Title which is changed
+ ///
+ public string Title
+ {
+ get;
+ set;
+ }
+ }
+
+}
diff --git a/GreenshotJiraPlugin/Hooking/TitleChangeEventDelegate.cs b/GreenshotJiraPlugin/Hooking/TitleChangeEventDelegate.cs
new file mode 100644
index 000000000..29847a1e5
--- /dev/null
+++ b/GreenshotJiraPlugin/Hooking/TitleChangeEventDelegate.cs
@@ -0,0 +1,29 @@
+/*
+ * dapplo - building blocks for desktop applications
+ * Copyright (C) Dapplo 2015-2016
+ *
+ * For more information see: http://dapplo.net/
+ * dapplo repositories are hosted on GitHub: https://github.com/dapplo
+ *
+ * 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 .
+ */
+
+namespace GreenshotJiraPlugin.Hooking
+{
+ ///
+ /// Delegate for the title change event
+ ///
+ ///
+ public delegate void TitleChangeEventDelegate(TitleChangeEventArgs eventArgs);
+}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/Hooking/WindowsEventHook.cs b/GreenshotJiraPlugin/Hooking/WindowsEventHook.cs
new file mode 100644
index 000000000..e2be9d0b0
--- /dev/null
+++ b/GreenshotJiraPlugin/Hooking/WindowsEventHook.cs
@@ -0,0 +1,152 @@
+/*
+ * dapplo - building blocks for desktop applications
+ * Copyright (C) Dapplo 2015-2016
+ *
+ * For more information see: http://dapplo.net/
+ * dapplo repositories are hosted on GitHub: https://github.com/dapplo
+ *
+ * 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;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using GreenshotPlugin.UnmanagedHelpers;
+
+namespace GreenshotJiraPlugin.Hooking
+{
+ ///
+ /// The WinEventHook can register handlers to become important windows events
+ /// This makes it possible to know a.o. when a window is created, moved, updated and closed.
+ ///
+ public class WindowsEventHook : IDisposable
+ {
+ private readonly WinEventDelegate _winEventHandler;
+ private GCHandle _gcHandle;
+
+ ///
+ /// Used with Register hook
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public delegate void WinEventHandler(WinEvent eventType, IntPtr hwnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
+
+ ///
+ /// Create a WindowsEventHook object
+ ///
+ public WindowsEventHook()
+ {
+ _winEventHandler = WinEventDelegateHandler;
+ _gcHandle = GCHandle.Alloc(_winEventHandler);
+ }
+
+ #region native code
+ [DllImport("user32", SetLastError = true)]
+ private static extern bool UnhookWinEvent(IntPtr hWinEventHook);
+ [DllImport("user32", SetLastError = true)]
+ private static extern IntPtr SetWinEventHook(WinEvent eventMin, WinEvent eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, int idProcess, int idThread, WinEventHookFlags dwFlags);
+
+ ///
+ /// Used with SetWinEventHook
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private delegate void WinEventDelegate(IntPtr hWinEventHook, WinEvent eventType, IntPtr hwnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
+ #endregion
+
+ private readonly IDictionary _winEventHandlers = new Dictionary();
+
+ ///
+ /// Are hooks active?
+ ///
+ public bool IsHooked => _winEventHandlers.Count > 0;
+
+ ///
+ /// Hook a WinEvent
+ ///
+ ///
+ ///
+ /// true if success
+ public void Hook(WinEvent winEvent, WinEventHandler winEventHandler)
+ {
+ Hook(winEvent, winEvent, winEventHandler);
+ }
+
+ ///
+ /// Hook a WinEvent
+ ///
+ ///
+ ///
+ ///
+ public void Hook(WinEvent winEventStart, WinEvent winEventEnd, WinEventHandler winEventHandler)
+ {
+ var hookPtr = SetWinEventHook(winEventStart, winEventEnd, IntPtr.Zero, _winEventHandler, 0, 0, WinEventHookFlags.WINEVENT_SKIPOWNPROCESS | WinEventHookFlags.WINEVENT_OUTOFCONTEXT);
+ _winEventHandlers.Add(hookPtr, winEventHandler);
+ }
+
+ ///
+ /// Remove all hooks
+ ///
+ private void Unhook()
+ {
+ foreach (var hookPtr in _winEventHandlers.Keys)
+ {
+ if (hookPtr != IntPtr.Zero)
+ {
+ UnhookWinEvent(hookPtr);
+ }
+ }
+ _winEventHandlers.Clear();
+ _gcHandle.Free();
+ }
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ public void Dispose()
+ {
+ Unhook();
+ }
+
+ ///
+ /// Call the WinEventHandler for this event
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void WinEventDelegateHandler(IntPtr hWinEventHook, WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ {
+ WinEventHandler handler;
+ if (_winEventHandlers.TryGetValue(hWinEventHook, out handler))
+ {
+ handler(eventType, hWnd, idObject, idChild, dwEventThread, dwmsEventTime);
+ }
+ }
+
+ }
+
+}
diff --git a/GreenshotJiraPlugin/Hooking/WindowsTitleMonitor.cs b/GreenshotJiraPlugin/Hooking/WindowsTitleMonitor.cs
new file mode 100644
index 000000000..5e0a05cf7
--- /dev/null
+++ b/GreenshotJiraPlugin/Hooking/WindowsTitleMonitor.cs
@@ -0,0 +1,139 @@
+/*
+ * dapplo - building blocks for desktop applications
+ * Copyright (C) Dapplo 2015-2016
+ *
+ * For more information see: http://dapplo.net/
+ * dapplo repositories are hosted on GitHub: https://github.com/dapplo
+ *
+ * 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;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.UnmanagedHelpers;
+
+namespace GreenshotJiraPlugin.Hooking
+{
+ ///
+ /// Monitor all title changes
+ ///
+ public sealed class WindowsTitleMonitor : IDisposable
+ {
+ private WindowsEventHook _hook;
+ private readonly object _lockObject = new object();
+ // ReSharper disable once InconsistentNaming
+ private event TitleChangeEventDelegate _titleChangeEvent;
+
+ ///
+ /// Add / remove event handler to the title monitor
+ ///
+ public event TitleChangeEventDelegate TitleChangeEvent
+ {
+ add
+ {
+ lock (_lockObject)
+ {
+ if (_hook == null)
+ {
+ _hook = new WindowsEventHook();
+ _hook.Hook(WinEvent.EVENT_OBJECT_NAMECHANGE, WinEventHandler);
+ }
+ _titleChangeEvent += value;
+ }
+ }
+ remove
+ {
+ lock (_lockObject)
+ {
+ _titleChangeEvent -= value;
+ if (_titleChangeEvent == null || _titleChangeEvent.GetInvocationList().Length == 0)
+ {
+ if (_hook != null)
+ {
+ _hook.Dispose();
+ _hook = null;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// WinEventDelegate for the creation & destruction
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void WinEventHandler(WinEvent eventType, IntPtr hWnd, EventObjects idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
+ {
+ if (hWnd == IntPtr.Zero || idObject != EventObjects.OBJID_WINDOW)
+ {
+ return;
+ }
+ if (eventType == WinEvent.EVENT_OBJECT_NAMECHANGE)
+ {
+ if (_titleChangeEvent != null)
+ {
+ string newTitle = new WindowDetails(hWnd).Text;
+ _titleChangeEvent(new TitleChangeEventArgs { HWnd = hWnd, Title = newTitle });
+ }
+ }
+ }
+
+ #region IDisposable Support
+
+ private bool _disposedValue; // To detect redundant calls
+
+ ///
+ /// Dispose the underlying hook
+ ///
+ public void Dispose(bool disposing)
+ {
+ if (_disposedValue)
+ {
+ return;
+ }
+ lock (_lockObject)
+ {
+ _hook?.Dispose();
+ }
+ _disposedValue = true;
+ }
+
+ ///
+ /// Make sure the finalizer disposes the underlying hook
+ ///
+ ~WindowsTitleMonitor()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(false);
+ }
+
+ ///
+ /// Dispose the underlying hook
+ ///
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+}
diff --git a/GreenshotJiraPlugin/IssueTypeBitmapCache.cs b/GreenshotJiraPlugin/IssueTypeBitmapCache.cs
new file mode 100644
index 000000000..b48173e8f
--- /dev/null
+++ b/GreenshotJiraPlugin/IssueTypeBitmapCache.cs
@@ -0,0 +1,55 @@
+/*
+ * 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 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
+ * 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;
+using System.Drawing;
+using System.Threading;
+using System.Threading.Tasks;
+using Dapplo.Jira;
+using Dapplo.Jira.Entities;
+
+namespace GreenshotJiraPlugin
+{
+ ///
+ /// This is the bach for the IssueType bitmaps
+ ///
+ public class IssueTypeBitmapCache : AsyncMemoryCache
+ {
+ private readonly JiraApi _jiraApi;
+
+ public IssueTypeBitmapCache(JiraApi jiraApi)
+ {
+ _jiraApi = jiraApi;
+ // Set the expire timeout to an hour
+ ExpireTimeSpan = TimeSpan.FromHours(4);
+ }
+
+ protected override string CreateKey(IssueType keyObject)
+ {
+ return keyObject.Name;
+ }
+
+ protected override async Task CreateAsync(IssueType issueType, CancellationToken cancellationToken = new CancellationToken())
+ {
+ return await _jiraApi.GetUriContentAsync(issueType.IconUri, cancellationToken).ConfigureAwait(false);
+ }
+ }
+}
diff --git a/GreenshotJiraPlugin/Jira.cs b/GreenshotJiraPlugin/Jira.cs
deleted file mode 100644
index cdaaae97a..000000000
--- a/GreenshotJiraPlugin/Jira.cs
+++ /dev/null
@@ -1,410 +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 Greenshot.IniFile;
-using GreenshotJiraPlugin;
-using GreenshotPlugin.Controls;
-using GreenshotPlugin.Core;
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using System.Windows.Forms;
-
-namespace Jira {
- #region transport classes
- public class JiraFilter {
- public JiraFilter(string name, string id) {
- this.Name = name;
- this.Id = id;
- }
- public string Name {
- get;
- set;
- }
- public string Id {
- get;
- set;
- }
- }
-
- public class JiraIssue {
- public JiraIssue(string key, DateTime? created, string reporter, string assignee, string project, string summary, string description, string environment, string [] attachmentNames) {
- this.Key = key;
- this.Created = created;
- this.Reporter = reporter;
- this.Assignee = assignee;
- this.Project = project;
- this.Summary = summary;
- this.Description = description;
- this.Environment = environment;
- this.AttachmentNames = attachmentNames;
- }
- public string Key {
- get;
- set;
- }
- public DateTime? Created {
- get;
- private set;
- }
- public string Reporter {
- get;
- private set;
- }
- public string Assignee {
- get;
- private set;
- }
- public string Project {
- get;
- private set;
- }
- public string Summary {
- get;
- private set;
- }
- public string Description {
- get;
- private set;
- }
- public string Environment {
- get;
- private set;
- }
- public string[] AttachmentNames {
- get;
- private set;
- }
- }
- #endregion
-
- public class JiraConnector : IDisposable {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(JiraConnector));
- private const string AUTH_FAILED_EXCEPTION_NAME = "com.atlassian.jira.rpc.exception.RemoteAuthenticationException";
- private static JiraConfiguration config = IniConfig.GetIniSection();
- public const string DEFAULT_POSTFIX = "/rpc/soap/jirasoapservice-v2?wsdl";
- private string credentials;
- private DateTime loggedInTime = DateTime.Now;
- private bool loggedIn;
- private JiraSoapServiceService jira;
- private int timeout;
- private string url;
- private Cache jiraCache = new Cache(60 * config.Timeout);
- private Cache userCache = new Cache(60 * config.Timeout);
- private bool suppressBackgroundForm = false;
-
- public void Dispose() {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing) {
- if (jira != null) {
- logout();
- }
-
- if (disposing) {
- if (jira != null) {
- jira.Dispose();
- jira = null;
- }
- }
- }
-
- public JiraConnector() : this(false) {
- }
-
- public JiraConnector(bool suppressBackgroundForm) {
- this.url = config.Url;
- this.timeout = config.Timeout;
- this.suppressBackgroundForm = suppressBackgroundForm;
- createService();
- }
-
- private void createService() {
- if (!suppressBackgroundForm) {
- new PleaseWaitForm().ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait),
- delegate() {
- jira = new JiraSoapServiceService();
- }
- );
- } else {
- jira = new JiraSoapServiceService();
- }
- jira.Url = url;
- jira.Proxy = NetworkHelper.CreateProxy(new Uri(url));
- // Do not use:
- //jira.AllowAutoRedirect = true;
- jira.UserAgent = "Greenshot";
- }
-
- ~JiraConnector() {
- Dispose(false);
- }
-
- ///
- /// Internal login which catches the exceptions
- ///
- /// true if login was done sucessfully
- private bool doLogin(string user, string password, bool suppressBackgroundForm) {
-
- // This is what needs to be done
- ThreadStart jiraLogin = delegate {
- LOG.DebugFormat("Loggin in");
- try {
- this.credentials = jira.login(user, password);
- } catch (Exception) {
- if (!url.EndsWith("wsdl")) {
- url = url + "/rpc/soap/jirasoapservice-v2?wsdl";
- // recreate the service with the new url
- createService();
- this.credentials = jira.login(user, password);
- // Worked, store the url in the configuration
- config.Url = url;
- IniConfig.Save();
- } else {
- throw;
- }
- }
-
- LOG.DebugFormat("Logged in");
- this.loggedInTime = DateTime.Now;
- this.loggedIn = true;
-
- };
- // Here we do it
- try {
- if (!suppressBackgroundForm) {
- new PleaseWaitForm().ShowAndWait(JiraPlugin.Instance.JiraPluginAttributes.Name, Language.GetString("jira", LangKey.communication_wait), jiraLogin);
- } else {
- jiraLogin.Invoke();
- }
- } catch (Exception e) {
- // check if auth failed
- if (e.Message.Contains(AUTH_FAILED_EXCEPTION_NAME)) {
- return false;
- }
- // Not an authentication issue
- this.loggedIn = false;
- this.credentials = null;
- e.Data.Add("user", user);
- e.Data.Add("url", url);
- throw;
- }
- return true;
- }
-
- public void login() {
- login(false);
- }
- public void login(bool suppressBackgroundForm) {
- logout();
- try {
- // Get the system name, so the user knows where to login to
- string systemName = url.Replace(DEFAULT_POSTFIX,"");
- CredentialsDialog dialog = new CredentialsDialog(systemName);
- dialog.Name = null;
- while (dialog.Show(dialog.Name) == DialogResult.OK) {
- if (doLogin(dialog.Name, dialog.Password, suppressBackgroundForm)) {
- if (dialog.SaveChecked) {
- dialog.Confirm(true);
- }
- return;
- } else {
- try {
- dialog.Confirm(false);
- } catch (ApplicationException e) {
- // exception handling ...
- LOG.Error("Problem using the credentials dialog", e);
- }
- // For every windows version after XP show an incorrect password baloon
- dialog.IncorrectPassword = true;
- // Make sure the dialog is display, the password was false!
- dialog.AlwaysDisplay = true;
- }
- }
- } catch (ApplicationException e) {
- // exception handling ...
- LOG.Error("Problem using the credentials dialog", e);
- }
- }
-
- public void logout() {
- if (credentials != null) {
- jira.logout(credentials);
- credentials = null;
- loggedIn = false;
- }
- }
-
- private void checkCredentials() {
- if (loggedIn) {
- if (loggedInTime.AddMinutes(timeout-1).CompareTo(DateTime.Now) < 0) {
- logout();
- login();
- }
- } else {
- login();
- }
- }
-
- public bool isLoggedIn {
- get {
- return loggedIn;
- }
- }
-
- public JiraFilter[] getFilters() {
- List filters = new List();
- checkCredentials();
- RemoteFilter[] remoteFilters = jira.getSavedFilters(credentials);
- foreach (RemoteFilter remoteFilter in remoteFilters) {
- filters.Add(new JiraFilter(remoteFilter.name, remoteFilter.id));
- }
- return filters.ToArray();
- }
-
- private JiraIssue createDummyErrorIssue(Exception e) {
- // Creating bogus jira to indicate a problem
- return new JiraIssue("error", DateTime.Now, "error", "error", "error", e.Message, "error", "error", null);
- }
-
- public JiraIssue getIssue(string key) {
- JiraIssue jiraIssue = null;
- if (jiraCache.Contains(key)) {
- jiraIssue = jiraCache[key];
- }
- if (jiraIssue == null) {
- checkCredentials();
- try {
- RemoteIssue issue = jira.getIssue(credentials, key);
- jiraIssue = new JiraIssue(issue.key, issue.created, getUserFullName(issue.reporter), getUserFullName(issue.assignee), issue.project, issue.summary, issue.description, issue.environment, issue.attachmentNames);
- jiraCache.Add(key, jiraIssue);
- } catch (Exception e) {
- LOG.Error("Problem retrieving Jira: " + key, e);
- }
- }
- return jiraIssue;
- }
-
- public JiraIssue[] getIssuesForFilter(string filterId) {
- List issuesToReturn = new List();
- checkCredentials();
- try {
- RemoteIssue[] issues = jira.getIssuesFromFilter(credentials, filterId);
-
- #region Username cache update
- List users = new List();
- foreach (RemoteIssue issue in issues) {
- if (issue.reporter != null && !hasUser(issue.reporter) && !users.Contains(issue.reporter)) {
- users.Add(issue.reporter);
- }
- if (issue.assignee != null && !hasUser(issue.assignee) && !users.Contains(issue.assignee)) {
- users.Add(issue.assignee);
- }
- }
- int taskCount = users.Count;
- if (taskCount > 0) {
- ManualResetEvent doneEvent = new ManualResetEvent(false);
- for (int i = 0; i < users.Count; i++) {
- ThreadPool.QueueUserWorkItem(delegate(object name) {
- LOG.InfoFormat("Retrieving {0}", name);
- getUserFullName((string)name);
- if (Interlocked.Decrement(ref taskCount) == 0) {
- doneEvent.Set();
- }
- }, users[i]);
- }
- doneEvent.WaitOne();
- }
- #endregion
-
- foreach (RemoteIssue issue in issues) {
- try {
- JiraIssue jiraIssue = new JiraIssue(issue.key, issue.created, getUserFullName(issue.reporter), getUserFullName(issue.assignee), issue.project, issue.summary, issue.description, "", issue.attachmentNames);
- issuesToReturn.Add(jiraIssue);
- } catch (Exception e) {
- LOG.Error("Problem retrieving Jira: " + issue.key, e);
- JiraIssue jiraIssue = createDummyErrorIssue(e);
- jiraIssue.Key = issue.key;
- issuesToReturn.Add(jiraIssue);
- }
- }
- } catch (Exception e) {
- LOG.Error("Problem retrieving Jiras for Filter: " + filterId, e);
- issuesToReturn.Add(createDummyErrorIssue(e));
- }
- return issuesToReturn.ToArray(); ;
- }
-
- public string getURL(string issueKey) {
- return url.Replace(DEFAULT_POSTFIX,"") + "/browse/" + issueKey;
- }
-
- public void addAttachment(string issueKey, string filename, IBinaryContainer attachment) {
- checkCredentials();
- try {
- jira.addBase64EncodedAttachmentsToIssue(credentials, issueKey, new string[] { filename }, new string[] { attachment.ToBase64String(Base64FormattingOptions.InsertLineBreaks) });
- } catch (Exception ex1) {
- LOG.WarnFormat("Failed to upload by using method addBase64EncodedAttachmentsToIssue, error was {0}", ex1.Message);
- try {
- LOG.Warn("Trying addAttachmentsToIssue instead");
- jira.addAttachmentsToIssue(credentials, issueKey, new string[] { filename }, (sbyte[])(Array)attachment.ToByteArray());
- } catch (Exception ex2) {
- LOG.WarnFormat("Failed to use alternative method, error was: {0}", ex2.Message);
- throw;
- }
- }
- }
-
- public void addComment(string issueKey, string commentString) {
- RemoteComment comment = new RemoteComment();
- comment.body = commentString;
- checkCredentials();
- jira.addComment(credentials, issueKey, comment);
- }
-
- private bool hasUser(string user) {
- if (user != null) {
- return userCache.Contains(user);
- }
- return false;
- }
-
- private string getUserFullName(string user) {
- string fullname = null;
- if (user != null) {
- if (userCache.Contains(user)) {
- fullname = userCache[user].fullname;
- } else {
- checkCredentials();
- RemoteUser remoteUser = jira.getUser(credentials, user);
- userCache.Add(user, remoteUser);
- fullname = remoteUser.fullname;
- }
- } else {
- fullname = "Not assigned";
- }
- return fullname;
- }
- }
-}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/JiraConfiguration.cs b/GreenshotJiraPlugin/JiraConfiguration.cs
index 1ebb03186..8674aeaa4 100644
--- a/GreenshotJiraPlugin/JiraConfiguration.cs
+++ b/GreenshotJiraPlugin/JiraConfiguration.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,7 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-using System.Windows.Forms;
+
using Greenshot.IniFile;
using GreenshotPlugin.Core;
@@ -28,35 +28,22 @@ namespace GreenshotJiraPlugin {
///
[IniSection("Jira", Description="Greenshot Jira Plugin configuration")]
public class JiraConfiguration : IniSection {
- public const string DEFAULT_PREFIX = "http://";
- private const string DEFAULT_URL = DEFAULT_PREFIX + "jira" + Jira.JiraConnector.DEFAULT_POSTFIX;
+ public const string DefaultPrefix = "http://";
+ private const string DefaultUrl = DefaultPrefix + "jira";
+
+ [IniProperty("Url", Description="Base url to Jira system, without anything else", DefaultValue=DefaultUrl)]
+ public string Url { get; set; }
- [IniProperty("Url", Description="Url to Jira system, including wsdl.", DefaultValue=DEFAULT_URL)]
- public string Url;
[IniProperty("Timeout", Description="Session timeout in minutes", DefaultValue="30")]
- public int Timeout;
-
- [IniProperty("LastUsedJira", Description="Last used Jira")]
- public string LastUsedJira;
+ public int Timeout { get; set; }
[IniProperty("UploadFormat", Description="What file type to use for uploading", DefaultValue="png")]
- public OutputFormat UploadFormat;
- [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
- public int UploadJpegQuality;
- [IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")]
- public bool UploadReduceColors;
+ public OutputFormat UploadFormat { get; set; }
- ///
- /// A form for username/password
- ///
- /// bool true if OK was pressed, false if cancel
- public bool ShowConfigDialog() {
- SettingsForm settingsForm = new SettingsForm(this);
- DialogResult result = settingsForm.ShowDialog();
- if (result == DialogResult.OK) {
- return true;
- }
- return false;
- }
+ [IniProperty("UploadJpegQuality", Description="JPEG file save quality in %.", DefaultValue="80")]
+ public int UploadJpegQuality { get; set; }
+
+ [IniProperty("UploadReduceColors", Description="Reduce color amount of the uploaded image to 256", DefaultValue="False")]
+ public bool UploadReduceColors { get; set; }
}
}
diff --git a/GreenshotJiraPlugin/JiraConnector.cs b/GreenshotJiraPlugin/JiraConnector.cs
new file mode 100644
index 000000000..ee9e98a2f
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraConnector.cs
@@ -0,0 +1,302 @@
+
+/*
+ * 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 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
+ * 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;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using Dapplo.HttpExtensions;
+using Dapplo.Jira;
+using Dapplo.Jira.Entities;
+using Greenshot.IniFile;
+using GreenshotPlugin.Core;
+
+namespace GreenshotJiraPlugin {
+ ///
+ /// This encapsulates the JiraApi to make it possible to change as less old Greenshot code as needed
+ ///
+ public class JiraConnector : IDisposable {
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraConnector));
+ private static readonly JiraConfiguration JiraConfig = IniConfig.GetIniSection();
+ private static readonly CoreConfiguration CoreConfig = IniConfig.GetIniSection();
+ // Used to remove the wsdl information from the old SOAP Uri
+ public const string DefaultPostfix = "/rpc/soap/jirasoapservice-v2?wsdl";
+ private DateTimeOffset _loggedInTime = DateTimeOffset.MinValue;
+ private bool _loggedIn;
+ private readonly int _timeout;
+ private JiraApi _jiraApi;
+ private IssueTypeBitmapCache _issueTypeBitmapCache;
+ private static readonly SvgBitmapHttpContentConverter SvgBitmapHttpContentConverterInstance = new SvgBitmapHttpContentConverter();
+
+ ///
+ /// Initialize some basic stuff, in the case the SVG to bitmap converter
+ ///
+ static JiraConnector()
+ {
+ if (HttpExtensionsGlobals.HttpContentConverters.All(x => x.GetType() != typeof(SvgBitmapHttpContentConverter)))
+ {
+ HttpExtensionsGlobals.HttpContentConverters.Add(SvgBitmapHttpContentConverterInstance);
+ }
+ SvgBitmapHttpContentConverterInstance.Width = CoreConfig.IconSize.Width;
+ SvgBitmapHttpContentConverterInstance.Height = CoreConfig.IconSize.Height;
+ CoreConfig.PropertyChanged += (sender, args) =>
+ {
+ if (args.PropertyName == nameof(CoreConfig.IconSize))
+ {
+ SvgBitmapHttpContentConverterInstance.Width = CoreConfig.IconSize.Width;
+ SvgBitmapHttpContentConverterInstance.Height = CoreConfig.IconSize.Height;
+ }
+ };
+
+ }
+
+ ///
+ /// Dispose, logout the users
+ ///
+ public void Dispose() {
+ if (_jiraApi != null)
+ {
+ Task.Run(async () => await LogoutAsync()).Wait();
+ }
+ FavIcon?.Dispose();
+ }
+
+ ///
+ /// Constructor
+ ///
+ public JiraConnector()
+ {
+ JiraConfig.Url = JiraConfig.Url.Replace(DefaultPostfix, "");
+ _timeout = JiraConfig.Timeout;
+ }
+
+ ///
+ /// Access the jira monitor
+ ///
+ public JiraMonitor Monitor { get; private set; }
+
+ public Bitmap FavIcon { get; private set; }
+
+ ///
+ /// Internal login which catches the exceptions
+ ///
+ /// true if login was done sucessfully
+ private async Task DoLoginAsync(string user, string password)
+ {
+ if (string.IsNullOrEmpty(user) || string.IsNullOrEmpty(password))
+ {
+ return false;
+ }
+ _jiraApi = new JiraApi(new Uri(JiraConfig.Url));
+ _issueTypeBitmapCache = new IssueTypeBitmapCache(_jiraApi);
+ LoginInfo loginInfo;
+ try
+ {
+ loginInfo = await _jiraApi.StartSessionAsync(user, password);
+ Monitor = new JiraMonitor();
+ await Monitor.AddJiraInstanceAsync(_jiraApi);
+
+ var favIconUri = _jiraApi.JiraBaseUri.AppendSegments("favicon.ico");
+ try
+ {
+ FavIcon = await _jiraApi.GetUriContentAsync(favIconUri);
+ }
+ catch (Exception ex)
+ {
+ Log.WarnFormat("Couldn't load favicon from {0}", favIconUri);
+ Log.Warn("Exception details: ", ex);
+ }
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+ return loginInfo != null;
+ }
+
+ ///
+ /// Use the credentials dialog, this will show if there are not correct credentials.
+ /// If there are credentials, call the real login.
+ ///
+ /// Task
+ public async Task LoginAsync() {
+ await LogoutAsync();
+ try {
+ // Get the system name, so the user knows where to login to
+ var credentialsDialog = new CredentialsDialog(JiraConfig.Url)
+ {
+ Name = null
+ };
+ while (credentialsDialog.Show(credentialsDialog.Name) == DialogResult.OK) {
+ if (await DoLoginAsync(credentialsDialog.Name, credentialsDialog.Password)) {
+ if (credentialsDialog.SaveChecked) {
+ credentialsDialog.Confirm(true);
+ }
+ _loggedIn = true;
+ _loggedInTime = DateTime.Now;
+ return;
+ }
+ // Login failed, confirm this
+ try {
+ credentialsDialog.Confirm(false);
+ } catch (ApplicationException e) {
+ // exception handling ...
+ Log.Error("Problem using the credentials dialog", e);
+ }
+ // For every windows version after XP show an incorrect password baloon
+ credentialsDialog.IncorrectPassword = true;
+ // Make sure the dialog is display, the password was false!
+ credentialsDialog.AlwaysDisplay = true;
+ }
+ } catch (ApplicationException e) {
+ // exception handling ...
+ Log.Error("Problem using the credentials dialog", e);
+ }
+
+ }
+
+ ///
+ /// End the session, if there was one
+ ///
+ public async Task LogoutAsync() {
+ if (_jiraApi != null && _loggedIn)
+ {
+ Monitor.Dispose();
+ await _jiraApi.EndSessionAsync();
+ _loggedIn = false;
+ }
+ }
+
+ ///
+ /// check the login credentials, to prevent timeouts of the session, or makes a login
+ /// Do not use ConfigureAwait to call this, as it will move await from the UI thread.
+ ///
+ ///
+ private async Task CheckCredentialsAsync() {
+ if (_loggedIn) {
+ if (_loggedInTime.AddMinutes(_timeout-1).CompareTo(DateTime.Now) < 0) {
+ await LogoutAsync();
+ await LoginAsync();
+ }
+ } else {
+ await LoginAsync();
+ }
+ }
+
+ ///
+ /// Get the favourite filters
+ ///
+ /// List with filters
+ public async Task> GetFavoriteFiltersAsync()
+ {
+ await CheckCredentialsAsync();
+ return await _jiraApi.GetFavoriteFiltersAsync().ConfigureAwait(false);
+ }
+
+ ///
+ /// Get the issue for a key
+ ///
+ /// Jira issue key
+ /// Issue
+ public async Task GetIssueAsync(string issueKey)
+ {
+ await CheckCredentialsAsync();
+ try
+ {
+ return await _jiraApi.GetIssueAsync(issueKey).ConfigureAwait(false);
+ }
+ catch
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Attach the content to the jira
+ ///
+ ///
+ /// IBinaryContainer
+ ///
+ ///
+ public async Task AttachAsync(string issueKey, IBinaryContainer content, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await CheckCredentialsAsync();
+ using (var memoryStream = new MemoryStream())
+ {
+ content.WriteToStream(memoryStream);
+ memoryStream.Seek(0, SeekOrigin.Begin);
+ await _jiraApi.AttachAsync(issueKey, memoryStream, content.Filename, content.ContentType, cancellationToken).ConfigureAwait(false);
+ }
+ }
+
+ ///
+ /// Add a comment to the supplied issue
+ ///
+ /// Jira issue key
+ /// text
+ /// the visibility role
+ /// CancellationToken
+ public async Task AddCommentAsync(string issueKey, string body, string visibility = null, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await CheckCredentialsAsync();
+ await _jiraApi.AddCommentAsync(issueKey, body, visibility, cancellationToken).ConfigureAwait(false);
+ }
+
+ ///
+ /// Get the search results for the specified filter
+ ///
+ /// Filter
+ ///
+ ///
+ public async Task> SearchAsync(Filter filter, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ await CheckCredentialsAsync();
+ var searchResult = await _jiraApi.SearchAsync(filter.Jql, 20, new[] { "summary", "reporter", "assignee", "created", "issuetype" }, cancellationToken).ConfigureAwait(false);
+ return searchResult.Issues;
+ }
+
+ ///
+ /// Get the bitmap representing the issue type of an issue, from cache.
+ ///
+ /// Issue
+ /// CancellationToken
+ /// Bitmap
+ public async Task GetIssueTypeBitmapAsync(Issue issue, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return await _issueTypeBitmapCache.GetOrCreateAsync(issue.Fields.IssueType, cancellationToken).ConfigureAwait(false);
+ }
+
+ ///
+ /// Get the base uri
+ ///
+ public Uri JiraBaseUri => _jiraApi.JiraBaseUri;
+
+ ///
+ /// Is the user "logged in?
+ ///
+ public bool IsLoggedIn => _loggedIn;
+ }
+}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/JiraDestination.cs b/GreenshotJiraPlugin/JiraDestination.cs
index bd443b37e..1b35e6fde 100644
--- a/GreenshotJiraPlugin/JiraDestination.cs
+++ b/GreenshotJiraPlugin/JiraDestination.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,126 +18,134 @@
* 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.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
+using Dapplo.HttpExtensions;
+using Dapplo.Jira.Entities;
using Greenshot.IniFile;
using Greenshot.Plugin;
+using GreenshotJiraPlugin.Forms;
using GreenshotPlugin.Controls;
using GreenshotPlugin.Core;
-using Jira;
namespace GreenshotJiraPlugin {
///
/// Description of JiraDestination.
///
public class JiraDestination : AbstractDestination {
- private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(JiraDestination));
- private static JiraConfiguration config = IniConfig.GetIniSection();
- private JiraPlugin jiraPlugin = null;
- private JiraIssue jira = null;
+ private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(typeof(JiraDestination));
+ private static readonly JiraConfiguration Config = IniConfig.GetIniSection();
+ private readonly JiraPlugin _jiraPlugin;
+ private readonly Issue _jiraIssue;
public JiraDestination(JiraPlugin jiraPlugin) {
- this.jiraPlugin = jiraPlugin;
+ _jiraPlugin = jiraPlugin;
}
- public JiraDestination(JiraPlugin jiraPlugin, JiraIssue jira) {
- this.jiraPlugin = jiraPlugin;
- this.jira = jira;
+ public JiraDestination(JiraPlugin jiraPlugin, Issue jiraIssue) {
+ _jiraPlugin = jiraPlugin;
+ _jiraIssue = jiraIssue;
}
- public override string Designation {
- get {
- return "Jira";
- }
- }
-
- private string FormatUpload(JiraIssue jira) {
- return Designation + " - " + jira.Key + ": " + jira.Summary.Substring(0, Math.Min(20, jira.Summary.Length));
- }
+ public override string Designation => "Jira";
public override string Description {
- get {
- if (jira == null) {
+ get
+ {
+ if (_jiraIssue?.Fields?.Summary == null) {
return Language.GetString("jira", LangKey.upload_menu_item);
- } else {
- return FormatUpload(jira);
}
+ // Format the title of this destination
+ return _jiraIssue.Key + ": " + _jiraIssue.Fields.Summary.Substring(0, Math.Min(20, _jiraIssue.Fields.Summary.Length));
}
}
- public override bool isActive {
- get {
- return base.isActive && !string.IsNullOrEmpty(config.Url);
- }
- }
+ public override bool IsActive => base.IsActive && !string.IsNullOrEmpty(Config.Url);
+
+ public override bool IsDynamic => true;
- public override bool isDynamic {
- get {
- return true;
- }
- }
public override Image DisplayIcon {
- get {
- ComponentResourceManager resources = new ComponentResourceManager(typeof(JiraPlugin));
- return (Image)resources.GetObject("Jira");
+ get
+ {
+ Image displayIcon = null;
+ var jiraConnector = JiraPlugin.Instance.CurrentJiraConnector;
+ if (jiraConnector != null)
+ {
+ if (_jiraIssue != null)
+ {
+ displayIcon = jiraConnector.GetIssueTypeBitmapAsync(_jiraIssue).Result;
+ }
+ else
+ {
+ displayIcon = jiraConnector.FavIcon;
+ }
+ }
+ if (displayIcon == null)
+ {
+ var resources = new ComponentResourceManager(typeof(JiraPlugin));
+ displayIcon = (Image)resources.GetObject("Jira");
+ }
+ return displayIcon;
}
}
- public override IEnumerable DynamicDestinations() {
- if (JiraPlugin.Instance.CurrentJiraConnector == null || !JiraPlugin.Instance.CurrentJiraConnector.isLoggedIn) {
+ public override IEnumerable DynamicDestinations()
+ {
+ var jiraConnector = JiraPlugin.Instance.CurrentJiraConnector;
+ if (jiraConnector == null || !jiraConnector.IsLoggedIn) {
yield break;
}
- List issues = JiraUtils.GetCurrentJiras();
- if (issues != null) {
- foreach(JiraIssue jiraIssue in issues) {
- yield return new JiraDestination(jiraPlugin, jiraIssue);
- }
+ foreach(var jiraDetails in jiraConnector.Monitor.RecentJiras)
+ {
+ yield return new JiraDestination(_jiraPlugin,jiraDetails.JiraIssue);
}
}
public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surfaceToUpload, ICaptureDetails captureDetails) {
- ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description);
- string filename = Path.GetFileName(FilenameHelper.GetFilename(config.UploadFormat, captureDetails));
- SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(config.UploadFormat, config.UploadJpegQuality, config.UploadReduceColors);
- if (jira != null) {
+ ExportInformation exportInformation = new ExportInformation(Designation, Description);
+ string filename = Path.GetFileName(FilenameHelper.GetFilename(Config.UploadFormat, captureDetails));
+ SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(Config.UploadFormat, Config.UploadJpegQuality, Config.UploadReduceColors);
+ if (_jiraIssue != null) {
try {
// Run upload in the background
new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait),
- delegate() {
- jiraPlugin.JiraConnector.addAttachment(jira.Key, filename, new SurfaceContainer(surfaceToUpload, outputSettings, filename));
+ async () =>
+ {
+ var surfaceContainer = new SurfaceContainer(surfaceToUpload, outputSettings, filename);
+ await _jiraPlugin.JiraConnector.AttachAsync(_jiraIssue.Key, surfaceContainer);
+ surfaceToUpload.UploadUrl = _jiraPlugin.JiraConnector.JiraBaseUri.AppendSegments("browse", _jiraIssue.Key).AbsoluteUri;
}
);
- LOG.Debug("Uploaded to Jira.");
+ Log.DebugFormat("Uploaded to Jira {0}", _jiraIssue.Key);
exportInformation.ExportMade = true;
- // TODO: This can't work:
- exportInformation.Uri = surfaceToUpload.UploadURL;
+ exportInformation.Uri = surfaceToUpload.UploadUrl;
} catch (Exception e) {
MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message);
}
} else {
- JiraForm jiraForm = new JiraForm(jiraPlugin.JiraConnector);
- if (jiraPlugin.JiraConnector.isLoggedIn) {
- jiraForm.setFilename(filename);
- DialogResult result = jiraForm.ShowDialog();
- if (result == DialogResult.OK) {
- try {
- // Run upload in the background
- new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait),
- delegate() {
- jiraForm.upload(new SurfaceContainer(surfaceToUpload, outputSettings, filename));
- }
- );
- LOG.Debug("Uploaded to Jira.");
- exportInformation.ExportMade = true;
- // TODO: This can't work:
- exportInformation.Uri = surfaceToUpload.UploadURL;
- } catch(Exception e) {
- MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message);
- }
+ var jiraForm = new JiraForm(_jiraPlugin.JiraConnector);
+ jiraForm.SetFilename(filename);
+ var dialogResult = jiraForm.ShowDialog();
+ if (dialogResult == DialogResult.OK) {
+ try {
+ surfaceToUpload.UploadUrl = _jiraPlugin.JiraConnector.JiraBaseUri.AppendSegments("browse", jiraForm.GetJiraIssue().Key).AbsoluteUri;
+ // Run upload in the background
+ new PleaseWaitForm().ShowAndWait(Description, Language.GetString("jira", LangKey.communication_wait),
+ async () =>
+ {
+ await jiraForm.UploadAsync(new SurfaceContainer(surfaceToUpload, outputSettings, filename));
+ }
+ );
+ Log.DebugFormat("Uploaded to Jira {0}", jiraForm.GetJiraIssue().Key);
+ exportInformation.ExportMade = true;
+ exportInformation.Uri = surfaceToUpload.UploadUrl;
+ } catch(Exception e) {
+ MessageBox.Show(Language.GetString("jira", LangKey.upload_failure) + " " + e.Message);
}
}
}
diff --git a/GreenshotJiraPlugin/JiraDetails.cs b/GreenshotJiraPlugin/JiraDetails.cs
new file mode 100644
index 000000000..e03172873
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraDetails.cs
@@ -0,0 +1,71 @@
+/*
+ * 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 GitHub: https://github.com/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;
+using Dapplo.Jira.Entities;
+
+namespace GreenshotJiraPlugin
+{
+ public class JiraDetails : IComparable
+ {
+ public JiraDetails()
+ {
+ FirstSeenAt = SeenAt = DateTimeOffset.Now;
+ }
+
+ public string ProjectKey
+ {
+ get;
+ set;
+ }
+
+ public string Id
+ {
+ get;
+ set;
+ }
+
+ public string JiraKey => ProjectKey + "-" + Id;
+
+ public Issue JiraIssue
+ {
+ get;
+ set;
+ }
+
+ public DateTimeOffset FirstSeenAt
+ {
+ get;
+ private set;
+ }
+
+ public DateTimeOffset SeenAt
+ {
+ get;
+ set;
+ }
+
+ public int CompareTo(JiraDetails other)
+ {
+ return SeenAt.CompareTo(other.SeenAt);
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/JiraEventArgs.cs b/GreenshotJiraPlugin/JiraEventArgs.cs
new file mode 100644
index 000000000..cbe7caa0d
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraEventArgs.cs
@@ -0,0 +1,40 @@
+/*
+ * 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 GitHub: https://github.com/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;
+
+namespace GreenshotJiraPlugin
+{
+ public class JiraEventArgs : EventArgs
+ {
+ public JiraEventTypes EventType
+ {
+ get;
+ set;
+ }
+
+ public JiraDetails Details
+ {
+ get;
+ set;
+ }
+ }
+}
diff --git a/GreenshotJiraPlugin/JiraEventTypes.cs b/GreenshotJiraPlugin/JiraEventTypes.cs
new file mode 100644
index 000000000..06b95db22
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraEventTypes.cs
@@ -0,0 +1,29 @@
+/*
+ * 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 GitHub: https://github.com/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 .
+ */
+
+namespace GreenshotJiraPlugin
+{
+ public enum JiraEventTypes
+ {
+ OrderChanged,
+ DetectedNewJiraIssue
+ }
+}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/JiraMonitor.cs b/GreenshotJiraPlugin/JiraMonitor.cs
new file mode 100644
index 000000000..81605bddf
--- /dev/null
+++ b/GreenshotJiraPlugin/JiraMonitor.cs
@@ -0,0 +1,225 @@
+/*
+ * 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 GitHub: https://github.com/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;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using Dapplo.Jira;
+using Dapplo.Log.Facade;
+using GreenshotJiraPlugin.Hooking;
+
+namespace GreenshotJiraPlugin
+{
+
+ ///
+ /// This class will monitor all _jira activity by registering for title changes
+ /// It keeps a list of the last "accessed" jiras, and makes it easy to upload to one.
+ /// Make sure this is instanciated on the UI thread!
+ ///
+ public class JiraMonitor : IDisposable
+ {
+ private static readonly LogSource Log = new LogSource();
+ private readonly Regex _jiraKeyPattern = new Regex(@"[A-Z][A-Z0-9]+\-[0-9]+");
+ private readonly WindowsTitleMonitor _monitor;
+ private readonly IList _jiraInstances = new List();
+ private readonly IDictionary _projectJiraApiMap = new Dictionary();
+ private readonly int _maxEntries;
+ private IDictionary _recentJiras = new Dictionary();
+
+ ///
+ /// Register to this event to get events when new jira issues are detected
+ ///
+ public event EventHandler JiraEvent;
+
+ public JiraMonitor(int maxEntries = 40)
+ {
+ _maxEntries = maxEntries;
+ _monitor = new WindowsTitleMonitor();
+ _monitor.TitleChangeEvent += MonitorTitleChangeEvent;
+ }
+
+ #region Dispose
+
+ ///
+ /// Dispose
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Dispose all managed resources
+ ///
+ /// when true is passed all managed resources are disposed.
+ protected void Dispose(bool disposing)
+ {
+ if (!disposing)
+ {
+ return;
+ }
+ // free managed resources
+ _monitor.TitleChangeEvent -= MonitorTitleChangeEvent;
+ _monitor.Dispose();
+ // free native resources if there are any.
+ }
+
+ #endregion
+
+ ///
+ /// Retrieve the API belonging to a JiraDetails
+ ///
+ ///
+ /// JiraAPI
+ public JiraApi GetJiraApiForKey(JiraDetails jiraDetails)
+ {
+ return _projectJiraApiMap[jiraDetails.ProjectKey];
+ }
+
+ ///
+ /// Get the "list" of recently seen Jiras
+ ///
+ public IEnumerable RecentJiras =>
+ (from jiraDetails in _recentJiras.Values
+ orderby jiraDetails.SeenAt descending
+ select jiraDetails);
+
+ ///
+ /// Check if this monitor has active instances
+ ///
+ public bool HasJiraInstances => _jiraInstances.Count > 0;
+
+ ///
+ /// Add an instance of a JIRA system
+ ///
+ ///
+ ///
+ public async Task AddJiraInstanceAsync(JiraApi jiraInstance, CancellationToken token = default(CancellationToken))
+ {
+ _jiraInstances.Add(jiraInstance);
+ var projects = await jiraInstance.GetProjectsAsync(token).ConfigureAwait(false);
+ if (projects != null)
+ {
+ foreach (var project in projects)
+ {
+ if (!_projectJiraApiMap.ContainsKey(project.Key))
+ {
+ _projectJiraApiMap.Add(project.Key, jiraInstance);
+ }
+ }
+ }
+ }
+
+ ///
+ /// This method will update details, like the title, and send an event to registed listeners of the JiraEvent
+ ///
+ /// Contains the jira key to retrieve the title (XYZ-1234)
+ /// Task
+ private async Task DetectedNewJiraIssueAsync(JiraDetails jiraDetails)
+ {
+ try
+ {
+ JiraApi jiraApi;
+ if (_projectJiraApiMap.TryGetValue(jiraDetails.ProjectKey, out jiraApi))
+ {
+ var issue = await jiraApi.GetIssueAsync(jiraDetails.JiraKey).ConfigureAwait(false);
+ jiraDetails.JiraIssue = issue;
+ }
+ // Send event
+ JiraEvent?.Invoke(this, new JiraEventArgs { Details = jiraDetails, EventType = JiraEventTypes.DetectedNewJiraIssue });
+ }
+ catch (Exception ex)
+ {
+ Log.Warn().WriteLine("Couldn't retrieve JIRA title: {0}", ex.Message);
+ }
+ }
+
+ ///
+ /// Handle title changes, check for JIRA
+ ///
+ ///
+ private void MonitorTitleChangeEvent(TitleChangeEventArgs eventArgs)
+ {
+ string windowTitle = eventArgs.Title;
+ if (string.IsNullOrEmpty(windowTitle))
+ {
+ return;
+ }
+ var jiraKeyMatch = _jiraKeyPattern.Match(windowTitle);
+ if (!jiraKeyMatch.Success)
+ {
+ return;
+ }
+ // Found a possible JIRA title
+ var jiraKey = jiraKeyMatch.Value;
+ var jiraKeyParts = jiraKey.Split('-');
+ var projectKey = jiraKeyParts[0];
+ var jiraId = jiraKeyParts[1];
+
+ JiraApi jiraApi;
+ // Check if we have a JIRA instance with a project for this key
+ if (_projectJiraApiMap.TryGetValue(projectKey, out jiraApi))
+ {
+ // We have found a project for this _jira key, so it must be a valid & known JIRA
+ JiraDetails currentJiraDetails;
+ if (_recentJiras.TryGetValue(jiraKey, out currentJiraDetails))
+ {
+ // update
+ currentJiraDetails.SeenAt = DateTimeOffset.Now;
+
+ // Notify the order change
+ JiraEvent?.Invoke(this, new JiraEventArgs { Details = currentJiraDetails, EventType = JiraEventTypes.OrderChanged });
+ // Nothing else to do
+
+ return;
+ }
+ // We detected an unknown JIRA, so add it to our list
+ currentJiraDetails = new JiraDetails
+ {
+ Id = jiraId,
+ ProjectKey = projectKey
+ };
+ _recentJiras.Add(currentJiraDetails.JiraKey, currentJiraDetails);
+
+ // Make sure we don't collect _jira's until the memory is full
+ if (_recentJiras.Count > _maxEntries)
+ {
+ // Add it to the list of recent Jiras
+ IList clonedList = new List(_recentJiras.Values);
+ _recentJiras = (from jiraDetails in clonedList
+ orderby jiraDetails.SeenAt descending
+ select jiraDetails).Take(_maxEntries).ToDictionary(jd => jd.JiraKey, jd => jd);
+ }
+ // Now we can get the title from JIRA itself
+ // ReSharper disable once UnusedVariable
+ var updateTitleTask = DetectedNewJiraIssueAsync(currentJiraDetails);
+ }
+ else
+ {
+ Log.Info().WriteLine("Couldn't match possible JIRA key {0} to projects in a configured JIRA instance, ignoring", projectKey);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/GreenshotJiraPlugin/JiraPlugin.cs b/GreenshotJiraPlugin/JiraPlugin.cs
index 18e6576b9..a7240293e 100644
--- a/GreenshotJiraPlugin/JiraPlugin.cs
+++ b/GreenshotJiraPlugin/JiraPlugin.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,54 +19,44 @@
* along with this program. If not, see .
*/
using System.Collections.Generic;
-using System.ComponentModel;
using System.Windows.Forms;
using Greenshot.IniFile;
using Greenshot.Plugin;
-using Jira;
using System;
+using System.Threading.Tasks;
+using Dapplo.Log.Facade;
+using GreenshotJiraPlugin.Forms;
+using GreenshotPlugin.Core;
+using log4net;
namespace GreenshotJiraPlugin {
///
/// This is the JiraPlugin base code
///
public class JiraPlugin : IGreenshotPlugin {
- private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(JiraPlugin));
- private PluginAttribute jiraPluginAttributes;
- private IGreenshotHost host;
- private JiraConnector jiraConnector = null;
- private JiraConfiguration config = null;
- private ComponentResourceManager resources;
- private static JiraPlugin instance = null;
+ private static readonly ILog Log = LogManager.GetLogger(typeof(JiraPlugin));
+ private JiraConfiguration _config;
+ private static JiraPlugin _instance;
+ private JiraConnector _jiraConnector;
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
- protected virtual void Dispose(bool disposing) {
+ protected void Dispose(bool disposing) {
if (disposing) {
- if (jiraConnector != null) {
- jiraConnector.Dispose();
- jiraConnector = null;
+ if (JiraConnector != null) {
+ JiraConnector.Dispose();
+ JiraConnector = null;
}
}
}
- public static JiraPlugin Instance {
- get {
- return instance;
- }
- }
+ public static JiraPlugin Instance => _instance;
public JiraPlugin() {
- instance = this;
- }
-
- public PluginAttribute JiraPluginAttributes {
- get {
- return jiraPluginAttributes;
- }
+ _instance = this;
}
public IEnumerable Destinations() {
@@ -78,69 +68,118 @@ namespace GreenshotJiraPlugin {
}
//Needed for a fail-fast
- public JiraConnector CurrentJiraConnector {
- get {
- return jiraConnector;
- }
- }
-
- public JiraConnector JiraConnector {
- get {
- if (jiraConnector == null) {
- jiraConnector = new JiraConnector(true);
+ public JiraConnector CurrentJiraConnector => JiraConnector;
+
+ public JiraConnector JiraConnector
+ {
+ get
+ {
+ lock (_instance)
+ {
+ if (_jiraConnector == null)
+ {
+ JiraConnector = new JiraConnector();
+ }
}
- return jiraConnector;
+ return _jiraConnector;
}
+ private set { _jiraConnector = value; }
}
///
/// Implementation of the IGreenshotPlugin.Initialize
///
- /// Use the IGreenshotPluginHost interface to register events
- /// Use the ICaptureHost interface to register in the MainContextMenu
- /// My own attributes
+ /// Use the IGreenshotPluginHost interface to register events
+ /// My own attributes
/// true if plugin is initialized, false if not (doesn't show)
- public virtual bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
- this.host = (IGreenshotHost)pluginHost;
- jiraPluginAttributes = myAttributes;
-
+ public bool Initialize(IGreenshotHost pluginHost, PluginAttribute myAttributes) {
// Register configuration (don't need the configuration itself)
- config = IniConfig.GetIniSection();
- resources = new ComponentResourceManager(typeof(JiraPlugin));
+ _config = IniConfig.GetIniSection();
+
+ // Make sure the loggin is enable for the corect level.
+ if (Log.IsDebugEnabled)
+ {
+ LogSettings.RegisterDefaultLogger(LogLevels.Verbose);
+ }
+ else if (Log.IsInfoEnabled)
+ {
+ LogSettings.RegisterDefaultLogger(LogLevels.Info);
+ }
+ else if (Log.IsWarnEnabled)
+ {
+ LogSettings.RegisterDefaultLogger(LogLevels.Warn);
+ }
+ else if (Log.IsErrorEnabled)
+ {
+ LogSettings.RegisterDefaultLogger(LogLevels.Error);
+ }
+ else if (Log.IsErrorEnabled)
+ {
+ LogSettings.RegisterDefaultLogger