mirror of
https://github.com/ShareX/ShareX.git
synced 2024-06-28 11:10:23 +12:00
Initial commit of ShareX project r748
This commit is contained in:
parent
e8c6c97f1d
commit
dba0ec79f8
26
CodeWorks.sln
Normal file
26
CodeWorks.sln
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 2012
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeWorks", "CodeWorks\CodeWorks.csproj", "{DE11B434-2D8D-4155-B150-72DF9F76FAB4}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelpersLib", "HelpersLib\HelpersLib.csproj", "{327750E1-9FB7-4CC3-8AEA-9BC42180CAD3}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{DE11B434-2D8D-4155-B150-72DF9F76FAB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DE11B434-2D8D-4155-B150-72DF9F76FAB4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DE11B434-2D8D-4155-B150-72DF9F76FAB4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DE11B434-2D8D-4155-B150-72DF9F76FAB4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{327750E1-9FB7-4CC3-8AEA-9BC42180CAD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{327750E1-9FB7-4CC3-8AEA-9BC42180CAD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{327750E1-9FB7-4CC3-8AEA-9BC42180CAD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{327750E1-9FB7-4CC3-8AEA-9BC42180CAD3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
134
CodeWorks/CodeWorks.csproj
Normal file
134
CodeWorks/CodeWorks.csproj
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>9.0.30729</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{DE11B434-2D8D-4155-B150-72DF9F76FAB4}</ProjectGuid>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>CodeWorks</RootNamespace>
|
||||||
|
<AssemblyName>CodeWorks</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<FileUpgradeFlags>
|
||||||
|
</FileUpgradeFlags>
|
||||||
|
<UpgradeBackupLocation>
|
||||||
|
</UpgradeBackupLocation>
|
||||||
|
<OldToolsVersion>3.5</OldToolsVersion>
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ApplicationRevision>0</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<Prefer32Bit>false</Prefer32Bit>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Xml.Linq">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Data.DataSetExtensions">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Deployment" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="Licenses\ShareXLicense.txt" />
|
||||||
|
<Compile Include="MainForm.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="MainForm.Designer.cs">
|
||||||
|
<DependentUpon>MainForm.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DesignTime>True</DesignTime>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="RegionArea.cs" />
|
||||||
|
<Compile Include="RegionAreaManager.cs" />
|
||||||
|
<Compile Include="TextInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="MainForm.resx">
|
||||||
|
<DependentUpon>MainForm.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Windows Installer 3.1</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\HelpersLib\HelpersLib.csproj">
|
||||||
|
<Project>{327750e1-9fb7-4cc3-8aea-9bc42180cad3}</Project>
|
||||||
|
<Name>HelpersLib</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
24
CodeWorks/Licenses/ShareXLicense.txt
Normal file
24
CodeWorks/Licenses/ShareXLicense.txt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#region License Information (GPL v3)
|
||||||
|
|
||||||
|
/*
|
||||||
|
ShareX - A program that allows you to take screenshots and share any file type
|
||||||
|
Copyright (C) 2008-2013 ShareX Developers
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endregion License Information (GPL v3)
|
302
CodeWorks/MainForm.Designer.cs
generated
Normal file
302
CodeWorks/MainForm.Designer.cs
generated
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
namespace CodeWorks
|
||||||
|
{
|
||||||
|
partial class MainForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.txtFolderPath = new System.Windows.Forms.TextBox();
|
||||||
|
this.btnSearch = new System.Windows.Forms.Button();
|
||||||
|
this.lvResults = new System.Windows.Forms.ListView();
|
||||||
|
this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
|
||||||
|
this.btnAddLicense = new System.Windows.Forms.Button();
|
||||||
|
this.btnAddLicenseAll = new System.Windows.Forms.Button();
|
||||||
|
this.scTextBoxes = new System.Windows.Forms.SplitContainer();
|
||||||
|
this.groupBox1 = new System.Windows.Forms.GroupBox();
|
||||||
|
this.tbDefaultText = new System.Windows.Forms.TextBox();
|
||||||
|
this.groupBox2 = new System.Windows.Forms.GroupBox();
|
||||||
|
this.btnCopyToClipboard = new System.Windows.Forms.Button();
|
||||||
|
this.tbNewText = new System.Windows.Forms.TextBox();
|
||||||
|
this.scMain = new System.Windows.Forms.SplitContainer();
|
||||||
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
|
this.lblFileCount = new System.Windows.Forms.Label();
|
||||||
|
this.btnFindRegionAreas = new System.Windows.Forms.Button();
|
||||||
|
this.btnOrderLines = new System.Windows.Forms.Button();
|
||||||
|
this.scTextBoxes.Panel1.SuspendLayout();
|
||||||
|
this.scTextBoxes.Panel2.SuspendLayout();
|
||||||
|
this.scTextBoxes.SuspendLayout();
|
||||||
|
this.groupBox1.SuspendLayout();
|
||||||
|
this.groupBox2.SuspendLayout();
|
||||||
|
this.scMain.Panel1.SuspendLayout();
|
||||||
|
this.scMain.Panel2.SuspendLayout();
|
||||||
|
this.scMain.SuspendLayout();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// txtFolderPath
|
||||||
|
//
|
||||||
|
this.txtFolderPath.Location = new System.Drawing.Point(72, 8);
|
||||||
|
this.txtFolderPath.Name = "txtFolderPath";
|
||||||
|
this.txtFolderPath.Size = new System.Drawing.Size(974, 20);
|
||||||
|
this.txtFolderPath.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// btnSearch
|
||||||
|
//
|
||||||
|
this.btnSearch.Location = new System.Drawing.Point(152, 40);
|
||||||
|
this.btnSearch.Name = "btnSearch";
|
||||||
|
this.btnSearch.Size = new System.Drawing.Size(136, 24);
|
||||||
|
this.btnSearch.TabIndex = 1;
|
||||||
|
this.btnSearch.Text = "Search (Old method)";
|
||||||
|
this.btnSearch.UseVisualStyleBackColor = true;
|
||||||
|
this.btnSearch.Click += new System.EventHandler(this.btnSearch_Click);
|
||||||
|
//
|
||||||
|
// lvResults
|
||||||
|
//
|
||||||
|
this.lvResults.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
|
||||||
|
this.columnHeader1});
|
||||||
|
this.lvResults.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.lvResults.FullRowSelect = true;
|
||||||
|
this.lvResults.GridLines = true;
|
||||||
|
this.lvResults.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
|
||||||
|
this.lvResults.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.lvResults.MultiSelect = false;
|
||||||
|
this.lvResults.Name = "lvResults";
|
||||||
|
this.lvResults.Size = new System.Drawing.Size(1040, 351);
|
||||||
|
this.lvResults.TabIndex = 2;
|
||||||
|
this.lvResults.UseCompatibleStateImageBehavior = false;
|
||||||
|
this.lvResults.View = System.Windows.Forms.View.Details;
|
||||||
|
this.lvResults.SelectedIndexChanged += new System.EventHandler(this.lvResults_SelectedIndexChanged);
|
||||||
|
//
|
||||||
|
// columnHeader1
|
||||||
|
//
|
||||||
|
this.columnHeader1.Width = 900;
|
||||||
|
//
|
||||||
|
// btnAddLicense
|
||||||
|
//
|
||||||
|
this.btnAddLicense.Location = new System.Drawing.Point(296, 40);
|
||||||
|
this.btnAddLicense.Name = "btnAddLicense";
|
||||||
|
this.btnAddLicense.Size = new System.Drawing.Size(80, 24);
|
||||||
|
this.btnAddLicense.TabIndex = 4;
|
||||||
|
this.btnAddLicense.Text = "Add license";
|
||||||
|
this.btnAddLicense.UseVisualStyleBackColor = true;
|
||||||
|
this.btnAddLicense.Click += new System.EventHandler(this.btnAddLicense_Click);
|
||||||
|
//
|
||||||
|
// btnAddLicenseAll
|
||||||
|
//
|
||||||
|
this.btnAddLicenseAll.Location = new System.Drawing.Point(384, 40);
|
||||||
|
this.btnAddLicenseAll.Name = "btnAddLicenseAll";
|
||||||
|
this.btnAddLicenseAll.Size = new System.Drawing.Size(112, 24);
|
||||||
|
this.btnAddLicenseAll.TabIndex = 5;
|
||||||
|
this.btnAddLicenseAll.Text = "Add license to all";
|
||||||
|
this.btnAddLicenseAll.UseVisualStyleBackColor = true;
|
||||||
|
this.btnAddLicenseAll.Click += new System.EventHandler(this.btnAddLicenseAll_Click);
|
||||||
|
//
|
||||||
|
// scTextBoxes
|
||||||
|
//
|
||||||
|
this.scTextBoxes.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.scTextBoxes.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.scTextBoxes.Name = "scTextBoxes";
|
||||||
|
//
|
||||||
|
// scTextBoxes.Panel1
|
||||||
|
//
|
||||||
|
this.scTextBoxes.Panel1.Controls.Add(this.groupBox1);
|
||||||
|
//
|
||||||
|
// scTextBoxes.Panel2
|
||||||
|
//
|
||||||
|
this.scTextBoxes.Panel2.Controls.Add(this.groupBox2);
|
||||||
|
this.scTextBoxes.Size = new System.Drawing.Size(1040, 346);
|
||||||
|
this.scTextBoxes.SplitterDistance = 501;
|
||||||
|
this.scTextBoxes.TabIndex = 6;
|
||||||
|
//
|
||||||
|
// groupBox1
|
||||||
|
//
|
||||||
|
this.groupBox1.Controls.Add(this.tbDefaultText);
|
||||||
|
this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.groupBox1.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.groupBox1.Name = "groupBox1";
|
||||||
|
this.groupBox1.Size = new System.Drawing.Size(501, 346);
|
||||||
|
this.groupBox1.TabIndex = 0;
|
||||||
|
this.groupBox1.TabStop = false;
|
||||||
|
this.groupBox1.Text = "Default text";
|
||||||
|
//
|
||||||
|
// tbDefaultText
|
||||||
|
//
|
||||||
|
this.tbDefaultText.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.tbDefaultText.Location = new System.Drawing.Point(3, 16);
|
||||||
|
this.tbDefaultText.Multiline = true;
|
||||||
|
this.tbDefaultText.Name = "tbDefaultText";
|
||||||
|
this.tbDefaultText.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
|
this.tbDefaultText.Size = new System.Drawing.Size(495, 327);
|
||||||
|
this.tbDefaultText.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// groupBox2
|
||||||
|
//
|
||||||
|
this.groupBox2.Controls.Add(this.btnCopyToClipboard);
|
||||||
|
this.groupBox2.Controls.Add(this.tbNewText);
|
||||||
|
this.groupBox2.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.groupBox2.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.groupBox2.Name = "groupBox2";
|
||||||
|
this.groupBox2.Size = new System.Drawing.Size(535, 346);
|
||||||
|
this.groupBox2.TabIndex = 0;
|
||||||
|
this.groupBox2.TabStop = false;
|
||||||
|
this.groupBox2.Text = "New text";
|
||||||
|
//
|
||||||
|
// btnCopyToClipboard
|
||||||
|
//
|
||||||
|
this.btnCopyToClipboard.Location = new System.Drawing.Point(384, 312);
|
||||||
|
this.btnCopyToClipboard.Name = "btnCopyToClipboard";
|
||||||
|
this.btnCopyToClipboard.Size = new System.Drawing.Size(115, 23);
|
||||||
|
this.btnCopyToClipboard.TabIndex = 2;
|
||||||
|
this.btnCopyToClipboard.Text = "Copy to clipboard";
|
||||||
|
this.btnCopyToClipboard.UseVisualStyleBackColor = true;
|
||||||
|
this.btnCopyToClipboard.Click += new System.EventHandler(this.btnCopyToClipboard_Click);
|
||||||
|
//
|
||||||
|
// tbNewText
|
||||||
|
//
|
||||||
|
this.tbNewText.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.tbNewText.Location = new System.Drawing.Point(3, 16);
|
||||||
|
this.tbNewText.Multiline = true;
|
||||||
|
this.tbNewText.Name = "tbNewText";
|
||||||
|
this.tbNewText.ScrollBars = System.Windows.Forms.ScrollBars.Both;
|
||||||
|
this.tbNewText.Size = new System.Drawing.Size(529, 327);
|
||||||
|
this.tbNewText.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// scMain
|
||||||
|
//
|
||||||
|
this.scMain.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.scMain.Location = new System.Drawing.Point(8, 72);
|
||||||
|
this.scMain.Name = "scMain";
|
||||||
|
this.scMain.Orientation = System.Windows.Forms.Orientation.Horizontal;
|
||||||
|
//
|
||||||
|
// scMain.Panel1
|
||||||
|
//
|
||||||
|
this.scMain.Panel1.Controls.Add(this.lvResults);
|
||||||
|
//
|
||||||
|
// scMain.Panel2
|
||||||
|
//
|
||||||
|
this.scMain.Panel2.Controls.Add(this.scTextBoxes);
|
||||||
|
this.scMain.Size = new System.Drawing.Size(1040, 704);
|
||||||
|
this.scMain.SplitterDistance = 351;
|
||||||
|
this.scMain.SplitterWidth = 7;
|
||||||
|
this.scMain.TabIndex = 7;
|
||||||
|
//
|
||||||
|
// label1
|
||||||
|
//
|
||||||
|
this.label1.AutoSize = true;
|
||||||
|
this.label1.Location = new System.Drawing.Point(8, 12);
|
||||||
|
this.label1.Name = "label1";
|
||||||
|
this.label1.Size = new System.Drawing.Size(63, 13);
|
||||||
|
this.label1.TabIndex = 8;
|
||||||
|
this.label1.Text = "Folder path:";
|
||||||
|
//
|
||||||
|
// lblFileCount
|
||||||
|
//
|
||||||
|
this.lblFileCount.AutoSize = true;
|
||||||
|
this.lblFileCount.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(162)));
|
||||||
|
this.lblFileCount.Location = new System.Drawing.Point(512, 44);
|
||||||
|
this.lblFileCount.Name = "lblFileCount";
|
||||||
|
this.lblFileCount.Size = new System.Drawing.Size(0, 16);
|
||||||
|
this.lblFileCount.TabIndex = 9;
|
||||||
|
//
|
||||||
|
// btnFindRegionAreas
|
||||||
|
//
|
||||||
|
this.btnFindRegionAreas.Location = new System.Drawing.Point(8, 40);
|
||||||
|
this.btnFindRegionAreas.Name = "btnFindRegionAreas";
|
||||||
|
this.btnFindRegionAreas.Size = new System.Drawing.Size(136, 24);
|
||||||
|
this.btnFindRegionAreas.TabIndex = 10;
|
||||||
|
this.btnFindRegionAreas.Text = "Search region areas";
|
||||||
|
this.btnFindRegionAreas.UseVisualStyleBackColor = true;
|
||||||
|
this.btnFindRegionAreas.Click += new System.EventHandler(this.btnFindRegionAreas_Click);
|
||||||
|
//
|
||||||
|
// btnOrderLines
|
||||||
|
//
|
||||||
|
this.btnOrderLines.Location = new System.Drawing.Point(912, 40);
|
||||||
|
this.btnOrderLines.Name = "btnOrderLines";
|
||||||
|
this.btnOrderLines.Size = new System.Drawing.Size(128, 24);
|
||||||
|
this.btnOrderLines.TabIndex = 11;
|
||||||
|
this.btnOrderLines.Text = "Clipboard lines A-Z";
|
||||||
|
this.btnOrderLines.UseVisualStyleBackColor = true;
|
||||||
|
this.btnOrderLines.Click += new System.EventHandler(this.btnOrderLines_Click);
|
||||||
|
//
|
||||||
|
// MainForm
|
||||||
|
//
|
||||||
|
this.AllowDrop = true;
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(1057, 785);
|
||||||
|
this.Controls.Add(this.btnOrderLines);
|
||||||
|
this.Controls.Add(this.btnFindRegionAreas);
|
||||||
|
this.Controls.Add(this.lblFileCount);
|
||||||
|
this.Controls.Add(this.label1);
|
||||||
|
this.Controls.Add(this.scMain);
|
||||||
|
this.Controls.Add(this.btnAddLicenseAll);
|
||||||
|
this.Controls.Add(this.btnAddLicense);
|
||||||
|
this.Controls.Add(this.btnSearch);
|
||||||
|
this.Controls.Add(this.txtFolderPath);
|
||||||
|
this.Name = "MainForm";
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||||
|
this.Text = "CodeWorks";
|
||||||
|
this.DragDrop += new System.Windows.Forms.DragEventHandler(this.MainForm_DragDrop);
|
||||||
|
this.DragEnter += new System.Windows.Forms.DragEventHandler(this.MainForm_DragEnter);
|
||||||
|
this.Resize += new System.EventHandler(this.MainForm_Resize);
|
||||||
|
this.scTextBoxes.Panel1.ResumeLayout(false);
|
||||||
|
this.scTextBoxes.Panel2.ResumeLayout(false);
|
||||||
|
this.scTextBoxes.ResumeLayout(false);
|
||||||
|
this.groupBox1.ResumeLayout(false);
|
||||||
|
this.groupBox1.PerformLayout();
|
||||||
|
this.groupBox2.ResumeLayout(false);
|
||||||
|
this.groupBox2.PerformLayout();
|
||||||
|
this.scMain.Panel1.ResumeLayout(false);
|
||||||
|
this.scMain.Panel2.ResumeLayout(false);
|
||||||
|
this.scMain.ResumeLayout(false);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.TextBox txtFolderPath;
|
||||||
|
private System.Windows.Forms.Button btnSearch;
|
||||||
|
private System.Windows.Forms.ListView lvResults;
|
||||||
|
private System.Windows.Forms.ColumnHeader columnHeader1;
|
||||||
|
private System.Windows.Forms.Button btnAddLicense;
|
||||||
|
private System.Windows.Forms.Button btnAddLicenseAll;
|
||||||
|
private System.Windows.Forms.SplitContainer scTextBoxes;
|
||||||
|
private System.Windows.Forms.GroupBox groupBox1;
|
||||||
|
private System.Windows.Forms.TextBox tbDefaultText;
|
||||||
|
private System.Windows.Forms.GroupBox groupBox2;
|
||||||
|
private System.Windows.Forms.TextBox tbNewText;
|
||||||
|
private System.Windows.Forms.SplitContainer scMain;
|
||||||
|
private System.Windows.Forms.Label label1;
|
||||||
|
private System.Windows.Forms.Label lblFileCount;
|
||||||
|
private System.Windows.Forms.Button btnFindRegionAreas;
|
||||||
|
private System.Windows.Forms.Button btnOrderLines;
|
||||||
|
private System.Windows.Forms.Button btnCopyToClipboard;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
280
CodeWorks/MainForm.cs
Normal file
280
CodeWorks/MainForm.cs
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
#region License Information (GPL v3)
|
||||||
|
|
||||||
|
/*
|
||||||
|
ShareX - A program that allows you to take screenshots and share any file type
|
||||||
|
Copyright (C) 2008-2013 ShareX Developers
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endregion License Information (GPL v3)
|
||||||
|
|
||||||
|
using CodeWorks.Properties;
|
||||||
|
using HelpersLib;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Media;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace CodeWorks
|
||||||
|
{
|
||||||
|
public partial class MainForm : Form
|
||||||
|
{
|
||||||
|
private readonly string folderPath = Path.GetFullPath(@"..\..\..\..\trunk");
|
||||||
|
private readonly string[] ignoreFolders = new string[] { "bin", "obj", "Properties", "GreenshotImageEditor", "AviFile" };
|
||||||
|
private readonly string[] ignoreFiles = new string[] { };
|
||||||
|
private readonly string[] ignoreFilenamesEndsWith = new string[] { ".designer.cs" };
|
||||||
|
private readonly string[] allowFilenamesEndsWith = new string[] { ".cs" };
|
||||||
|
private readonly string licenseText = Resources.ShareXLicense;
|
||||||
|
|
||||||
|
public MainForm()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
txtFolderPath.Text = folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnFindRegionAreas_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
lvResults.Items.Clear();
|
||||||
|
SearchFolderRegionAreas(txtFolderPath.Text);
|
||||||
|
lblFileCount.Text = lvResults.Items.Count + " files.";
|
||||||
|
SystemSounds.Exclamation.Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SearchFolderRegionAreas(string path)
|
||||||
|
{
|
||||||
|
if (IsValidFolder(path))
|
||||||
|
{
|
||||||
|
foreach (string folder in Directory.GetDirectories(path))
|
||||||
|
{
|
||||||
|
SearchFolderRegionAreas(folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string file in Directory.GetFiles(path))
|
||||||
|
{
|
||||||
|
CleanRegionAreas(file, "License Information (GPL v3)", licenseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CleanRegionAreas(string path, string searchRegionName, string newRegionText)
|
||||||
|
{
|
||||||
|
if (IsValidFile(path))
|
||||||
|
{
|
||||||
|
TextInfo info = new TextInfo(path);
|
||||||
|
RegionAreaManager regionAreaManager = new RegionAreaManager(info.DefaultText);
|
||||||
|
List<RegionArea> regionAreas = regionAreaManager.GetRegionAreas();
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
foreach (RegionArea regionArea in regionAreas)
|
||||||
|
{
|
||||||
|
if (regionArea.RegionName.IndexOf(searchRegionName, StringComparison.InvariantCultureIgnoreCase) >= 0)
|
||||||
|
{
|
||||||
|
regionArea.RegionIndexOffset = offset;
|
||||||
|
string regionAreaTextRemoved = regionArea.RemoveRegionText();
|
||||||
|
offset += -regionArea.RegionLength;
|
||||||
|
regionAreaManager.Text = regionAreaTextRemoved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info.NewText = newRegionText + "\r\n\r\n" + regionAreaManager.Text.Trim();
|
||||||
|
|
||||||
|
if (info.IsDifferent)
|
||||||
|
{
|
||||||
|
lvResults.Items.Add(path).Tag = info;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnSearch_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
lvResults.Items.Clear();
|
||||||
|
SearchFolder(txtFolderPath.Text);
|
||||||
|
lblFileCount.Text = lvResults.Items.Count + " files.";
|
||||||
|
SystemSounds.Exclamation.Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SearchFolder(string path)
|
||||||
|
{
|
||||||
|
if (IsValidFolder(path))
|
||||||
|
{
|
||||||
|
foreach (string folder in Directory.GetDirectories(path))
|
||||||
|
{
|
||||||
|
SearchFolder(folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string file in Directory.GetFiles(path))
|
||||||
|
{
|
||||||
|
CheckFile(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsValidFolder(string path)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
string foldername = Path.GetFileName(path).ToLowerInvariant();
|
||||||
|
return ignoreFolders.All(x => !foldername.Equals(x, StringComparison.InvariantCultureIgnoreCase)) && Directory.Exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsValidFile(string path)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(path))
|
||||||
|
{
|
||||||
|
string filename = Path.GetFileName(path).ToLowerInvariant();
|
||||||
|
return Path.HasExtension(filename) && allowFilenamesEndsWith.Any(x => filename.EndsWith(x)) &&
|
||||||
|
ignoreFiles.All(x => !filename.Equals(x, StringComparison.InvariantCultureIgnoreCase)) &&
|
||||||
|
ignoreFilenamesEndsWith.All(x => !filename.EndsWith(x)) && File.Exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool CheckFile(string path)
|
||||||
|
{
|
||||||
|
if (IsValidFile(path))
|
||||||
|
{
|
||||||
|
TextInfo info = new TextInfo(path);
|
||||||
|
info.NewText = CheckLicense(info.DefaultText);
|
||||||
|
// result = RemoveDuplicateLines(result);
|
||||||
|
|
||||||
|
if (info.IsDifferent)
|
||||||
|
{
|
||||||
|
lvResults.Items.Add(path).Tag = info;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string CheckLicense(string text)
|
||||||
|
{
|
||||||
|
if (!text.StartsWith(licenseText))
|
||||||
|
{
|
||||||
|
return text.Insert(0, licenseText + "\r\n\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string RemoveDuplicateLines(string text)
|
||||||
|
{
|
||||||
|
return Regex.Replace(text, @"(\r\n\s*){3,}", "\r\n\r\n", RegexOptions.Singleline);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lvResults_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (lvResults.SelectedItems.Count > 0)
|
||||||
|
{
|
||||||
|
TextInfo info = lvResults.SelectedItems[0].Tag as TextInfo;
|
||||||
|
|
||||||
|
if (info != null)
|
||||||
|
{
|
||||||
|
tbDefaultText.Text = info.DefaultText;
|
||||||
|
tbNewText.Text = info.NewText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnAddLicense_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (lvResults.SelectedItems.Count > 0)
|
||||||
|
{
|
||||||
|
TextInfo info = lvResults.SelectedItems[0].Tag as TextInfo;
|
||||||
|
|
||||||
|
if (info != null)
|
||||||
|
{
|
||||||
|
info.WriteNewText();
|
||||||
|
lvResults.Items.Remove(lvResults.SelectedItems[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnAddLicenseAll_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
foreach (ListViewItem lvi in lvResults.Items)
|
||||||
|
{
|
||||||
|
TextInfo info = lvi.Tag as TextInfo;
|
||||||
|
|
||||||
|
if (info != null)
|
||||||
|
{
|
||||||
|
info.WriteNewText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lvResults.Items.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MainForm_Resize(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MainForm_DragEnter(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
|
||||||
|
{
|
||||||
|
e.Effect = DragDropEffects.Copy;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e.Effect = DragDropEffects.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MainForm_DragDrop(object sender, DragEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
|
||||||
|
{
|
||||||
|
string[] files = e.Data.GetData(DataFormats.FileDrop, false) as string[];
|
||||||
|
txtFolderPath.Text = files[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnOrderLines_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
string clipboard = Clipboard.GetText();
|
||||||
|
clipboard = clipboard.Trim();
|
||||||
|
string[] lines = new StringLineReader(clipboard).ReadAllLines();
|
||||||
|
Array.Sort(lines);
|
||||||
|
string result = string.Join("\r\n", lines);
|
||||||
|
|
||||||
|
tbDefaultText.Text = clipboard;
|
||||||
|
tbNewText.Text = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void btnCopyToClipboard_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(tbNewText.Text))
|
||||||
|
{
|
||||||
|
Clipboard.SetText(tbNewText.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
120
CodeWorks/MainForm.resx
Normal file
120
CodeWorks/MainForm.resx
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
41
CodeWorks/Program.cs
Normal file
41
CodeWorks/Program.cs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#region License Information (GPL v3)
|
||||||
|
|
||||||
|
/*
|
||||||
|
ShareX - A program that allows you to take screenshots and share any file type
|
||||||
|
Copyright (C) 2008-2013 ShareX Developers
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endregion License Information (GPL v3)
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace CodeWorks
|
||||||
|
{
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
private static void Main()
|
||||||
|
{
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
Application.Run(new MainForm());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
CodeWorks/Properties/AssemblyInfo.cs
Normal file
35
CodeWorks/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("CodeWorks")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("ShareX Developers")]
|
||||||
|
[assembly: AssemblyProduct("CodeWorks")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright (C) 2012 ShareX Developers")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("3c399454-8486-40f9-b65c-24b23909c368")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.180")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
84
CodeWorks/Properties/Resources.Designer.cs
generated
Normal file
84
CodeWorks/Properties/Resources.Designer.cs
generated
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <auto-generated>
|
||||||
|
// This code was generated by a tool.
|
||||||
|
// Runtime Version:4.0.30319.18047
|
||||||
|
//
|
||||||
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
|
// the code is regenerated.
|
||||||
|
// </auto-generated>
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
namespace CodeWorks.Properties {
|
||||||
|
using System;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||||
|
/// </summary>
|
||||||
|
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||||
|
// class via a tool like ResGen or Visual Studio.
|
||||||
|
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||||
|
// with the /str option, or rebuild your VS project.
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||||
|
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
internal class Resources {
|
||||||
|
|
||||||
|
private static global::System.Resources.ResourceManager resourceMan;
|
||||||
|
|
||||||
|
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||||
|
|
||||||
|
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||||
|
internal Resources() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the cached ResourceManager instance used by this class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||||
|
get {
|
||||||
|
if (object.ReferenceEquals(resourceMan, null)) {
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CodeWorks.Properties.Resources", typeof(Resources).Assembly);
|
||||||
|
resourceMan = temp;
|
||||||
|
}
|
||||||
|
return resourceMan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overrides the current thread's CurrentUICulture property for all
|
||||||
|
/// resource lookups using this strongly typed resource class.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||||
|
internal static global::System.Globalization.CultureInfo Culture {
|
||||||
|
get {
|
||||||
|
return resourceCulture;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
resourceCulture = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to #region License Information (GPL v3)
|
||||||
|
///
|
||||||
|
////*
|
||||||
|
/// ShareX - A program that allows you to take screenshots and share any file type
|
||||||
|
/// Copyright (C) 2008-2013 ShareX Developers
|
||||||
|
///
|
||||||
|
/// 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 2
|
||||||
|
/// of the License, or (at your option) any later version.
|
||||||
|
///
|
||||||
|
/// This program is distributed in the hope that it will be useful,
|
||||||
|
/// [rest of string was truncated]";.
|
||||||
|
/// </summary>
|
||||||
|
internal static string ShareXLicense {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("ShareXLicense", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
124
CodeWorks/Properties/Resources.resx
Normal file
124
CodeWorks/Properties/Resources.resx
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||||
|
<data name="ShareXLicense" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\licenses\sharexlicense.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;windows-1254</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
79
CodeWorks/RegionArea.cs
Normal file
79
CodeWorks/RegionArea.cs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
#region License Information (GPL v3)
|
||||||
|
|
||||||
|
/*
|
||||||
|
ShareX - A program that allows you to take screenshots and share any file type
|
||||||
|
Copyright (C) 2008-2013 ShareX Developers
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endregion License Information (GPL v3)
|
||||||
|
|
||||||
|
namespace CodeWorks
|
||||||
|
{
|
||||||
|
public class RegionArea
|
||||||
|
{
|
||||||
|
public int RegionStartIndex { get; set; }
|
||||||
|
public int RegionEndIndex { get; set; }
|
||||||
|
|
||||||
|
public int RegionLength
|
||||||
|
{
|
||||||
|
get { return RegionEndIndex - RegionStartIndex + 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string RegionName { get; set; }
|
||||||
|
|
||||||
|
public int RegionIndexOffset { get; set; }
|
||||||
|
|
||||||
|
private RegionAreaManager manager;
|
||||||
|
|
||||||
|
public RegionArea(RegionAreaManager regionAreaManager)
|
||||||
|
{
|
||||||
|
manager = regionAreaManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RegionArea(RegionAreaManager regionAreaManager, int regionStartIndex)
|
||||||
|
: this(regionAreaManager)
|
||||||
|
{
|
||||||
|
RegionStartIndex = regionStartIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetRegionText()
|
||||||
|
{
|
||||||
|
return manager.Text.Substring(RegionStartIndex + RegionIndexOffset, RegionLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string RemoveRegionText()
|
||||||
|
{
|
||||||
|
return manager.Text.Remove(RegionStartIndex + RegionIndexOffset, RegionLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReplaceRegionText(string replaceWith)
|
||||||
|
{
|
||||||
|
string result = string.Empty;
|
||||||
|
|
||||||
|
if (RegionStartIndex + RegionIndexOffset > 0)
|
||||||
|
{
|
||||||
|
result = manager.Text.Substring(0, RegionStartIndex + RegionIndexOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
result += replaceWith + manager.Text.Substring(RegionEndIndex + RegionIndexOffset);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
85
CodeWorks/RegionAreaManager.cs
Normal file
85
CodeWorks/RegionAreaManager.cs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
#region License Information (GPL v3)
|
||||||
|
|
||||||
|
/*
|
||||||
|
ShareX - A program that allows you to take screenshots and share any file type
|
||||||
|
Copyright (C) 2008-2013 ShareX Developers
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endregion License Information (GPL v3)
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using HelpersLib;
|
||||||
|
|
||||||
|
namespace CodeWorks
|
||||||
|
{
|
||||||
|
public class RegionAreaManager
|
||||||
|
{
|
||||||
|
public string Text { get; set; }
|
||||||
|
public List<RegionArea> RegionAreas { get; private set; }
|
||||||
|
|
||||||
|
public RegionAreaManager(string text)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RegionArea> GetRegionAreas()
|
||||||
|
{
|
||||||
|
RegionAreas = new List<RegionArea>();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(Text))
|
||||||
|
{
|
||||||
|
bool searchingRegionStart = true;
|
||||||
|
|
||||||
|
StringLineReader reader = new StringLineReader(Text);
|
||||||
|
string line;
|
||||||
|
RegionArea regionArea = null;
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
while ((line = reader.ReadLine()) != null)
|
||||||
|
{
|
||||||
|
line = line.Trim();
|
||||||
|
|
||||||
|
if (searchingRegionStart)
|
||||||
|
{
|
||||||
|
if (line.StartsWith("#region", StringComparison.InvariantCulture))
|
||||||
|
{
|
||||||
|
searchingRegionStart = false;
|
||||||
|
regionArea = new RegionArea(this, index);
|
||||||
|
if (line.Length > 8) regionArea.RegionName = line.Substring(8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (line.StartsWith("#endregion", StringComparison.InvariantCulture))
|
||||||
|
{
|
||||||
|
searchingRegionStart = true;
|
||||||
|
regionArea.RegionEndIndex = reader.Position - 1;
|
||||||
|
RegionAreas.Add(regionArea);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
index = reader.Position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RegionAreas;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
58
CodeWorks/TextInfo.cs
Normal file
58
CodeWorks/TextInfo.cs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#region License Information (GPL v3)
|
||||||
|
|
||||||
|
/*
|
||||||
|
ShareX - A program that allows you to take screenshots and share any file type
|
||||||
|
Copyright (C) 2008-2013 ShareX Developers
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Optionally you can also view the license at <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#endregion License Information (GPL v3)
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CodeWorks
|
||||||
|
{
|
||||||
|
public class TextInfo
|
||||||
|
{
|
||||||
|
public string FilePath { get; set; }
|
||||||
|
public string DefaultText { get; set; }
|
||||||
|
public string NewText { get; set; }
|
||||||
|
|
||||||
|
public bool IsDifferent
|
||||||
|
{
|
||||||
|
get { return !string.IsNullOrEmpty(NewText) && DefaultText != NewText; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextInfo() { }
|
||||||
|
|
||||||
|
public TextInfo(string filePath)
|
||||||
|
{
|
||||||
|
FilePath = filePath;
|
||||||
|
DefaultText = File.ReadAllText(FilePath, Encoding.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteNewText()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(FilePath) && !string.IsNullOrEmpty(NewText) && File.Exists(FilePath))
|
||||||
|
{
|
||||||
|
File.WriteAllText(FilePath, NewText, Encoding.UTF8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
404
Docs/CodeMaid.settings
Normal file
404
Docs/CodeMaid.settings
Normal file
|
@ -0,0 +1,404 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<configSections>
|
||||||
|
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
|
||||||
|
<section name="SteveCadwallader.CodeMaid.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
|
||||||
|
</sectionGroup>
|
||||||
|
</configSections>
|
||||||
|
<userSettings>
|
||||||
|
<SteveCadwallader.CodeMaid.Properties.Settings>
|
||||||
|
<setting name="Cleaning_IncludeXAML" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeEvents" serializeAs="String">
|
||||||
|
<value>5</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_UpdateAccessorsToBothBeSingleLineOrMultiLine"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeNamespaces"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertExplicitAccessModifiersOnMethods"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeStructs" serializeAs="String">
|
||||||
|
<value>11</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_UsingStatementsToReinsertWhenRemovedExpression"
|
||||||
|
serializeAs="String">
|
||||||
|
<value />
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeIndexers" serializeAs="String">
|
||||||
|
<value>9</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterInterfaces"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeProperties" serializeAs="String">
|
||||||
|
<value>8</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeFields" serializeAs="String">
|
||||||
|
<value>1</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="General_Font" serializeAs="String">
|
||||||
|
<value>Segoe UI</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeEnumerations"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_CommentMinorTags" serializeAs="String">
|
||||||
|
<value>param||exception||returns||value||permissions</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeCaseStatements"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Collapsing_CollapseSolutionWhenOpened" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="General_UseUndoTransactions" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Digging_CenterOnWhole" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RemoveBlankLinesAfterAttributes" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_UpdateSingleLineMethods" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterMethods" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_SkipRemoveUnusedUsingStatementsDuringAutoCleanupOnSave"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeClasses" serializeAs="String">
|
||||||
|
<value>12</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterProperties"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="General_IconSet" serializeAs="String">
|
||||||
|
<value>0</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeClasses"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Progressing_ShowBuildProgressOnBuildStart" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_AutoCleanupOnFileSave" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_CommentWrapColumn" serializeAs="String">
|
||||||
|
<value>100</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertExplicitAccessModifiersOnStructs"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_IncludeCPlusPlus" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_KeepMembersWithinRegions" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeFieldsMultiLine"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeSingleLineComments"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeProperties"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_IncludeJavaScript" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Collapsing_KeepSoloProjectExpanded" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeMethods" serializeAs="String">
|
||||||
|
<value>10</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Progressing_ShowProgressOnWindowsTaskbar" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_ExclusionExpression" serializeAs="String">
|
||||||
|
<value>.*\.Designer\.cs||.*\.Designer\.vb||.*\.resx</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeEndRegionTags"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterFieldsMultiLine"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RemoveEndOfLineWhitespace" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeUsingStatementBlocks"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_PerformPartialCleanupOnExternal" serializeAs="String">
|
||||||
|
<value>0</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeEvents" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterStructs" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RemoveBlankLinesAfterOpeningBrace" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_IncludeCSS" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RunVisualStudioRemoveUnusedUsingStatements"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Digging_ComplexityWarningThreshold" serializeAs="String">
|
||||||
|
<value>10</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Digging_ShowItemMetadata" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Digging_SynchronizeOutlining" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Digging_ShowItemComplexity" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterUsingStatementBlocks"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_IncludeCSharp" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_IncludeTypeScript" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_AlphabetizeMembersOfTheSameGroup"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertExplicitAccessModifiersOnProperties"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeDelegates" serializeAs="String">
|
||||||
|
<value>4</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Progressing_HideBuildProgressOnBuildStop" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="General_Theme" serializeAs="String">
|
||||||
|
<value>0</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RemoveBlankLinesAtBottom" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_RunAtStartOfCleanup" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBetweenPropertiesMultiLineAccessors"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeConstructors" serializeAs="String">
|
||||||
|
<value>2</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_IncludeXML" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RunVisualStudioFormatDocumentCommand"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RunVisualStudioSortUsingStatements" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="General_DiagnosticsMode" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Digging_ComplexityAlertThreshold" serializeAs="String">
|
||||||
|
<value>15</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertExplicitAccessModifiersOnClasses"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterEvents" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterNamespaces"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_CommentMajorTags" serializeAs="String">
|
||||||
|
<value>summary||remarks||example</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertExplicitAccessModifiersOnFields"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertExplicitAccessModifiersOnEnumerations"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_IncludeHTML" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Switching_RelatedFileExtensionsExpression" serializeAs="String">
|
||||||
|
<value>.cpp .h||.xaml .xaml.cs||.xml .xsd||.ascx .ascx.cs||.aspx .aspx.cs||.master .master.cs</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterEnumerations"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_UpdateEndRegionDirectives" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_IncludeVB" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeDestructors" serializeAs="String">
|
||||||
|
<value>3</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterEndRegionTags"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RemoveMultipleConsecutiveBlankLines"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeInterfaces"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="General_ShowStartPageOnSolutionClose" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeStructs"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RemoveEndOfFileTrailingNewLine" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Digging_CacheFiles" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeMethods"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeEnums" serializeAs="String">
|
||||||
|
<value>6</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterClasses" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Digging_ShowMethodParameters" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_CommentRunDuringCleanup" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Digging_SecondarySortTypeByName" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankSpaceBeforeSelfClosingAngleBrackets"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Reorganizing_SortOrderTypeInterfaces" serializeAs="String">
|
||||||
|
<value>7</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertExplicitAccessModifiersOnEvents"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeRegionTags"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Compatibility_UseReSharperSilentCleanup" serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_AutoSaveAndCloseIfOpenedByCleanup" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterRegionTags"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertExplicitAccessModifiersOnInterfaces"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingBeforeDelegates"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_SkipSortUsingStatementsDuringAutoCleanupOnSave"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RemoveBlankLinesBeforeClosingTags" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_ExcludeT4GeneratedCode" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertBlankLinePaddingAfterDelegates"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>False</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_InsertExplicitAccessModifiersOnDelegates"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RemoveBlankLinesBeforeClosingBrace" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RemoveBlankSpacesBeforeClosingAngleBrackets"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Digging_IndentationMargin" serializeAs="String">
|
||||||
|
<value>17</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_RemoveBlankLinesAtTop" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="Cleaning_IncludeFSharp" serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
<setting name="General_SkipUndoTransactionsDuringAutoCleanupOnSave"
|
||||||
|
serializeAs="String">
|
||||||
|
<value>True</value>
|
||||||
|
</setting>
|
||||||
|
</SteveCadwallader.CodeMaid.Properties.Settings>
|
||||||
|
</userSettings>
|
||||||
|
</configuration>
|
BIN
Docs/ShareX_Class.zip
Normal file
BIN
Docs/ShareX_Class.zip
Normal file
Binary file not shown.
201
Docs/VersionHistory.txt
Normal file
201
Docs/VersionHistory.txt
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
ShareX 8.3 r700 - 2013-10-15
|
||||||
|
|
||||||
|
Added new After Capture task "Add image effects" in favour of resize, border and shadow
|
||||||
|
Added hotkey support for Tools (screen color picker, hash check and index folder) and to stop uploading
|
||||||
|
Added mega.co.nz file uploader support
|
||||||
|
|
||||||
|
ShareX 8.2 r655 – 2013-09-26
|
||||||
|
|
||||||
|
Added folder indexer with support for text, HTML and XML
|
||||||
|
Option to change clipboard content format for wider software compatibility
|
||||||
|
New after capture task: Image resize
|
||||||
|
Added support for indexing a folder during Clipboard Upload
|
||||||
|
Ability to use Windows modifier for hotkeys using configuration file
|
||||||
|
Rectangle Lite support in Advanced settings for slow computers
|
||||||
|
|
||||||
|
|
||||||
|
ShareX 8.1 r573 - 2013-09-04
|
||||||
|
|
||||||
|
Redesigned main configuration with simplified settings
|
||||||
|
Improved hotkey system to support all possible hotkey specific tasks
|
||||||
|
Support custom formats for clipboard content
|
||||||
|
Improved screen recorder
|
||||||
|
Automatic mode for proxy configuration
|
||||||
|
|
||||||
|
ShareX 8.0 r463 - 2013-08-12
|
||||||
|
|
||||||
|
Ability to create custom hotkeys with task settings
|
||||||
|
Unlimited screen recorder support
|
||||||
|
Commandline support for screen recorder
|
||||||
|
Added auto capture support
|
||||||
|
Capture selected monitor screen
|
||||||
|
Windows 7 taskbar support
|
||||||
|
Ability to change settings folder
|
||||||
|
|
||||||
|
ShareX 7.0.0.350 - 2013-04-05
|
||||||
|
|
||||||
|
Added modified version of Greenshot image editor (After capture -> Annotate Image)
|
||||||
|
Imgur, Google URL Shortener and Picasa using OAuth 2.0 now (You need to re-authorize)
|
||||||
|
Added Imgur album support
|
||||||
|
Added Google Drive uploader
|
||||||
|
Fixed Flickr upload issue
|
||||||
|
Updated to use Twitter 1.1 API
|
||||||
|
Fixed Possible crash with non existent program paths
|
||||||
|
Simplified Proxy handling behavior. No need to manually enter proxy host as the program will automatically retrieve it from the system proxy.
|
||||||
|
Added "Send URL with email" After upload task
|
||||||
|
Issues with DST time fixed
|
||||||
|
|
||||||
|
ShareX 6.7.0.311 - 2013-03-19
|
||||||
|
|
||||||
|
Issues with arguments and custom uploaders fixed
|
||||||
|
Fixed screen capture issues with Custom DPI settings
|
||||||
|
POST file support for custom text uploader
|
||||||
|
Shows cursor only if its visible
|
||||||
|
Added Hash Check Tool
|
||||||
|
Added localhostr.com support
|
||||||
|
|
||||||
|
ShareX 6.6.2.293 - 2013-02-01
|
||||||
|
|
||||||
|
Fixed errors with screen recording
|
||||||
|
Added Name Formatting support for custom uploaders
|
||||||
|
Fixed errors with updater
|
||||||
|
Remembers file upload directory
|
||||||
|
Goo.gl shortener fix
|
||||||
|
Fixed issues with slow FTP uploads
|
||||||
|
|
||||||
|
ShareX 6.6.1.283 - 2013-01-21
|
||||||
|
|
||||||
|
Reverted minimum system requirements to .NET 3.5 to support Windows XP
|
||||||
|
|
||||||
|
ShareX 6.6.0.280 - 2013-01-20
|
||||||
|
|
||||||
|
Added Screenshot delay setting
|
||||||
|
Added Clipboard upload settings tab
|
||||||
|
Fixed bug related to clipboard copy
|
||||||
|
Additional directory checks before saving screenshot
|
||||||
|
Added custom uploader support for all data types (image, text, file, url shortener)
|
||||||
|
Added Screen Recording with GIF/AVI output
|
||||||
|
Minimum system requirements updated to .NET 4.5
|
||||||
|
|
||||||
|
ShareX 6.5.0.248 - 2012-09-19
|
||||||
|
|
||||||
|
Use Delete key to remove items from main window
|
||||||
|
Added "Post capture tasks" window
|
||||||
|
Long file name error while capturing Active Window fixed
|
||||||
|
Updated Dropbox uploader
|
||||||
|
Auto Generated file names feature updated
|
||||||
|
Added Watermark support
|
||||||
|
Image history will remember your view settings
|
||||||
|
History & Image history will remember position, size and window state info
|
||||||
|
Be able to see response for a failed upload
|
||||||
|
Added "Add Border" Option to "After Capture Tasks" menu
|
||||||
|
Imgur upload bug fixed
|
||||||
|
|
||||||
|
ShareX 6.4.0.220 - 2012-08-10
|
||||||
|
|
||||||
|
Shows Balloon Tip after capture
|
||||||
|
Added Picasa image uploader
|
||||||
|
Added option to Clear List in Main Window
|
||||||
|
Minor UI changes to updater
|
||||||
|
|
||||||
|
ShareX 6.3.0.212 - 2012-08-03
|
||||||
|
|
||||||
|
Added new hotkeys to main window, history, image history: Enter = Open URL, Ctrl + Enter = Open file, Ctrl + C = Copy URL, F5 = Refresh
|
||||||
|
Added separate name format for active window capture
|
||||||
|
Moved magnifier out of text area
|
||||||
|
Added the option of capturing Active Windows without borders
|
||||||
|
FTP path issues fixed
|
||||||
|
Added Auto Increment option for Naming Files
|
||||||
|
Added paste.ee text uploader support
|
||||||
|
Added Progress(in %) information to the main window title
|
||||||
|
Added Shadow Offset setting
|
||||||
|
Double Clicking on a file performs checks in this order to open it: Shortended url first, url then and then the local file.
|
||||||
|
Added ge.tt file uploader
|
||||||
|
|
||||||
|
ShareX 6.2.0.195 - 2012-07-15
|
||||||
|
|
||||||
|
Added watch folder tab to settings for auto uploading newly created files in these folders
|
||||||
|
Added screen color picker to tools section
|
||||||
|
Added image history with a thumbnail view
|
||||||
|
Updated naming pattern to include variables such as 'active window title' and 'image width/height'
|
||||||
|
It is now possible to copy multiple uploaded item infos (html, bbcode etc.)
|
||||||
|
In 'shape capture' mode spacebar will now perform a fullscreen capture
|
||||||
|
|
||||||
|
ShareX 6.1.0.180 - 2012-06-23
|
||||||
|
|
||||||
|
Added support for sharing via social networking services initially with Twitter
|
||||||
|
After capture tasks and After upload tasks are configurable from the main window or tray menu
|
||||||
|
Reconfigured main window to have the main menu strip vertically
|
||||||
|
History storage optimizations
|
||||||
|
Ability to retry upload via main window context menu
|
||||||
|
Added printer support
|
||||||
|
|
||||||
|
ShareX 6.0.0.161 - 2012-06-09
|
||||||
|
|
||||||
|
Improved right click menu to include more open/copy options
|
||||||
|
Added support to preview image in the main window
|
||||||
|
Added support to run External Programs
|
||||||
|
Added pastee.org Text Uploader support
|
||||||
|
Ability to capture Last region
|
||||||
|
Proportional resizing of shapes while holding shift key
|
||||||
|
Added shortcut to "Send To" without using registry
|
||||||
|
Cursor can be moved using arrow keys during a shapes capture
|
||||||
|
Screen-wide crosshair support during shapes capture
|
||||||
|
Magnifier support during shapes capture, resizeable with mouse wheel (hold shift to increase box size)
|
||||||
|
Added imm.io Image Uploader
|
||||||
|
Rebranded as ShareX
|
||||||
|
|
||||||
|
ZUploader 5.5.0.3030 - 2012-03-07
|
||||||
|
|
||||||
|
5.5.0 Added Email as file uploader
|
||||||
|
5.4.1 Clipboard upload auto detects URL and shortens it
|
||||||
|
5.4.0 Added optional shadow capture for transparent capture
|
||||||
|
5.3.1 Settings are backed up for automatic recovery
|
||||||
|
5.3.0 Added Twitpic, Twitsnaps and yFrog
|
||||||
|
5.2.1 Improved tray menu
|
||||||
|
5.2.0 New updater with automatic downloader
|
||||||
|
5.1.0 Added image resize settings
|
||||||
|
5.0.0 Added Window & Control capture support to shape captures
|
||||||
|
4.9.0 Added new post-capture option: save screenshots to file
|
||||||
|
4.8.0 Added Box file uploader support
|
||||||
|
4.7.2 Supported image/text/file based FTP destinations
|
||||||
|
4.7.1 Added camera sound when capture is made
|
||||||
|
4.7.0 Added Transparent window capture
|
||||||
|
4.6.0 Added Hotkeys support
|
||||||
|
4.5.0 Added support to capture window from a list of windows
|
||||||
|
4.4.0 Added support to capture shapes to Clipboard
|
||||||
|
4.3.0 Added Minus uploader support
|
||||||
|
4.2.0 Added Photobucket uploader support
|
||||||
|
4.1.1 Added user account support for Goo.gl URL Shortener service
|
||||||
|
4.1.0 Added tray icon support
|
||||||
|
4.0.0 Added Capture menu to capture rectangle, rounded rectangle, ellipse, triangle, diamond, polygon and freehand shapes
|
||||||
|
3.12.0 Plugin system to perform Crop Shot and Entire Screen capture
|
||||||
|
3.11.0 New Uploaders Configuration window to setup user accounts
|
||||||
|
3.10.0 Added Clipboard Content Viewer to confirm uploading using Clipboard
|
||||||
|
3.9.0 Added URL Shortener support
|
||||||
|
3.8.0 Added ClipboardUpload hotkey (Ctrl + Page up)
|
||||||
|
3.7.0 Added upload queue system to limit simultaneous uploads
|
||||||
|
3.6.0 Added buffer size setting to improve upload speed
|
||||||
|
3.5.0 Added support to copy multiple URLs in history form
|
||||||
|
3.4.0 Text file detection improved for detecting popular programming code files
|
||||||
|
3.3.0 Image and text encoding operations moved to upload thread to prevent the main window from freezing
|
||||||
|
3.2.0 Drag & drop bitmap / text support
|
||||||
|
3.1.0 Startup time improved by using precompiled xml serialization dll (SGEN) and threads
|
||||||
|
3.0.0 Improved uploading speed and memory allocation especially for big uploads, many bug fixes
|
||||||
|
2.8.0 Added auto naming settings for clipboard upload
|
||||||
|
2.6.0 Added debug tab to settings form which also saves debug messages automatically to "ZUploaderPersonalPath/Log_(Month)_(Year).txt"
|
||||||
|
2.5.0 Added "Show response" button to right click menu to see upload response (Useful for debugging)
|
||||||
|
2.4.0 Added new CLI command (-clipboardupload)
|
||||||
|
2.3.0 Portable support
|
||||||
|
2.2.0 Added image viewer to history form
|
||||||
|
2.1.0 Added filters to history form
|
||||||
|
2.0.0 History support using SQLite as database
|
||||||
|
1.5.0 Image settings for changing image related settings such as image format, quality etc.
|
||||||
|
1.4.0 Single instance support for better shell extension uploading (Useful for CLI uploads)
|
||||||
|
1.3.0 Added "Stop upload" button to right click menu
|
||||||
|
1.2.0 Added support for Shell Extension "Upload using ShareX"
|
||||||
|
1.1.0 Reconfigured UI, Added proxy support
|
||||||
|
|
||||||
|
ZUploader 1.0.0.0 - 27-03-2010
|
||||||
|
|
||||||
|
1.0.0 Initial version of ZUploader
|
|
@ -1,7 +1,7 @@
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 3, 29 June 2007
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
Copyright (C) 2007 Free Software Foundation, Inc. {http://fsf.org/}
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
Everyone is permitted to copy and distribute verbatim copies
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
of this license document, but changing it is not allowed.
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively
|
||||||
state the exclusion of warranty; and each file should have at least
|
state the exclusion of warranty; and each file should have at least
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
{one line to give the program's name and a brief idea of what it does.}
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
Copyright (C) {year} {name of author}
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -645,14 +645,14 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||||
GNU General Public License for more details.
|
GNU General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see {http://www.gnu.org/licenses/}.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Also add information on how to contact you by electronic and paper mail.
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
If the program does terminal interaction, make it output a short
|
If the program does terminal interaction, make it output a short
|
||||||
notice like this when it starts in an interactive mode:
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
ShareX Copyright (C) 2013
|
<program> Copyright (C) <year> <name of author>
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
This is free software, and you are welcome to redistribute it
|
This is free software, and you are welcome to redistribute it
|
||||||
under certain conditions; type `show c' for details.
|
under certain conditions; type `show c' for details.
|
||||||
|
@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
|
||||||
You should also get your employer (if you work as a programmer) or school,
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
For more information on this, and how to apply and follow the GNU GPL, see
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
{http://www.gnu.org/licenses/}.
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
The GNU General Public License does not permit incorporating your program
|
The GNU General Public License does not permit incorporating your program
|
||||||
into proprietary programs. If your program is a subroutine library, you
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
may consider it more useful to permit linking proprietary applications with
|
may consider it more useful to permit linking proprietary applications with
|
||||||
the library. If this is what you want to do, use the GNU Lesser General
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
Public License instead of this License. But first, please read
|
Public License instead of this License. But first, please read
|
||||||
{http://www.gnu.org/philosophy/why-not-lgpl.html}.
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
1
Docs/svn global ignore.txt
Normal file
1
Docs/svn global ignore.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
.o *.lo *.la *.al .libs *.so *.so.[0-9] .a *.pyc *.pyo *.rej *~ ## .#* ..swp .DS_Store thumbs.db Thumbs.db *.bak *.class *.mine *.obj *.ncb *.lib *.log *.idb *.ilk *.msi *.res *.pch *.suo *.exp *.*~ *.~ ~. cvs CVS *.CVS *.cvs release Release debug Debug ignore Ignore bin Bin obj Obj *.csproj.user *.user
|
434
GreenshotImageEditor/Configuration/CoreConfiguration.cs
Normal file
434
GreenshotImageEditor/Configuration/CoreConfiguration.cs
Normal file
|
@ -0,0 +1,434 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using Greenshot.Plugin;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
public enum ClipboardFormat
|
||||||
|
{
|
||||||
|
PNG, DIB, HTML, HTMLDATAURL, BITMAP
|
||||||
|
}
|
||||||
|
public enum OutputFormat
|
||||||
|
{
|
||||||
|
bmp, gif, jpg, png, tiff, greenshot
|
||||||
|
}
|
||||||
|
public enum WindowCaptureMode
|
||||||
|
{
|
||||||
|
Screen, GDI, Aero, AeroTransparent, Auto
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum BuildStates
|
||||||
|
{
|
||||||
|
UNSTABLE,
|
||||||
|
RELEASE_CANDIDATE,
|
||||||
|
RELEASE
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ClickActions
|
||||||
|
{
|
||||||
|
DO_NOTHING,
|
||||||
|
OPEN_LAST_IN_EXPLORER,
|
||||||
|
OPEN_LAST_IN_EDITOR,
|
||||||
|
OPEN_SETTINGS,
|
||||||
|
SHOW_CONTEXT_MENU
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Description of CoreConfiguration.
|
||||||
|
/// </summary>
|
||||||
|
[IniSection("Core", Description = "Greenshot core configuration")]
|
||||||
|
public class CoreConfiguration : IniSection
|
||||||
|
{
|
||||||
|
[IniProperty("Language", Description = "The language in IETF format (e.g. en-US)")]
|
||||||
|
public string Language;
|
||||||
|
|
||||||
|
[IniProperty("RegionHotkey", Description = "Hotkey for starting the region capture", DefaultValue = "PrintScreen")]
|
||||||
|
public string RegionHotkey;
|
||||||
|
[IniProperty("WindowHotkey", Description = "Hotkey for starting the window capture", DefaultValue = "Alt + PrintScreen")]
|
||||||
|
public string WindowHotkey;
|
||||||
|
[IniProperty("FullscreenHotkey", Description = "Hotkey for starting the fullscreen capture", DefaultValue = "Ctrl + PrintScreen")]
|
||||||
|
public string FullscreenHotkey;
|
||||||
|
[IniProperty("LastregionHotkey", Description = "Hotkey for starting the last region capture", DefaultValue = "Shift + PrintScreen")]
|
||||||
|
public string LastregionHotkey;
|
||||||
|
[IniProperty("IEHotkey", Description = "Hotkey for starting the IE capture", DefaultValue = "Shift + Ctrl + PrintScreen")]
|
||||||
|
public string IEHotkey;
|
||||||
|
|
||||||
|
[IniProperty("IsFirstLaunch", Description = "Is this the first time launch?", DefaultValue = "true")]
|
||||||
|
public bool IsFirstLaunch;
|
||||||
|
[IniProperty("Destinations", Separator = ",", Description = "Which destinations? Possible options (more might be added by plugins) are: Editor, FileDefault, FileWithDialog, Clipboard, Printer, EMail, Picker", DefaultValue = "Picker")]
|
||||||
|
public List<string> OutputDestinations = new List<string>();
|
||||||
|
[IniProperty("ClipboardFormats", Separator = ",", Description = "Specify which formats we copy on the clipboard? Options are: PNG, HTML, HTMLDATAURL and DIB", DefaultValue = "PNG,DIB")]
|
||||||
|
public List<ClipboardFormat> ClipboardFormats = new List<ClipboardFormat>();
|
||||||
|
|
||||||
|
[IniProperty("CaptureMousepointer", Description = "Should the mouse be captured?", DefaultValue = "true")]
|
||||||
|
public bool CaptureMousepointer;
|
||||||
|
[IniProperty("CaptureWindowsInteractive", Description = "Use interactive window selection to capture? (false=Capture active window)", DefaultValue = "false")]
|
||||||
|
public bool CaptureWindowsInteractive;
|
||||||
|
[IniProperty("CaptureDelay", Description = "Capture delay in millseconds.", DefaultValue = "100")]
|
||||||
|
public int CaptureDelay;
|
||||||
|
[IniProperty("ScreenCaptureMode", Description = "The capture mode used to capture a screen. (Auto, FullScreen, Fixed)", DefaultValue = "Auto")]
|
||||||
|
public ScreenCaptureMode ScreenCaptureMode;
|
||||||
|
[IniProperty("ScreenToCapture", Description = "The screen number to capture when using ScreenCaptureMode Fixed.", DefaultValue = "1")]
|
||||||
|
public int ScreenToCapture;
|
||||||
|
[IniProperty("WindowCaptureMode", Description = "The capture mode used to capture a Window (Screen, GDI, Aero, AeroTransparent, Auto).", DefaultValue = "Auto")]
|
||||||
|
public WindowCaptureMode WindowCaptureMode;
|
||||||
|
[IniProperty("WindowCaptureAllChildLocations", Description = "Enable/disable capture all children, very slow but will make it possible to use this information in the editor.", DefaultValue = "False")]
|
||||||
|
public bool WindowCaptureAllChildLocations;
|
||||||
|
|
||||||
|
[IniProperty("DWMBackgroundColor", Description = "The background color for a DWM window capture.")]
|
||||||
|
public Color DWMBackgroundColor;
|
||||||
|
|
||||||
|
[IniProperty("PlayCameraSound", LanguageKey = "settings_playsound", Description = "Play a camera sound after taking a capture.", DefaultValue = "false")]
|
||||||
|
public bool PlayCameraSound = false;
|
||||||
|
[IniProperty("ShowTrayNotification", LanguageKey = "settings_shownotify", Description = "Show a notification from the systray when a capture is taken.", DefaultValue = "true")]
|
||||||
|
public bool ShowTrayNotification = true;
|
||||||
|
|
||||||
|
[IniProperty("OutputFilePath", Description = "Output file path.")]
|
||||||
|
public string OutputFilePath;
|
||||||
|
[IniProperty("OutputFileAllowOverwrite", Description = "If the target file already exists True will make Greenshot always overwrite and False will display a 'Save-As' dialog.", DefaultValue = "true")]
|
||||||
|
public bool OutputFileAllowOverwrite;
|
||||||
|
[IniProperty("OutputFileFilenamePattern", Description = "Filename pattern for screenshot.", DefaultValue = "${capturetime:d\"yyyy-MM-dd HH_mm_ss\"}-${title}")]
|
||||||
|
public string OutputFileFilenamePattern;
|
||||||
|
[IniProperty("OutputFileFormat", Description = "Default file type for writing screenshots. (bmp, gif, jpg, png, tiff)", DefaultValue = "png")]
|
||||||
|
public OutputFormat OutputFileFormat = OutputFormat.png;
|
||||||
|
[IniProperty("OutputFileReduceColors", Description = "If set to true, than the colors of the output file are reduced to 256 (8-bit) colors", DefaultValue = "false")]
|
||||||
|
public bool OutputFileReduceColors;
|
||||||
|
[IniProperty("OutputFileAutoReduceColors", Description = "If set to true the amount of colors is counted and if smaller than 256 the color reduction is automatically used.", DefaultValue = "true")]
|
||||||
|
public bool OutputFileAutoReduceColors;
|
||||||
|
|
||||||
|
[IniProperty("OutputFileCopyPathToClipboard", Description = "When saving a screenshot, copy the path to the clipboard?", DefaultValue = "true")]
|
||||||
|
public bool OutputFileCopyPathToClipboard;
|
||||||
|
[IniProperty("OutputFileAsFullpath", Description = "SaveAs Full path?")]
|
||||||
|
public string OutputFileAsFullpath;
|
||||||
|
|
||||||
|
[IniProperty("OutputFileJpegQuality", Description = "JPEG file save quality in %.", DefaultValue = "80")]
|
||||||
|
public int OutputFileJpegQuality;
|
||||||
|
[IniProperty("OutputFilePromptQuality", Description = "Ask for the quality before saving?", DefaultValue = "false")]
|
||||||
|
public bool OutputFilePromptQuality;
|
||||||
|
[IniProperty("OutputFileIncrementingNumber", Description = "The number for the ${NUM} in the filename pattern, is increased automatically after each save.", DefaultValue = "1")]
|
||||||
|
public uint OutputFileIncrementingNumber;
|
||||||
|
|
||||||
|
[IniProperty("OutputPrintPromptOptions", LanguageKey = "settings_alwaysshowprintoptionsdialog", Description = "Ask for print options when printing?", DefaultValue = "true")]
|
||||||
|
public bool OutputPrintPromptOptions;
|
||||||
|
[IniProperty("OutputPrintAllowRotate", LanguageKey = "printoptions_allowrotate", Description = "Allow rotating the picture for fitting on paper?", DefaultValue = "false")]
|
||||||
|
public bool OutputPrintAllowRotate;
|
||||||
|
[IniProperty("OutputPrintAllowEnlarge", LanguageKey = "printoptions_allowenlarge", Description = "Allow growing the picture for fitting on paper?", DefaultValue = "false")]
|
||||||
|
public bool OutputPrintAllowEnlarge;
|
||||||
|
[IniProperty("OutputPrintAllowShrink", LanguageKey = "printoptions_allowshrink", Description = "Allow shrinking the picture for fitting on paper?", DefaultValue = "true")]
|
||||||
|
public bool OutputPrintAllowShrink;
|
||||||
|
[IniProperty("OutputPrintCenter", LanguageKey = "printoptions_allowcenter", Description = "Center image when printing?", DefaultValue = "true")]
|
||||||
|
public bool OutputPrintCenter;
|
||||||
|
[IniProperty("OutputPrintInverted", LanguageKey = "printoptions_inverted", Description = "Print image inverted (use e.g. for console captures)", DefaultValue = "false")]
|
||||||
|
public bool OutputPrintInverted;
|
||||||
|
[IniProperty("OutputPrintGrayscale", LanguageKey = "printoptions_printgrayscale", Description = "Force grayscale printing", DefaultValue = "false")]
|
||||||
|
public bool OutputPrintGrayscale;
|
||||||
|
[IniProperty("OutputPrintMonochrome", LanguageKey = "printoptions_printmonochrome", Description = "Force monorchrome printing", DefaultValue = "false")]
|
||||||
|
public bool OutputPrintMonochrome;
|
||||||
|
[IniProperty("OutputPrintMonochromeThreshold", Description = "Threshold for monochrome filter (0 - 255), lower value means less black", DefaultValue = "127")]
|
||||||
|
public byte OutputPrintMonochromeThreshold;
|
||||||
|
[IniProperty("OutputPrintFooter", LanguageKey = "printoptions_timestamp", Description = "Print footer on print?", DefaultValue = "true")]
|
||||||
|
public bool OutputPrintFooter;
|
||||||
|
[IniProperty("OutputPrintFooterPattern", Description = "Footer pattern", DefaultValue = "${capturetime:d\"D\"} ${capturetime:d\"T\"} - ${title}")]
|
||||||
|
public string OutputPrintFooterPattern;
|
||||||
|
[IniProperty("NotificationSound", Description = "The wav-file to play when a capture is taken, loaded only once at the Greenshot startup", DefaultValue = "default")]
|
||||||
|
public string NotificationSound;
|
||||||
|
[IniProperty("UseProxy", Description = "Use your global proxy?", DefaultValue = "True")]
|
||||||
|
public bool UseProxy;
|
||||||
|
[IniProperty("IECapture", Description = "Enable/disable IE capture", DefaultValue = "True")]
|
||||||
|
public bool IECapture;
|
||||||
|
[IniProperty("IEFieldCapture", Description = "Enable/disable IE field capture, very slow but will make it possible to annotate the fields of a capture in the editor.", DefaultValue = "False")]
|
||||||
|
public bool IEFieldCapture;
|
||||||
|
[IniProperty("WindowClassesToCheckForIE", Description = "Comma separated list of Window-Classes which need to be checked for a IE instance!", DefaultValue = "AfxFrameOrView70,IMWindowClass")]
|
||||||
|
public List<string> WindowClassesToCheckForIE;
|
||||||
|
[IniProperty("AutoCropDifference", Description = "Sets how to compare the colors for the autocrop detection, the higher the more is 'selected'. Possible values are from 0 to 255, where everything above ~150 doesn't make much sense!", DefaultValue = "10")]
|
||||||
|
public int AutoCropDifference;
|
||||||
|
|
||||||
|
[IniProperty("IncludePlugins", Description = "Comma separated list of Plugins which are allowed. If something in the list, than every plugin not in the list will not be loaded!")]
|
||||||
|
public List<string> IncludePlugins;
|
||||||
|
[IniProperty("ExcludePlugins", Description = "Comma separated list of Plugins which are NOT allowed.")]
|
||||||
|
public List<string> ExcludePlugins;
|
||||||
|
[IniProperty("ExcludeDestinations", Description = "Comma separated list of destinations which should be disabled.", DefaultValue = "OneNote")]
|
||||||
|
public List<string> ExcludeDestinations;
|
||||||
|
|
||||||
|
[IniProperty("UpdateCheckInterval", Description = "How many days between every update check? (0=no checks)", DefaultValue = "1")]
|
||||||
|
public int UpdateCheckInterval;
|
||||||
|
[IniProperty("LastUpdateCheck", Description = "Last update check")]
|
||||||
|
public DateTime LastUpdateCheck;
|
||||||
|
|
||||||
|
[IniProperty("DisableSettings", Description = "Enable/disable the access to the settings, can only be changed manually in this .ini", DefaultValue = "False")]
|
||||||
|
public bool DisableSettings;
|
||||||
|
[IniProperty("DisableQuickSettings", Description = "Enable/disable the access to the quick settings, can only be changed manually in this .ini", DefaultValue = "False")]
|
||||||
|
public bool DisableQuickSettings;
|
||||||
|
[IniProperty("DisableTrayicon", Description = "Disable the trayicon, can only be changed manually in this .ini", DefaultValue = "False")]
|
||||||
|
public bool HideTrayicon;
|
||||||
|
[IniProperty("HideExpertSettings", Description = "Hide expert tab in the settings, can only be changed manually in this .ini", DefaultValue = "False")]
|
||||||
|
public bool HideExpertSettings;
|
||||||
|
|
||||||
|
[IniProperty("ThumnailPreview", Description = "Enable/disable thumbnail previews", DefaultValue = "True")]
|
||||||
|
public bool ThumnailPreview;
|
||||||
|
|
||||||
|
[IniProperty("NoGDICaptureForProduct", Description = "List of products for which GDI capturing doesn't work.", DefaultValue = "IntelliJ,IDEA")]
|
||||||
|
public List<string> NoGDICaptureForProduct;
|
||||||
|
[IniProperty("NoDWMCaptureForProduct", Description = "List of products for which DWM capturing doesn't work.", DefaultValue = "Citrix,ICA,Client")]
|
||||||
|
public List<string> NoDWMCaptureForProduct;
|
||||||
|
|
||||||
|
[IniProperty("OptimizeForRDP", Description = "Make some optimizations for usage with remote desktop", DefaultValue = "False")]
|
||||||
|
public bool OptimizeForRDP;
|
||||||
|
[IniProperty("MinimizeWorkingSetSize", Description = "Optimize memory footprint, but with a performance penalty!", DefaultValue = "False")]
|
||||||
|
public bool MinimizeWorkingSetSize;
|
||||||
|
|
||||||
|
[IniProperty("WindowCaptureRemoveCorners", Description = "Remove the corners from a window capture", DefaultValue = "True")]
|
||||||
|
public bool WindowCaptureRemoveCorners;
|
||||||
|
|
||||||
|
[IniProperty("CheckForUnstable", Description = "Also check for unstable version updates", DefaultValue = "False")]
|
||||||
|
public bool CheckForUnstable;
|
||||||
|
|
||||||
|
[IniProperty("ActiveTitleFixes", Description = "The fixes that are active.")]
|
||||||
|
public List<string> ActiveTitleFixes;
|
||||||
|
|
||||||
|
[IniProperty("TitleFixMatcher", Description = "The regular expressions to match the title with.")]
|
||||||
|
public Dictionary<string, string> TitleFixMatcher;
|
||||||
|
|
||||||
|
[IniProperty("TitleFixReplacer", Description = "The replacements for the matchers.")]
|
||||||
|
public Dictionary<string, string> TitleFixReplacer;
|
||||||
|
|
||||||
|
[IniProperty("ExperimentalFeatures", Description = "A list of experimental features, this allows us to test certain features before releasing them.", ExcludeIfNull = true)]
|
||||||
|
public List<string> ExperimentalFeatures;
|
||||||
|
|
||||||
|
[IniProperty("EnableSpecialDIBClipboardReader", Description = "Enable a special DIB clipboard reader", DefaultValue = "True")]
|
||||||
|
public bool EnableSpecialDIBClipboardReader;
|
||||||
|
|
||||||
|
[IniProperty("WindowCornerCutShape", Description = "The cutshape which is used to remove the window corners, is mirrorred for all corners", DefaultValue = "5,3,2,1,1")]
|
||||||
|
public List<int> WindowCornerCutShape;
|
||||||
|
|
||||||
|
[IniProperty("LeftClickAction", Description = "Specify what action is made if the tray icon is left clicked, if a double-click action is specified this action is initiated after a delay (configurable via the windows double-click speed)", DefaultValue = "SHOW_CONTEXT_MENU")]
|
||||||
|
public ClickActions LeftClickAction;
|
||||||
|
|
||||||
|
[IniProperty("DoubleClickAction", Description = "Specify what action is made if the tray icon is double clicked", DefaultValue = "OPEN_LAST_IN_EXPLORER")]
|
||||||
|
public ClickActions DoubleClickAction;
|
||||||
|
|
||||||
|
[IniProperty("ZoomerEnabled", Description = "Sets if the zoomer is enabled", DefaultValue = "True")]
|
||||||
|
public bool ZoomerEnabled;
|
||||||
|
|
||||||
|
[IniProperty("MaxMenuItemLength", Description = "Maximum length of submenu items in the context menu, making this longer might cause context menu issues on dual screen systems.", DefaultValue = "25")]
|
||||||
|
public int MaxMenuItemLength;
|
||||||
|
|
||||||
|
[IniProperty("MailApiTo", Description = "The 'to' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")]
|
||||||
|
public string MailApiTo;
|
||||||
|
[IniProperty("MailApiCC", Description = "The 'CC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")]
|
||||||
|
public string MailApiCC;
|
||||||
|
[IniProperty("MailApiBCC", Description = "The 'BCC' field for the email destination (settings for Outlook can be found under the Office section)", DefaultValue = "")]
|
||||||
|
public string MailApiBCC;
|
||||||
|
|
||||||
|
// Specifies what THIS build is
|
||||||
|
public BuildStates BuildState = BuildStates.UNSTABLE;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A helper method which returns true if the supplied experimental feature is enabled
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="experimentalFeature"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool isExperimentalFeatureEnabled(string experimentalFeature)
|
||||||
|
{
|
||||||
|
return (ExperimentalFeatures != null && ExperimentalFeatures.Contains(experimentalFeature));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Supply values we can't put as defaults
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="property">The property to return a default for</param>
|
||||||
|
/// <returns>object with the default value for the supplied property</returns>
|
||||||
|
public override object GetDefault(string property)
|
||||||
|
{
|
||||||
|
switch (property)
|
||||||
|
{
|
||||||
|
case "PluginWhitelist":
|
||||||
|
case "PluginBacklist":
|
||||||
|
return new List<string>();
|
||||||
|
case "OutputFileAsFullpath":
|
||||||
|
if (IniConfig.IsPortable)
|
||||||
|
{
|
||||||
|
return Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots\dummy.png");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "dummy.png");
|
||||||
|
}
|
||||||
|
case "OutputFilePath":
|
||||||
|
if (IniConfig.IsPortable)
|
||||||
|
{
|
||||||
|
string pafOutputFilePath = Path.Combine(Application.StartupPath, @"..\..\Documents\Pictures\Greenshots");
|
||||||
|
if (!Directory.Exists(pafOutputFilePath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(pafOutputFilePath);
|
||||||
|
return pafOutputFilePath;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LOG.Warn(ex);
|
||||||
|
// Problem creating directory, fallback to Desktop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return pafOutputFilePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||||
|
case "DWMBackgroundColor":
|
||||||
|
return Color.Transparent;
|
||||||
|
case "ActiveTitleFixes":
|
||||||
|
List<string> activeDefaults = new List<string>();
|
||||||
|
activeDefaults.Add("Firefox");
|
||||||
|
activeDefaults.Add("IE");
|
||||||
|
activeDefaults.Add("Chrome");
|
||||||
|
return activeDefaults;
|
||||||
|
case "TitleFixMatcher":
|
||||||
|
Dictionary<string, string> matcherDefaults = new Dictionary<string, string>();
|
||||||
|
matcherDefaults.Add("Firefox", " - Mozilla Firefox.*");
|
||||||
|
matcherDefaults.Add("IE", " - (Microsoft|Windows) Internet Explorer.*");
|
||||||
|
matcherDefaults.Add("Chrome", " - Google Chrome.*");
|
||||||
|
return matcherDefaults;
|
||||||
|
case "TitleFixReplacer":
|
||||||
|
Dictionary<string, string> replacerDefaults = new Dictionary<string, string>();
|
||||||
|
replacerDefaults.Add("Firefox", "");
|
||||||
|
replacerDefaults.Add("IE", "");
|
||||||
|
replacerDefaults.Add("Chrome", "");
|
||||||
|
return replacerDefaults;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will be called before converting the property, making to possible to correct a certain value
|
||||||
|
/// Can be used when migration is needed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyName">The name of the property</param>
|
||||||
|
/// <param name="propertyValue">The string value of the property</param>
|
||||||
|
/// <returns>string with the propertyValue, modified or not...</returns>
|
||||||
|
public override string PreCheckValue(string propertyName, string propertyValue)
|
||||||
|
{
|
||||||
|
// Changed the separator, now we need to correct this
|
||||||
|
if ("Destinations".Equals(propertyName))
|
||||||
|
{
|
||||||
|
if (propertyValue != null)
|
||||||
|
{
|
||||||
|
return propertyValue.Replace('|', ',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ("OutputFilePath".Equals(propertyName))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(propertyValue))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return base.PreCheckValue(propertyName, propertyValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will be called after reading the configuration, so eventually some corrections can be made
|
||||||
|
/// </summary>
|
||||||
|
public override void AfterLoad()
|
||||||
|
{
|
||||||
|
// Comment with releases
|
||||||
|
// CheckForUnstable = true;
|
||||||
|
|
||||||
|
if (OutputDestinations == null)
|
||||||
|
{
|
||||||
|
OutputDestinations = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure there is an output!
|
||||||
|
if (OutputDestinations.Count == 0)
|
||||||
|
{
|
||||||
|
OutputDestinations.Add("Editor");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent both settings at once, bug #3435056
|
||||||
|
if (OutputDestinations.Contains("Clipboard") && OutputFileCopyPathToClipboard)
|
||||||
|
{
|
||||||
|
OutputFileCopyPathToClipboard = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have clipboard formats, otherwise a paste doesn't make sense!
|
||||||
|
if (ClipboardFormats == null || ClipboardFormats.Count == 0)
|
||||||
|
{
|
||||||
|
ClipboardFormats = new List<ClipboardFormat>();
|
||||||
|
ClipboardFormats.Add(ClipboardFormat.PNG);
|
||||||
|
ClipboardFormats.Add(ClipboardFormat.HTML);
|
||||||
|
ClipboardFormats.Add(ClipboardFormat.DIB);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the lists are lowercase, to speedup the check
|
||||||
|
if (NoGDICaptureForProduct != null)
|
||||||
|
{
|
||||||
|
// Fix error in configuration
|
||||||
|
if (NoGDICaptureForProduct.Count == 1)
|
||||||
|
{
|
||||||
|
if ("intellij idea".Equals(NoGDICaptureForProduct[0]))
|
||||||
|
{
|
||||||
|
NoGDICaptureForProduct[0] = "intellij,idea";
|
||||||
|
IsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < NoGDICaptureForProduct.Count; i++)
|
||||||
|
{
|
||||||
|
NoGDICaptureForProduct[i] = NoGDICaptureForProduct[i].ToLower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (NoDWMCaptureForProduct != null)
|
||||||
|
{
|
||||||
|
// Fix error in configuration
|
||||||
|
if (NoDWMCaptureForProduct.Count == 1)
|
||||||
|
{
|
||||||
|
if ("citrix ica client".Equals(NoDWMCaptureForProduct[0]))
|
||||||
|
{
|
||||||
|
NoDWMCaptureForProduct[0] = "citrix,ica,client";
|
||||||
|
IsDirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < NoDWMCaptureForProduct.Count; i++)
|
||||||
|
{
|
||||||
|
NoDWMCaptureForProduct[i] = NoDWMCaptureForProduct[i].ToLower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AutoCropDifference < 0)
|
||||||
|
{
|
||||||
|
AutoCropDifference = 0;
|
||||||
|
}
|
||||||
|
if (AutoCropDifference > 255)
|
||||||
|
{
|
||||||
|
AutoCropDifference = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
141
GreenshotImageEditor/Configuration/EditorConfiguration.cs
Normal file
141
GreenshotImageEditor/Configuration/EditorConfiguration.cs
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Drawing.Fields;
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using GreenshotPlugin.UnmanagedHelpers;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Greenshot.Configuration
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of CoreConfiguration.
|
||||||
|
/// </summary>
|
||||||
|
[IniSection("Editor", Description = "Greenshot editor configuration")]
|
||||||
|
public class EditorConfiguration : IniSection
|
||||||
|
{
|
||||||
|
[IniProperty("RecentColors", Separator = "|", Description = "Last used colors")]
|
||||||
|
public List<Color> RecentColors;
|
||||||
|
|
||||||
|
[IniProperty("LastFieldValue", Separator = "|", Description = "Field values, make sure the last used settings are re-used")]
|
||||||
|
public Dictionary<string, object> LastUsedFieldValues;
|
||||||
|
|
||||||
|
[IniProperty("MatchSizeToCapture", Description = "Match the editor window size to the capture", DefaultValue = "True")]
|
||||||
|
public bool MatchSizeToCapture;
|
||||||
|
[IniProperty("WindowPlacementFlags", Description = "Placement flags", DefaultValue = "0")]
|
||||||
|
public WindowPlacementFlags WindowPlacementFlags;
|
||||||
|
[IniProperty("WindowShowCommand", Description = "Show command", DefaultValue = "Normal")]
|
||||||
|
public ShowWindowCommand ShowWindowCommand;
|
||||||
|
[IniProperty("WindowMinPosition", Description = "Position of minimized window", DefaultValue = "-1,-1")]
|
||||||
|
public Point WindowMinPosition;
|
||||||
|
[IniProperty("WindowMaxPosition", Description = "Position of maximized window", DefaultValue = "-1,-1")]
|
||||||
|
public Point WindowMaxPosition;
|
||||||
|
[IniProperty("WindowNormalPosition", Description = "Position of normal window", DefaultValue = "100,100,600,500")]
|
||||||
|
public Rectangle WindowNormalPosition;
|
||||||
|
[IniProperty("ReuseEditor", Description = "Reuse already open editor", DefaultValue = "false")]
|
||||||
|
public bool ReuseEditor;
|
||||||
|
[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;
|
||||||
|
|
||||||
|
[IniProperty("SuppressSaveDialogAtClose", Description = "Suppressed the 'do you want to save' dialog when closing the editor.", DefaultValue = "False")]
|
||||||
|
public bool SuppressSaveDialogAtClose;
|
||||||
|
|
||||||
|
/// <param name="requestingType">Type of the class for which to create the field</param>
|
||||||
|
/// <param name="fieldType">FieldType of the field to construct</param>
|
||||||
|
/// <param name="scope">FieldType of the field to construct</param>
|
||||||
|
/// <returns>a new Field of the given fieldType, with the scope of it's value being restricted to the Type scope</returns>
|
||||||
|
public Field CreateField(Type requestingType, FieldType fieldType, object preferredDefaultValue)
|
||||||
|
{
|
||||||
|
string requestingTypeName = requestingType.Name;
|
||||||
|
string requestedField = requestingTypeName + "." + fieldType.Name;
|
||||||
|
object fieldValue = preferredDefaultValue;
|
||||||
|
|
||||||
|
// Check if the configuration exists
|
||||||
|
if (LastUsedFieldValues == null)
|
||||||
|
{
|
||||||
|
LastUsedFieldValues = new Dictionary<string, object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if settings for the requesting type exist, if not create!
|
||||||
|
if (LastUsedFieldValues.ContainsKey(requestedField))
|
||||||
|
{
|
||||||
|
// Check if a value is set (not null)!
|
||||||
|
if (LastUsedFieldValues[requestedField] != null)
|
||||||
|
{
|
||||||
|
fieldValue = LastUsedFieldValues[requestedField];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Overwrite null value
|
||||||
|
LastUsedFieldValues[requestedField] = fieldValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LastUsedFieldValues.Add(requestedField, fieldValue);
|
||||||
|
}
|
||||||
|
Field returnField = new Field(fieldType, requestingType);
|
||||||
|
returnField.Value = fieldValue;
|
||||||
|
return returnField;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateLastFieldValue(Field field)
|
||||||
|
{
|
||||||
|
string requestedField = field.Scope + "." + field.FieldType.Name;
|
||||||
|
// Check if the configuration exists
|
||||||
|
if (LastUsedFieldValues == null)
|
||||||
|
{
|
||||||
|
LastUsedFieldValues = new Dictionary<string, object>();
|
||||||
|
}
|
||||||
|
// check if settings for the requesting type exist, if not create!
|
||||||
|
if (LastUsedFieldValues.ContainsKey(requestedField))
|
||||||
|
{
|
||||||
|
LastUsedFieldValues[requestedField] = field.myValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LastUsedFieldValues.Add(requestedField, field.myValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public WindowPlacement GetEditorPlacement()
|
||||||
|
{
|
||||||
|
WindowPlacement placement = WindowPlacement.Default;
|
||||||
|
placement.NormalPosition = new RECT(WindowNormalPosition);
|
||||||
|
placement.MaxPosition = new POINT(WindowMaxPosition);
|
||||||
|
placement.MinPosition = new POINT(WindowMinPosition);
|
||||||
|
placement.ShowCmd = ShowWindowCommand;
|
||||||
|
placement.Flags = WindowPlacementFlags;
|
||||||
|
return placement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetEditorPlacement(WindowPlacement placement)
|
||||||
|
{
|
||||||
|
WindowNormalPosition = placement.NormalPosition.ToRectangle();
|
||||||
|
WindowMaxPosition = placement.MaxPosition.ToPoint();
|
||||||
|
WindowMinPosition = placement.MinPosition.ToPoint();
|
||||||
|
ShowWindowCommand = placement.ShowCmd;
|
||||||
|
WindowPlacementFlags = placement.Flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
241
GreenshotImageEditor/Configuration/LanguageKeys.cs
Normal file
241
GreenshotImageEditor/Configuration/LanguageKeys.cs
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Greenshot.Configuration
|
||||||
|
{
|
||||||
|
public enum LangKey
|
||||||
|
{
|
||||||
|
none,
|
||||||
|
about_bugs,
|
||||||
|
about_donations,
|
||||||
|
about_host,
|
||||||
|
about_icons,
|
||||||
|
about_license,
|
||||||
|
about_title,
|
||||||
|
about_translation,
|
||||||
|
application_title,
|
||||||
|
bugreport_cancel,
|
||||||
|
bugreport_info,
|
||||||
|
bugreport_title,
|
||||||
|
clipboard_error,
|
||||||
|
clipboard_inuse,
|
||||||
|
colorpicker_alpha,
|
||||||
|
colorpicker_apply,
|
||||||
|
colorpicker_blue,
|
||||||
|
colorpicker_green,
|
||||||
|
colorpicker_htmlcolor,
|
||||||
|
colorpicker_recentcolors,
|
||||||
|
colorpicker_red,
|
||||||
|
colorpicker_title,
|
||||||
|
colorpicker_transparent,
|
||||||
|
config_unauthorizedaccess_write,
|
||||||
|
contextmenu_about,
|
||||||
|
contextmenu_capturearea,
|
||||||
|
contextmenu_captureclipboard,
|
||||||
|
contextmenu_capturefullscreen,
|
||||||
|
contextmenu_capturefullscreen_all,
|
||||||
|
contextmenu_capturefullscreen_left,
|
||||||
|
contextmenu_capturefullscreen_top,
|
||||||
|
contextmenu_capturefullscreen_right,
|
||||||
|
contextmenu_capturefullscreen_bottom,
|
||||||
|
contextmenu_capturelastregion,
|
||||||
|
contextmenu_capturewindow,
|
||||||
|
contextmenu_donate,
|
||||||
|
contextmenu_exit,
|
||||||
|
contextmenu_help,
|
||||||
|
contextmenu_openfile,
|
||||||
|
contextmenu_quicksettings,
|
||||||
|
contextmenu_settings,
|
||||||
|
contextmenu_captureie,
|
||||||
|
contextmenu_openrecentcapture,
|
||||||
|
editor_align_bottom,
|
||||||
|
editor_align_center,
|
||||||
|
editor_align_horizontal,
|
||||||
|
editor_align_middle,
|
||||||
|
editor_align_left,
|
||||||
|
editor_align_right,
|
||||||
|
editor_align_top,
|
||||||
|
editor_align_vertical,
|
||||||
|
editor_arrange,
|
||||||
|
editor_arrowheads,
|
||||||
|
editor_arrowheads_both,
|
||||||
|
editor_arrowheads_end,
|
||||||
|
editor_arrowheads_none,
|
||||||
|
editor_arrowheads_start,
|
||||||
|
editor_backcolor,
|
||||||
|
editor_blur_radius,
|
||||||
|
editor_bold,
|
||||||
|
editor_brightness,
|
||||||
|
editor_cancel,
|
||||||
|
editor_clipboardfailed,
|
||||||
|
editor_close,
|
||||||
|
editor_close_on_save,
|
||||||
|
editor_close_on_save_title,
|
||||||
|
editor_confirm,
|
||||||
|
editor_copyimagetoclipboard,
|
||||||
|
editor_copypathtoclipboard,
|
||||||
|
editor_copytoclipboard,
|
||||||
|
editor_crop,
|
||||||
|
editor_cursortool,
|
||||||
|
editor_cuttoclipboard,
|
||||||
|
editor_deleteelement,
|
||||||
|
editor_downonelevel,
|
||||||
|
editor_downtobottom,
|
||||||
|
editor_drawarrow,
|
||||||
|
editor_drawellipse,
|
||||||
|
editor_drawhighlighter,
|
||||||
|
editor_drawline,
|
||||||
|
editor_drawfreehand,
|
||||||
|
editor_drawrectangle,
|
||||||
|
editor_drawtextbox,
|
||||||
|
editor_duplicate,
|
||||||
|
editor_edit,
|
||||||
|
editor_email,
|
||||||
|
editor_file,
|
||||||
|
editor_fontsize,
|
||||||
|
editor_forecolor,
|
||||||
|
editor_highlight_area,
|
||||||
|
editor_highlight_grayscale,
|
||||||
|
editor_highlight_mode,
|
||||||
|
editor_highlight_text,
|
||||||
|
editor_highlight_magnify,
|
||||||
|
editor_pixel_size,
|
||||||
|
editor_imagesaved,
|
||||||
|
editor_italic,
|
||||||
|
editor_load_objects,
|
||||||
|
editor_magnification_factor,
|
||||||
|
editor_match_capture_size,
|
||||||
|
editor_obfuscate,
|
||||||
|
editor_obfuscate_blur,
|
||||||
|
editor_obfuscate_mode,
|
||||||
|
editor_obfuscate_pixelize,
|
||||||
|
editor_object,
|
||||||
|
editor_opendirinexplorer,
|
||||||
|
editor_pastefromclipboard,
|
||||||
|
editor_preview_quality,
|
||||||
|
editor_print,
|
||||||
|
editor_save,
|
||||||
|
editor_save_objects,
|
||||||
|
editor_saveas,
|
||||||
|
editor_selectall,
|
||||||
|
editor_senttoprinter,
|
||||||
|
editor_shadow,
|
||||||
|
editor_torn_edge,
|
||||||
|
editor_border,
|
||||||
|
editor_grayscale,
|
||||||
|
editor_effects,
|
||||||
|
editor_storedtoclipboard,
|
||||||
|
editor_thickness,
|
||||||
|
editor_title,
|
||||||
|
editor_uponelevel,
|
||||||
|
editor_uptotop,
|
||||||
|
editor_autocrop,
|
||||||
|
editor_undo,
|
||||||
|
editor_redo,
|
||||||
|
editor_insertwindow,
|
||||||
|
editor_resetsize,
|
||||||
|
error,
|
||||||
|
error_multipleinstances,
|
||||||
|
error_nowriteaccess,
|
||||||
|
error_openfile,
|
||||||
|
error_openlink,
|
||||||
|
error_save,
|
||||||
|
help_title,
|
||||||
|
jpegqualitydialog_choosejpegquality,
|
||||||
|
qualitydialog_dontaskagain,
|
||||||
|
qualitydialog_title,
|
||||||
|
settings_reducecolors,
|
||||||
|
print_error,
|
||||||
|
printoptions_allowcenter,
|
||||||
|
printoptions_allowenlarge,
|
||||||
|
printoptions_allowrotate,
|
||||||
|
printoptions_allowshrink,
|
||||||
|
printoptions_colors,
|
||||||
|
printoptions_dontaskagain,
|
||||||
|
printoptions_pagelayout,
|
||||||
|
printoptions_printcolor,
|
||||||
|
printoptions_printgrayscale,
|
||||||
|
printoptions_printmonochrome,
|
||||||
|
printoptions_timestamp,
|
||||||
|
printoptions_inverted,
|
||||||
|
printoptions_title,
|
||||||
|
quicksettings_destination_file,
|
||||||
|
settings_alwaysshowqualitydialog,
|
||||||
|
settings_alwaysshowprintoptionsdialog,
|
||||||
|
settings_applicationsettings,
|
||||||
|
settings_autostartshortcut,
|
||||||
|
settings_capture,
|
||||||
|
settings_capture_mousepointer,
|
||||||
|
settings_capture_windows_interactive,
|
||||||
|
settings_copypathtoclipboard,
|
||||||
|
settings_destination,
|
||||||
|
settings_destination_clipboard,
|
||||||
|
settings_destination_editor,
|
||||||
|
settings_destination_email,
|
||||||
|
settings_destination_file,
|
||||||
|
settings_destination_fileas,
|
||||||
|
settings_destination_printer,
|
||||||
|
settings_destination_picker,
|
||||||
|
settings_editor,
|
||||||
|
settings_filenamepattern,
|
||||||
|
settings_general,
|
||||||
|
settings_iecapture,
|
||||||
|
settings_jpegquality,
|
||||||
|
settings_qualitysettings,
|
||||||
|
settings_language,
|
||||||
|
settings_message_filenamepattern,
|
||||||
|
settings_output,
|
||||||
|
settings_playsound,
|
||||||
|
settings_plugins,
|
||||||
|
settings_plugins_name,
|
||||||
|
settings_plugins_version,
|
||||||
|
settings_plugins_createdby,
|
||||||
|
settings_plugins_dllpath,
|
||||||
|
settings_preferredfilesettings,
|
||||||
|
settings_primaryimageformat,
|
||||||
|
settings_printer,
|
||||||
|
settings_printoptions,
|
||||||
|
settings_registerhotkeys,
|
||||||
|
settings_showflashlight,
|
||||||
|
settings_storagelocation,
|
||||||
|
settings_title,
|
||||||
|
settings_tooltip_filenamepattern,
|
||||||
|
settings_tooltip_language,
|
||||||
|
settings_tooltip_primaryimageformat,
|
||||||
|
settings_tooltip_registerhotkeys,
|
||||||
|
settings_tooltip_storagelocation,
|
||||||
|
settings_visualization,
|
||||||
|
settings_shownotify,
|
||||||
|
settings_waittime,
|
||||||
|
settings_windowscapture,
|
||||||
|
settings_window_capture_mode,
|
||||||
|
settings_network,
|
||||||
|
settings_checkperiod,
|
||||||
|
settings_usedefaultproxy,
|
||||||
|
tooltip_firststart,
|
||||||
|
warning,
|
||||||
|
warning_hotkeys,
|
||||||
|
hotkeys,
|
||||||
|
wait_ie_capture,
|
||||||
|
update_found,
|
||||||
|
exported_to
|
||||||
|
}
|
||||||
|
}
|
141
GreenshotImageEditor/Controls/AnimatingForm.cs
Normal file
141
GreenshotImageEditor/Controls/AnimatingForm.cs
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin.UnmanagedHelpers;
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extend this Form to have the possibility for animations on your form
|
||||||
|
/// </summary>
|
||||||
|
public class AnimatingForm : GreenshotForm
|
||||||
|
{
|
||||||
|
private const int DEFAULT_VREFRESH = 60;
|
||||||
|
private int vRefresh = 0;
|
||||||
|
private Timer timer = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This flag specifies if any animation is used
|
||||||
|
/// </summary>
|
||||||
|
protected bool EnableAnimation
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vertical Refresh Rate
|
||||||
|
/// </summary>
|
||||||
|
protected int VRefresh
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (vRefresh == 0)
|
||||||
|
{
|
||||||
|
// get te hDC of the desktop to get the VREFRESH
|
||||||
|
using (SafeWindowDCHandle desktopHandle = SafeWindowDCHandle.fromDesktop())
|
||||||
|
{
|
||||||
|
vRefresh = GDI32.GetDeviceCaps(desktopHandle, DeviceCaps.VREFRESH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// A vertical refresh rate value of 0 or 1 represents the display hardware's default refresh rate.
|
||||||
|
// As there is currently no know way to get the default, we guess it.
|
||||||
|
if (vRefresh <= 1)
|
||||||
|
{
|
||||||
|
vRefresh = DEFAULT_VREFRESH;
|
||||||
|
}
|
||||||
|
return vRefresh;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if we are in a Terminal Server session OR need to optimize for RDP / remote desktop connections
|
||||||
|
/// </summary>
|
||||||
|
protected bool isTerminalServerSession
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return coreConfiguration.OptimizeForRDP || SystemInformation.TerminalServerSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate the amount of frames that an animation takes
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="milliseconds"></param>
|
||||||
|
/// <returns>Number of frames, 1 if in Terminal Server Session</returns>
|
||||||
|
protected int FramesForMillis(int milliseconds)
|
||||||
|
{
|
||||||
|
// If we are in a Terminal Server Session we return 1
|
||||||
|
if (isTerminalServerSession)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return milliseconds / VRefresh;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize the animation
|
||||||
|
/// </summary>
|
||||||
|
protected AnimatingForm()
|
||||||
|
{
|
||||||
|
Load += delegate
|
||||||
|
{
|
||||||
|
if (EnableAnimation)
|
||||||
|
{
|
||||||
|
timer = new Timer();
|
||||||
|
timer.Interval = 1000 / VRefresh;
|
||||||
|
timer.Tick += timer_Tick;
|
||||||
|
timer.Start();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Unregister at close
|
||||||
|
FormClosing += delegate
|
||||||
|
{
|
||||||
|
if (timer != null)
|
||||||
|
{
|
||||||
|
timer.Stop();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The tick handler initiates the animation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void timer_Tick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Animate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will be called every frame, so implement your animation/redraw logic here.
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void Animate()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
116
GreenshotImageEditor/Controls/BackgroundForm.cs
Normal file
116
GreenshotImageEditor/Controls/BackgroundForm.cs
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of PleaseWaitForm.
|
||||||
|
/// </summary>
|
||||||
|
public partial class BackgroundForm : Form
|
||||||
|
{
|
||||||
|
private volatile bool shouldClose = false;
|
||||||
|
|
||||||
|
private void BackgroundShowDialog()
|
||||||
|
{
|
||||||
|
ShowDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BackgroundForm ShowAndWait(string title, string text)
|
||||||
|
{
|
||||||
|
BackgroundForm backgroundForm = new BackgroundForm(title, text);
|
||||||
|
// Show form in background thread
|
||||||
|
Thread backgroundTask = new Thread(backgroundForm.BackgroundShowDialog);
|
||||||
|
backgroundForm.Name = "Background form";
|
||||||
|
backgroundTask.IsBackground = true;
|
||||||
|
backgroundTask.SetApartmentState(ApartmentState.STA);
|
||||||
|
backgroundTask.Start();
|
||||||
|
return backgroundForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BackgroundForm(string title, string text)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||||
|
//
|
||||||
|
InitializeComponent();
|
||||||
|
Icon = GreenshotResources.getGreenshotIcon();
|
||||||
|
shouldClose = false;
|
||||||
|
Text = title;
|
||||||
|
label_pleasewait.Text = text;
|
||||||
|
FormClosing += PreventFormClose;
|
||||||
|
timer_checkforclose.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can be used instead of ShowDialog
|
||||||
|
public new void Show()
|
||||||
|
{
|
||||||
|
base.Show();
|
||||||
|
bool positioned = false;
|
||||||
|
foreach (Screen screen in Screen.AllScreens)
|
||||||
|
{
|
||||||
|
if (screen.Bounds.Contains(Cursor.Position))
|
||||||
|
{
|
||||||
|
positioned = true;
|
||||||
|
Location = new Point(screen.Bounds.X + (screen.Bounds.Width / 2) - (Width / 2), screen.Bounds.Y + (screen.Bounds.Height / 2) - (Height / 2));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!positioned)
|
||||||
|
{
|
||||||
|
Location = new Point(Cursor.Position.X - Width / 2, Cursor.Position.Y - Height / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PreventFormClose(object sender, FormClosingEventArgs e)
|
||||||
|
{
|
||||||
|
if (!shouldClose)
|
||||||
|
{
|
||||||
|
e.Cancel = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Timer_checkforcloseTick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (shouldClose)
|
||||||
|
{
|
||||||
|
timer_checkforclose.Stop();
|
||||||
|
BeginInvoke(new EventHandler(delegate { Close(); }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CloseDialog()
|
||||||
|
{
|
||||||
|
shouldClose = true;
|
||||||
|
Application.DoEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BackgroundFormFormClosing(object sender, FormClosingEventArgs e)
|
||||||
|
{
|
||||||
|
timer_checkforclose.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
GreenshotImageEditor/Controls/BackgroundForm.designer.cs
generated
Normal file
99
GreenshotImageEditor/Controls/BackgroundForm.designer.cs
generated
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
partial class BackgroundForm
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Designer variable used to keep track of non-visual components.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes resources used by the form.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing) {
|
||||||
|
if (components != null) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method is required for Windows Forms designer support.
|
||||||
|
/// Do not change the method contents inside the source code editor. The Forms designer might
|
||||||
|
/// not be able to load this method if it was changed manually.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.components = new System.ComponentModel.Container();
|
||||||
|
this.label_pleasewait = new System.Windows.Forms.Label();
|
||||||
|
this.timer_checkforclose = new System.Windows.Forms.Timer(this.components);
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// label_pleasewait
|
||||||
|
//
|
||||||
|
this.label_pleasewait.AutoSize = true;
|
||||||
|
this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.label_pleasewait.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.label_pleasewait.Name = "label_pleasewait";
|
||||||
|
this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10);
|
||||||
|
this.label_pleasewait.Size = new System.Drawing.Size(90, 33);
|
||||||
|
this.label_pleasewait.TabIndex = 0;
|
||||||
|
this.label_pleasewait.Text = "Please wait...";
|
||||||
|
this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.label_pleasewait.UseWaitCursor = true;
|
||||||
|
//
|
||||||
|
// timer_checkforclose
|
||||||
|
//
|
||||||
|
this.timer_checkforclose.Interval = 200;
|
||||||
|
this.timer_checkforclose.Tick += new System.EventHandler(this.Timer_checkforcloseTick);
|
||||||
|
//
|
||||||
|
// BackgroundForm
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.AutoSize = true;
|
||||||
|
this.ClientSize = new System.Drawing.Size(169, 52);
|
||||||
|
this.ControlBox = true;
|
||||||
|
this.Controls.Add(this.label_pleasewait);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "BackgroundForm";
|
||||||
|
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.Text = "Greenshot";
|
||||||
|
this.TopMost = true;
|
||||||
|
this.UseWaitCursor = true;
|
||||||
|
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.BackgroundFormFormClosing);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
}
|
||||||
|
private System.Windows.Forms.Timer timer_checkforclose;
|
||||||
|
private System.Windows.Forms.Label label_pleasewait;
|
||||||
|
}
|
||||||
|
}
|
54
GreenshotImageEditor/Controls/BindableToolStripButton.cs
Normal file
54
GreenshotImageEditor/Controls/BindableToolStripButton.cs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin.Controls;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of BindableToolStripButton.
|
||||||
|
/// </summary>
|
||||||
|
public class BindableToolStripButton : ToolStripButton, INotifyPropertyChanged, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindableToolStripButton()
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
CheckedChanged += BindableToolStripButton_CheckedChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindableToolStripButton_CheckedChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Checked"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
GreenshotImageEditor/Controls/BindableToolStripComboBox.cs
Normal file
57
GreenshotImageEditor/Controls/BindableToolStripComboBox.cs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin.Controls;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A simple ToolStripComboBox implementing INotifyPropertyChanged for data binding
|
||||||
|
/// </summary>
|
||||||
|
public class BindableToolStripComboBox : ToolStripComboBox, INotifyPropertyChanged, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindableToolStripComboBox()
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (PropertyChanged != null)
|
||||||
|
{
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin.Controls;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A simple ToolStripDropDownButton implementing INotifyPropertyChanged for data binding.
|
||||||
|
/// Also, when a DropDownItem is selected, the DropDownButton adops its Tag and Image.
|
||||||
|
/// The selected tag can be accessed via SelectedTag property.
|
||||||
|
/// </summary>
|
||||||
|
public class BindableToolStripDropDownButton : ToolStripDropDownButton, INotifyPropertyChanged, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindableToolStripDropDownButton()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public object SelectedTag
|
||||||
|
{
|
||||||
|
get { if (Tag == null && DropDownItems.Count > 0) Tag = DropDownItems[0].Tag; return Tag; }
|
||||||
|
set { AdoptFromTag(value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnDropDownItemClicked(ToolStripItemClickedEventArgs e)
|
||||||
|
{
|
||||||
|
ToolStripItem clickedItem = e.ClickedItem;
|
||||||
|
if (Tag == null || !Tag.Equals(clickedItem.Tag))
|
||||||
|
{
|
||||||
|
Tag = clickedItem.Tag;
|
||||||
|
Image = clickedItem.Image;
|
||||||
|
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("SelectedTag"));
|
||||||
|
}
|
||||||
|
base.OnDropDownItemClicked(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AdoptFromTag(object tag)
|
||||||
|
{
|
||||||
|
if (Tag == null || !Tag.Equals(tag))
|
||||||
|
{
|
||||||
|
Tag = tag;
|
||||||
|
foreach (ToolStripItem item in DropDownItems)
|
||||||
|
{
|
||||||
|
if (item.Tag != null && item.Tag.Equals(tag))
|
||||||
|
{
|
||||||
|
Image = item.Image;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tag = tag;
|
||||||
|
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("SelectedTag"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
101
GreenshotImageEditor/Controls/ColorButton.cs
Normal file
101
GreenshotImageEditor/Controls/ColorButton.cs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin.Controls;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of ColorButton.
|
||||||
|
/// </summary>
|
||||||
|
public class ColorButton : Button, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColorButton()
|
||||||
|
{
|
||||||
|
Click += ColorButtonClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color SelectedColor
|
||||||
|
{
|
||||||
|
get { return selectedColor; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
selectedColor = value;
|
||||||
|
|
||||||
|
Brush brush;
|
||||||
|
if (value != Color.Transparent)
|
||||||
|
{
|
||||||
|
brush = new SolidBrush(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
brush = new HatchBrush(HatchStyle.Percent50, Color.White, Color.Gray);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Image != null)
|
||||||
|
{
|
||||||
|
using (Graphics graphics = Graphics.FromImage(Image))
|
||||||
|
{
|
||||||
|
graphics.FillRectangle(brush, new Rectangle(4, 17, 16, 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup GDI Object
|
||||||
|
brush.Dispose();
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
GreenshotImageEditor/Controls/FontFamilyComboBox.cs
Normal file
68
GreenshotImageEditor/Controls/FontFamilyComboBox.cs
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ToolStripComboBox containing installed font families,
|
||||||
|
/// implementing INotifyPropertyChanged for data binding
|
||||||
|
/// </summary>
|
||||||
|
public class FontFamilyComboBox : ToolStripComboBox, INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
public FontFamily FontFamily
|
||||||
|
{
|
||||||
|
get { return (FontFamily)SelectedItem; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!SelectedItem.Equals(value))
|
||||||
|
{
|
||||||
|
SelectedItem = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public FontFamilyComboBox()
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
ComboBox.DataSource = FontFamily.Families;
|
||||||
|
ComboBox.DisplayMember = "Name";
|
||||||
|
SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (PropertyChanged != null)
|
||||||
|
{
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs("Text"));
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs("FontFamily"));
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs("SelectedIndex"));
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
GreenshotImageEditor/Controls/FormWithoutActivation.cs
Normal file
36
GreenshotImageEditor/Controls/FormWithoutActivation.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// FormWithoutActivation is exactly like a normal form, but doesn't activate (steal focus)
|
||||||
|
/// </summary>
|
||||||
|
public class FormWithoutActivation : Form
|
||||||
|
{
|
||||||
|
protected override bool ShowWithoutActivation
|
||||||
|
{
|
||||||
|
get { return true; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
GreenshotImageEditor/Controls/GreenshotButton.cs
Normal file
36
GreenshotImageEditor/Controls/GreenshotButton.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public class GreenshotButton : Button, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
GreenshotImageEditor/Controls/GreenshotCheckBox.cs
Normal file
60
GreenshotImageEditor/Controls/GreenshotCheckBox.cs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of GreenshotCheckbox.
|
||||||
|
/// </summary>
|
||||||
|
public class GreenshotCheckBox : CheckBox, IGreenshotLanguageBindable, IGreenshotConfigBindable
|
||||||
|
{
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string sectionName = "Core";
|
||||||
|
[Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
|
||||||
|
public string SectionName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return sectionName;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
sectionName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")]
|
||||||
|
public string PropertyName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
138
GreenshotImageEditor/Controls/GreenshotColumnSorter.cs
Normal file
138
GreenshotImageEditor/Controls/GreenshotColumnSorter.cs
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class is an implementation of the 'IComparer' interface.
|
||||||
|
/// </summary>
|
||||||
|
public class GreenshotColumnSorter : IComparer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the column to be sorted
|
||||||
|
/// </summary>
|
||||||
|
private int ColumnToSort;
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the order in which to sort (i.e. 'Ascending').
|
||||||
|
/// </summary>
|
||||||
|
private SortOrder OrderOfSort;
|
||||||
|
/// <summary>
|
||||||
|
/// Case insensitive comparer object
|
||||||
|
/// </summary>
|
||||||
|
private CaseInsensitiveComparer ObjectCompare;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Class constructor. Initializes various elements
|
||||||
|
/// </summary>
|
||||||
|
public GreenshotColumnSorter()
|
||||||
|
{
|
||||||
|
// Initialize the column to '0'
|
||||||
|
ColumnToSort = 0;
|
||||||
|
|
||||||
|
// Initialize the sort order to 'none'
|
||||||
|
OrderOfSort = SortOrder.None;
|
||||||
|
|
||||||
|
// Initialize the CaseInsensitiveComparer object
|
||||||
|
ObjectCompare = new CaseInsensitiveComparer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method is inherited from the IComparer interface. It compares the two objects passed using a case insensitive comparison.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">First object to be compared</param>
|
||||||
|
/// <param name="y">Second object to be compared</param>
|
||||||
|
/// <returns>The result of the comparison. "0" if equal, negative if 'x' is less than 'y' and positive if 'x' is greater than 'y'</returns>
|
||||||
|
public int Compare(object x, object y)
|
||||||
|
{
|
||||||
|
int compareResult;
|
||||||
|
ListViewItem listviewX, listviewY;
|
||||||
|
|
||||||
|
if (x == null && y == null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (x == null && y != null)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (x != null && y == null)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// Cast the objects to be compared to ListViewItem objects
|
||||||
|
listviewX = (ListViewItem)x;
|
||||||
|
listviewY = (ListViewItem)y;
|
||||||
|
|
||||||
|
// Compare the two items
|
||||||
|
compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
|
||||||
|
|
||||||
|
// Calculate correct return value based on object comparison
|
||||||
|
if (OrderOfSort == SortOrder.Ascending)
|
||||||
|
{
|
||||||
|
// Ascending sort is selected, return normal result of compare operation
|
||||||
|
return compareResult;
|
||||||
|
}
|
||||||
|
else if (OrderOfSort == SortOrder.Descending)
|
||||||
|
{
|
||||||
|
// Descending sort is selected, return negative result of compare operation
|
||||||
|
return (-compareResult);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Return '0' to indicate they are equal
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the number of the column to which to apply the sorting operation (Defaults to '0').
|
||||||
|
/// </summary>
|
||||||
|
public int SortColumn
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
ColumnToSort = value;
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return ColumnToSort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the order of sorting to apply (for example, 'Ascending' or 'Descending').
|
||||||
|
/// </summary>
|
||||||
|
public SortOrder Order
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
OrderOfSort = value;
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return OrderOfSort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
132
GreenshotImageEditor/Controls/GreenshotComboBox.cs
Normal file
132
GreenshotImageEditor/Controls/GreenshotComboBox.cs
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public class GreenshotComboBox : ComboBox, IGreenshotConfigBindable
|
||||||
|
{
|
||||||
|
private Type enumType = null;
|
||||||
|
private Enum selectedEnum = null;
|
||||||
|
private string sectionName = "Core";
|
||||||
|
[Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
|
||||||
|
public string SectionName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return sectionName;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
sectionName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")]
|
||||||
|
public string PropertyName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GreenshotComboBox()
|
||||||
|
{
|
||||||
|
SelectedIndexChanged += delegate
|
||||||
|
{
|
||||||
|
StoreSelectedEnum();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetValue(Enum currentValue)
|
||||||
|
{
|
||||||
|
if (currentValue != null)
|
||||||
|
{
|
||||||
|
selectedEnum = currentValue;
|
||||||
|
SelectedItem = Language.Translate(currentValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This is a method to popululate the ComboBox
|
||||||
|
/// with the items from the enumeration
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="enumType">TEnum to populate with</param>
|
||||||
|
public void Populate(Type enumType)
|
||||||
|
{
|
||||||
|
// Store the enum-type, so we can work with it
|
||||||
|
this.enumType = enumType;
|
||||||
|
|
||||||
|
var availableValues = Enum.GetValues(enumType);
|
||||||
|
Items.Clear();
|
||||||
|
string enumTypeName = enumType.Name;
|
||||||
|
foreach (var enumValue in availableValues)
|
||||||
|
{
|
||||||
|
Items.Add(Language.Translate((Enum)enumValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Store the selected value internally
|
||||||
|
/// </summary>
|
||||||
|
private void StoreSelectedEnum()
|
||||||
|
{
|
||||||
|
string enumTypeName = enumType.Name;
|
||||||
|
string selectedValue = SelectedItem as string;
|
||||||
|
var availableValues = Enum.GetValues(enumType);
|
||||||
|
object returnValue = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
returnValue = Enum.Parse(enumType, selectedValue);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Enum enumValue in availableValues)
|
||||||
|
{
|
||||||
|
string enumKey = enumTypeName + "." + enumValue.ToString();
|
||||||
|
if (Language.hasKey(enumKey))
|
||||||
|
{
|
||||||
|
string translation = Language.GetString(enumTypeName + "." + enumValue.ToString());
|
||||||
|
if (translation.Equals(selectedValue))
|
||||||
|
{
|
||||||
|
returnValue = enumValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectedEnum = (Enum)returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the selected enum value from the combobox, uses generics
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The enum value of the combobox</returns>
|
||||||
|
public Enum GetSelectedEnum()
|
||||||
|
{
|
||||||
|
return selectedEnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
635
GreenshotImageEditor/Controls/GreenshotForm.cs
Normal file
635
GreenshotImageEditor/Controls/GreenshotForm.cs
Normal file
|
@ -0,0 +1,635 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.ComponentModel.Design;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This form is used for automatically binding the elements of the form to the language
|
||||||
|
/// </summary>
|
||||||
|
public class GreenshotForm : Form, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
protected static CoreConfiguration coreConfiguration;
|
||||||
|
private static IDictionary<Type, FieldInfo[]> reflectionCache = new Dictionary<Type, FieldInfo[]>();
|
||||||
|
private IComponentChangeService m_changeService;
|
||||||
|
private bool isDesignModeLanguageSet = false;
|
||||||
|
private bool applyLanguageManually = false;
|
||||||
|
private bool storeFieldsManually = false;
|
||||||
|
private IDictionary<string, Control> designTimeControls;
|
||||||
|
private IDictionary<string, ToolStripItem> designTimeToolStripItems;
|
||||||
|
|
||||||
|
static GreenshotForm()
|
||||||
|
{
|
||||||
|
if (!IsInDesignMode)
|
||||||
|
{
|
||||||
|
coreConfiguration = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to check the designmode during a constructor
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected static bool IsInDesignMode
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) > -1) || (Application.ExecutablePath.IndexOf("sharpdevelop.exe", StringComparison.OrdinalIgnoreCase) > -1 || (Application.ExecutablePath.IndexOf("wdexpress.exe", StringComparison.OrdinalIgnoreCase) > -1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool ManualLanguageApply
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return applyLanguageManually;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
applyLanguageManually = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool ManualStoreFields
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return storeFieldsManually;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
storeFieldsManually = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Code to initialize the language etc during design time
|
||||||
|
/// </summary>
|
||||||
|
protected void InitializeForDesigner()
|
||||||
|
{
|
||||||
|
if (DesignMode)
|
||||||
|
{
|
||||||
|
designTimeControls = new Dictionary<string, Control>();
|
||||||
|
designTimeToolStripItems = new Dictionary<string, ToolStripItem>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ITypeResolutionService typeResService = GetService(typeof(ITypeResolutionService)) as ITypeResolutionService;
|
||||||
|
|
||||||
|
// Add a hard-path if you are using SharpDevelop
|
||||||
|
// Language.AddLanguageFilePath(@"C:\Greenshot\Greenshot\Languages");
|
||||||
|
|
||||||
|
// this "type"
|
||||||
|
Assembly currentAssembly = GetType().Assembly;
|
||||||
|
string assemblyPath = typeResService.GetPathOfAssembly(currentAssembly.GetName());
|
||||||
|
string assemblyDirectory = Path.GetDirectoryName(assemblyPath);
|
||||||
|
if (!Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\Greenshot\Languages\")))
|
||||||
|
{
|
||||||
|
Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\..\Greenshot\Languages\"));
|
||||||
|
}
|
||||||
|
if (!Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\Languages\")))
|
||||||
|
{
|
||||||
|
Language.AddLanguageFilePath(Path.Combine(assemblyDirectory, @"..\..\..\Languages\"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This override is only for the design-time of the form
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
protected override void OnPaint(PaintEventArgs e)
|
||||||
|
{
|
||||||
|
if (DesignMode)
|
||||||
|
{
|
||||||
|
if (!isDesignModeLanguageSet)
|
||||||
|
{
|
||||||
|
isDesignModeLanguageSet = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ApplyLanguage();
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.OnPaint(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnLoad(EventArgs e)
|
||||||
|
{
|
||||||
|
if (!DesignMode)
|
||||||
|
{
|
||||||
|
if (!applyLanguageManually)
|
||||||
|
{
|
||||||
|
ApplyLanguage();
|
||||||
|
}
|
||||||
|
FillFields();
|
||||||
|
base.OnLoad(e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.Info("OnLoad called from designer.");
|
||||||
|
InitializeForDesigner();
|
||||||
|
base.OnLoad(e);
|
||||||
|
ApplyLanguage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// check if the form was closed with an OK, if so store the values in the GreenshotControls
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
protected override void OnClosed(EventArgs e)
|
||||||
|
{
|
||||||
|
if (!DesignMode && !storeFieldsManually)
|
||||||
|
{
|
||||||
|
if (DialogResult == DialogResult.OK)
|
||||||
|
{
|
||||||
|
LOG.Info("Form was closed with OK: storing field values.");
|
||||||
|
StoreFields();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.OnClosed(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This override allows the control to register event handlers for IComponentChangeService events
|
||||||
|
/// at the time the control is sited, which happens only in design mode.
|
||||||
|
/// </summary>
|
||||||
|
public override ISite Site
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return base.Site;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// Clear any component change event handlers.
|
||||||
|
ClearChangeNotifications();
|
||||||
|
|
||||||
|
// Set the new Site value.
|
||||||
|
base.Site = value;
|
||||||
|
|
||||||
|
m_changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService));
|
||||||
|
|
||||||
|
// Register event handlers for component change events.
|
||||||
|
RegisterChangeNotifications();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearChangeNotifications()
|
||||||
|
{
|
||||||
|
// The m_changeService value is null when not in design mode,
|
||||||
|
// as the IComponentChangeService is only available at design time.
|
||||||
|
m_changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService));
|
||||||
|
|
||||||
|
// Clear our the component change events to prepare for re-siting.
|
||||||
|
if (m_changeService != null)
|
||||||
|
{
|
||||||
|
m_changeService.ComponentChanged -= OnComponentChanged;
|
||||||
|
m_changeService.ComponentAdded -= OnComponentAdded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RegisterChangeNotifications()
|
||||||
|
{
|
||||||
|
// Register the event handlers for the IComponentChangeService events
|
||||||
|
if (m_changeService != null)
|
||||||
|
{
|
||||||
|
m_changeService.ComponentChanged += OnComponentChanged;
|
||||||
|
m_changeService.ComponentAdded += OnComponentAdded;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method handles the OnComponentChanged event to display a notification.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="ce"></param>
|
||||||
|
private void OnComponentChanged(object sender, ComponentChangedEventArgs ce)
|
||||||
|
{
|
||||||
|
if (ce.Component != null && ((IComponent)ce.Component).Site != null && ce.Member != null)
|
||||||
|
{
|
||||||
|
if ("LanguageKey".Equals(ce.Member.Name))
|
||||||
|
{
|
||||||
|
Control control = ce.Component as Control;
|
||||||
|
if (control != null)
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Changing LanguageKey for {0} to {1}", control.Name, ce.NewValue);
|
||||||
|
ApplyLanguage(control, (string)ce.NewValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ToolStripItem item = ce.Component as ToolStripItem;
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Changing LanguageKey for {0} to {1}", item.Name, ce.NewValue);
|
||||||
|
ApplyLanguage(item, (string)ce.NewValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Not possible to changing LanguageKey for {0} to {1}", ce.Component.GetType(), ce.NewValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnComponentAdded(object sender, ComponentEventArgs ce)
|
||||||
|
{
|
||||||
|
if (ce.Component != null && ((IComponent)ce.Component).Site != null)
|
||||||
|
{
|
||||||
|
Control control = ce.Component as Control;
|
||||||
|
if (control != null)
|
||||||
|
{
|
||||||
|
if (!designTimeControls.ContainsKey(control.Name))
|
||||||
|
{
|
||||||
|
designTimeControls.Add(control.Name, control);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
designTimeControls[control.Name] = control;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ce.Component is ToolStripItem)
|
||||||
|
{
|
||||||
|
ToolStripItem item = ce.Component as ToolStripItem;
|
||||||
|
if (!designTimeControls.ContainsKey(item.Name))
|
||||||
|
{
|
||||||
|
designTimeToolStripItems.Add(item.Name, item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
designTimeToolStripItems[item.Name] = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up any resources being used.
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
ClearChangeNotifications();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ApplyLanguage(ToolStripItem applyTo, string languageKey)
|
||||||
|
{
|
||||||
|
string langString = null;
|
||||||
|
if (!string.IsNullOrEmpty(languageKey))
|
||||||
|
{
|
||||||
|
if (!Language.TryGetString(languageKey, out langString))
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("Unknown language key '{0}' configured for control '{1}', this might be okay.", languageKey, applyTo.Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applyTo.Text = langString;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback to control name!
|
||||||
|
if (Language.TryGetString(applyTo.Name, out langString))
|
||||||
|
{
|
||||||
|
applyTo.Text = langString;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!DesignMode)
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Greenshot control without language key: {0}", applyTo.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ApplyLanguage(ToolStripItem applyTo)
|
||||||
|
{
|
||||||
|
IGreenshotLanguageBindable languageBindable = applyTo as IGreenshotLanguageBindable;
|
||||||
|
if (languageBindable != null)
|
||||||
|
{
|
||||||
|
ApplyLanguage(applyTo, languageBindable.LanguageKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void ApplyLanguage(Control applyTo)
|
||||||
|
{
|
||||||
|
IGreenshotLanguageBindable languageBindable = applyTo as IGreenshotLanguageBindable;
|
||||||
|
if (languageBindable == null)
|
||||||
|
{
|
||||||
|
// check if it's a menu!
|
||||||
|
ToolStrip toolStrip = applyTo as ToolStrip;
|
||||||
|
if (toolStrip != null)
|
||||||
|
{
|
||||||
|
foreach (ToolStripItem item in toolStrip.Items)
|
||||||
|
{
|
||||||
|
ApplyLanguage(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply language text to the control
|
||||||
|
ApplyLanguage(applyTo, languageBindable.LanguageKey);
|
||||||
|
|
||||||
|
// Repopulate the combox boxes
|
||||||
|
IGreenshotConfigBindable configBindable = applyTo as IGreenshotConfigBindable;
|
||||||
|
GreenshotComboBox comboxBox = applyTo as GreenshotComboBox;
|
||||||
|
if (configBindable != null && comboxBox != null)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(configBindable.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName))
|
||||||
|
{
|
||||||
|
IniSection section = IniConfig.GetIniSection(configBindable.SectionName);
|
||||||
|
if (section != null)
|
||||||
|
{
|
||||||
|
// Only update the language, so get the actual value and than repopulate
|
||||||
|
Enum currentValue = (Enum)comboxBox.GetSelectedEnum();
|
||||||
|
comboxBox.Populate(section.Values[configBindable.PropertyName].ValueType);
|
||||||
|
comboxBox.SetValue(currentValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to cache the fieldinfo values, so we don't need to reflect all the time!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="typeToGetFieldsFor"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static FieldInfo[] GetCachedFields(Type typeToGetFieldsFor)
|
||||||
|
{
|
||||||
|
FieldInfo[] fields = null;
|
||||||
|
if (!reflectionCache.TryGetValue(typeToGetFieldsFor, out fields))
|
||||||
|
{
|
||||||
|
fields = typeToGetFieldsFor.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
|
reflectionCache.Add(typeToGetFieldsFor, fields);
|
||||||
|
}
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply all the language settings to the "Greenshot" Controls on this form
|
||||||
|
/// </summary>
|
||||||
|
protected void ApplyLanguage()
|
||||||
|
{
|
||||||
|
string langString = null;
|
||||||
|
SuspendLayout();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Set title of the form
|
||||||
|
if (!string.IsNullOrEmpty(LanguageKey) && Language.TryGetString(LanguageKey, out langString))
|
||||||
|
{
|
||||||
|
Text = langString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the text values for all GreenshotControls
|
||||||
|
foreach (FieldInfo field in GetCachedFields(GetType()))
|
||||||
|
{
|
||||||
|
Object controlObject = field.GetValue(this);
|
||||||
|
if (controlObject == null)
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("No value: {0}", field.Name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Control applyToControl = controlObject as Control;
|
||||||
|
if (applyToControl == null)
|
||||||
|
{
|
||||||
|
ToolStripItem applyToItem = controlObject as ToolStripItem;
|
||||||
|
if (applyToItem == null)
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("No Control or ToolStripItem: {0}", field.Name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ApplyLanguage(applyToItem);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplyLanguage(applyToControl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DesignMode)
|
||||||
|
{
|
||||||
|
foreach (Control designControl in designTimeControls.Values)
|
||||||
|
{
|
||||||
|
ApplyLanguage(designControl);
|
||||||
|
}
|
||||||
|
foreach (ToolStripItem designToolStripItem in designTimeToolStripItems.Values)
|
||||||
|
{
|
||||||
|
ApplyLanguage(designToolStripItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
ResumeLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply the language text to supplied control
|
||||||
|
/// </summary>
|
||||||
|
protected void ApplyLanguage(Control applyTo, string languageKey)
|
||||||
|
{
|
||||||
|
string langString = null;
|
||||||
|
if (!string.IsNullOrEmpty(languageKey))
|
||||||
|
{
|
||||||
|
if (!Language.TryGetString(languageKey, out langString))
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("Wrong language key '{0}' configured for control '{1}'", languageKey, applyTo.Name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applyTo.Text = langString;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Fallback to control name!
|
||||||
|
if (Language.TryGetString(applyTo.Name, out langString))
|
||||||
|
{
|
||||||
|
applyTo.Text = langString;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!DesignMode)
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Greenshot control without language key: {0}", applyTo.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fill all GreenshotControls with the values from the configuration
|
||||||
|
/// </summary>
|
||||||
|
protected void FillFields()
|
||||||
|
{
|
||||||
|
foreach (FieldInfo field in GetCachedFields(GetType()))
|
||||||
|
{
|
||||||
|
Object controlObject = field.GetValue(this);
|
||||||
|
if (controlObject == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IGreenshotConfigBindable configBindable = controlObject as IGreenshotConfigBindable;
|
||||||
|
if (configBindable == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(configBindable.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName))
|
||||||
|
{
|
||||||
|
IniSection section = IniConfig.GetIniSection(configBindable.SectionName);
|
||||||
|
if (section != null)
|
||||||
|
{
|
||||||
|
IniValue iniValue = null;
|
||||||
|
if (!section.Values.TryGetValue(configBindable.PropertyName, out iniValue))
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("Wrong property '{0}' configured for field '{1}'", configBindable.PropertyName, field.Name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckBox checkBox = controlObject as CheckBox;
|
||||||
|
if (checkBox != null)
|
||||||
|
{
|
||||||
|
checkBox.Checked = (bool)iniValue.Value;
|
||||||
|
checkBox.Enabled = !iniValue.IsFixed;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RadioButton radíoButton = controlObject as RadioButton;
|
||||||
|
if (radíoButton != null)
|
||||||
|
{
|
||||||
|
radíoButton.Checked = (bool)iniValue.Value;
|
||||||
|
radíoButton.Enabled = !iniValue.IsFixed;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextBox textBox = controlObject as TextBox;
|
||||||
|
if (textBox != null)
|
||||||
|
{
|
||||||
|
textBox.Text = iniValue.ToString();
|
||||||
|
textBox.Enabled = !iniValue.IsFixed;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GreenshotComboBox comboxBox = controlObject as GreenshotComboBox;
|
||||||
|
if (comboxBox != null)
|
||||||
|
{
|
||||||
|
comboxBox.Populate(iniValue.ValueType);
|
||||||
|
comboxBox.SetValue((Enum)iniValue.Value);
|
||||||
|
comboxBox.Enabled = !iniValue.IsFixed;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OnFieldsFilled();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnFieldsFilled()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Store all GreenshotControl values to the configuration
|
||||||
|
/// </summary>
|
||||||
|
protected void StoreFields()
|
||||||
|
{
|
||||||
|
bool iniDirty = false;
|
||||||
|
foreach (FieldInfo field in GetCachedFields(GetType()))
|
||||||
|
{
|
||||||
|
Object controlObject = field.GetValue(this);
|
||||||
|
if (controlObject == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
IGreenshotConfigBindable configBindable = controlObject as IGreenshotConfigBindable;
|
||||||
|
if (configBindable == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(configBindable.SectionName) && !string.IsNullOrEmpty(configBindable.PropertyName))
|
||||||
|
{
|
||||||
|
IniSection section = IniConfig.GetIniSection(configBindable.SectionName);
|
||||||
|
if (section != null)
|
||||||
|
{
|
||||||
|
IniValue iniValue = null;
|
||||||
|
if (!section.Values.TryGetValue(configBindable.PropertyName, out iniValue))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CheckBox checkBox = controlObject as CheckBox;
|
||||||
|
if (checkBox != null)
|
||||||
|
{
|
||||||
|
iniValue.Value = checkBox.Checked;
|
||||||
|
iniDirty = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
RadioButton radioButton = controlObject as RadioButton;
|
||||||
|
if (radioButton != null)
|
||||||
|
{
|
||||||
|
iniValue.Value = radioButton.Checked;
|
||||||
|
iniDirty = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TextBox textBox = controlObject as TextBox;
|
||||||
|
if (textBox != null)
|
||||||
|
{
|
||||||
|
iniValue.UseValueOrDefault(textBox.Text);
|
||||||
|
iniDirty = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
GreenshotComboBox comboxBox = controlObject as GreenshotComboBox;
|
||||||
|
if (comboxBox != null)
|
||||||
|
{
|
||||||
|
iniValue.Value = comboxBox.GetSelectedEnum();
|
||||||
|
iniDirty = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (iniDirty)
|
||||||
|
{
|
||||||
|
//IniConfig.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
GreenshotImageEditor/Controls/GreenshotGroupBox.cs
Normal file
36
GreenshotImageEditor/Controls/GreenshotGroupBox.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public class GreenshotGroupBox : GroupBox, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
GreenshotImageEditor/Controls/GreenshotLabel.cs
Normal file
36
GreenshotImageEditor/Controls/GreenshotLabel.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public class GreenshotLabel : Label, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
GreenshotImageEditor/Controls/GreenshotRadioButton.cs
Normal file
60
GreenshotImageEditor/Controls/GreenshotRadioButton.cs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of GreenshotCheckbox.
|
||||||
|
/// </summary>
|
||||||
|
public class GreenshotRadioButton : RadioButton, IGreenshotLanguageBindable, IGreenshotConfigBindable
|
||||||
|
{
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string sectionName = "Core";
|
||||||
|
[Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
|
||||||
|
public string SectionName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return sectionName;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
sectionName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")]
|
||||||
|
public string PropertyName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
GreenshotImageEditor/Controls/GreenshotTabPage.cs
Normal file
36
GreenshotImageEditor/Controls/GreenshotTabPage.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public class GreenshotTabPage : TabPage, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
GreenshotImageEditor/Controls/GreenshotTextBox.cs
Normal file
50
GreenshotImageEditor/Controls/GreenshotTextBox.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public class GreenshotTextBox : TextBox, IGreenshotConfigBindable
|
||||||
|
{
|
||||||
|
private string sectionName = "Core";
|
||||||
|
[Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
|
||||||
|
public string SectionName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return sectionName;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
sectionName = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")]
|
||||||
|
public string PropertyName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
GreenshotImageEditor/Controls/GreenshotToolDropDownButton.cs
Normal file
36
GreenshotImageEditor/Controls/GreenshotToolDropDownButton.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public class GreenshotToolStripDropDownButton : ToolStripDropDownButton, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
GreenshotImageEditor/Controls/GreenshotToolStripButton.cs
Normal file
36
GreenshotImageEditor/Controls/GreenshotToolStripButton.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public class GreenshotToolStripButton : ToolStripButton, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
GreenshotImageEditor/Controls/GreenshotToolStripLabel.cs
Normal file
36
GreenshotImageEditor/Controls/GreenshotToolStripLabel.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public class GreenshotToolStripLabel : ToolStripLabel, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
GreenshotImageEditor/Controls/GreenshotToolStripMenuItem.cs
Normal file
36
GreenshotImageEditor/Controls/GreenshotToolStripMenuItem.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public class GreenshotToolStripMenuItem : ToolStripMenuItem, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
GreenshotImageEditor/Controls/IGreenshotConfigBindable.cs
Normal file
44
GreenshotImageEditor/Controls/IGreenshotConfigBindable.cs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
public interface IGreenshotConfigBindable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The class where the property-value is stored
|
||||||
|
/// </summary>
|
||||||
|
string SectionName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Path to the property value which will be mapped with this control
|
||||||
|
/// </summary>
|
||||||
|
string PropertyName
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
GreenshotImageEditor/Controls/IGreenshotLanguageBindable.cs
Normal file
38
GreenshotImageEditor/Controls/IGreenshotLanguageBindable.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This interface describes the designer fields that need to be implemented for Greenshot controls
|
||||||
|
/// </summary>
|
||||||
|
public interface IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Language key to use to fill the Text value with
|
||||||
|
/// </summary>
|
||||||
|
string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
GreenshotImageEditor/Controls/MenuStripEx.cs
Normal file
72
GreenshotImageEditor/Controls/MenuStripEx.cs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is an extension of the default MenuStrip 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
|
||||||
|
/// </summary>
|
||||||
|
public class MenuStripEx : MenuStrip
|
||||||
|
{
|
||||||
|
private const int WM_MOUSEACTIVATE = 0x21;
|
||||||
|
|
||||||
|
private enum NativeConstants : uint
|
||||||
|
{
|
||||||
|
MA_ACTIVATE = 1,
|
||||||
|
MA_ACTIVATEANDEAT = 2,
|
||||||
|
MA_NOACTIVATE = 3,
|
||||||
|
MA_NOACTIVATEANDEAT = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool clickThrough = false;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether the ToolStripEx honors item clicks when its containing form does not have input focus.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default value is false, which is the same behavior provided by the base ToolStrip class.
|
||||||
|
/// </remarks>
|
||||||
|
public bool ClickThrough
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return clickThrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
GreenshotImageEditor/Controls/NonJumpingPanel.cs
Normal file
40
GreenshotImageEditor/Controls/NonJumpingPanel.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// See: http://nickstips.wordpress.com/2010/03/03/c-panel-resets-scroll-position-after-focus-is-lost-and-regained/
|
||||||
|
/// </summary>
|
||||||
|
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
206
GreenshotImageEditor/Controls/Pipette.cs
Normal file
206
GreenshotImageEditor/Controls/Pipette.cs
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using Greenshot.Forms;
|
||||||
|
using GreenshotPlugin.UnmanagedHelpers;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This code was supplied by Hi-Coder as a patch for Greenshot
|
||||||
|
/// Needed some modifications to be stable.
|
||||||
|
/// </summary>
|
||||||
|
public class Pipette : Label, IMessageFilter, IDisposable
|
||||||
|
{
|
||||||
|
private MovableShowColorForm movableShowColorForm;
|
||||||
|
private bool dragging;
|
||||||
|
private Cursor _cursor;
|
||||||
|
private Bitmap _image;
|
||||||
|
private const int VK_ESC = 27;
|
||||||
|
|
||||||
|
public event EventHandler<PipetteUsedArgs> PipetteUsed;
|
||||||
|
|
||||||
|
public Pipette()
|
||||||
|
{
|
||||||
|
BorderStyle = BorderStyle.FixedSingle;
|
||||||
|
dragging = false;
|
||||||
|
_image = (Bitmap)new ComponentResourceManager(typeof(ColorDialog)).GetObject("pipette.Image");
|
||||||
|
Image = _image;
|
||||||
|
_cursor = CreateCursor((Bitmap)_image, 1, 14);
|
||||||
|
movableShowColorForm = new MovableShowColorForm();
|
||||||
|
Application.AddMessageFilter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a cursor from the supplied bitmap & hotspot coordinates
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bitmap">Bitmap to create an icon from</param>
|
||||||
|
/// <param name="hotspotX">Hotspot X coordinate</param>
|
||||||
|
/// <param name="hotspotY">Hotspot Y coordinate</param>
|
||||||
|
/// <returns>Cursor</returns>
|
||||||
|
private static Cursor CreateCursor(Bitmap bitmap, int hotspotX, int hotspotY)
|
||||||
|
{
|
||||||
|
using (SafeIconHandle iconHandle = new SafeIconHandle(bitmap.GetHicon()))
|
||||||
|
{
|
||||||
|
IntPtr icon;
|
||||||
|
IconInfo iconInfo = new IconInfo();
|
||||||
|
User32.GetIconInfo(iconHandle, out iconInfo);
|
||||||
|
iconInfo.xHotspot = hotspotX;
|
||||||
|
iconInfo.yHotspot = hotspotY;
|
||||||
|
iconInfo.fIcon = false;
|
||||||
|
icon = User32.CreateIconIndirect(ref iconInfo);
|
||||||
|
return new Cursor(icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The bulk of the clean-up code is implemented in Dispose(bool)
|
||||||
|
/// </summary>
|
||||||
|
public new void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This Dispose is called from the Dispose and the Destructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">When disposing==true all non-managed resources should be freed too!</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (_cursor != null)
|
||||||
|
{
|
||||||
|
_cursor.Dispose();
|
||||||
|
}
|
||||||
|
if (movableShowColorForm != null)
|
||||||
|
{
|
||||||
|
movableShowColorForm.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
movableShowColorForm = null;
|
||||||
|
_cursor = null;
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle the mouse down on the Pipette "label", we take the capture and move the zoomer to the current location
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">MouseEventArgs</param>
|
||||||
|
protected override void OnMouseDown(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Button == MouseButtons.Left)
|
||||||
|
{
|
||||||
|
User32.SetCapture(Handle);
|
||||||
|
movableShowColorForm.MoveTo(PointToScreen(new Point(e.X, e.Y)));
|
||||||
|
}
|
||||||
|
base.OnMouseDown(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle the mouse up on the Pipette "label", we release the capture and fire the PipetteUsed event
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">MouseEventArgs</param>
|
||||||
|
protected override void OnMouseUp(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Button == MouseButtons.Left)
|
||||||
|
{
|
||||||
|
//Release Capture should consume MouseUp when canceled with the escape key
|
||||||
|
User32.ReleaseCapture();
|
||||||
|
PipetteUsed(this, new PipetteUsedArgs(movableShowColorForm.color));
|
||||||
|
}
|
||||||
|
base.OnMouseUp(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle the mouse Move event, we move the ColorUnderCursor to the current location.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">MouseEventArgs</param>
|
||||||
|
protected override void OnMouseMove(MouseEventArgs e)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
base.OnMouseMove(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle the MouseCaptureChanged event
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
protected override void OnMouseCaptureChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
if (Capture)
|
||||||
|
{
|
||||||
|
dragging = true;
|
||||||
|
Image = null;
|
||||||
|
Cursor c = _cursor;
|
||||||
|
Cursor = c;
|
||||||
|
movableShowColorForm.Visible = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dragging = false;
|
||||||
|
Image = _image;
|
||||||
|
Cursor = Cursors.Arrow;
|
||||||
|
movableShowColorForm.Visible = false;
|
||||||
|
}
|
||||||
|
Update();
|
||||||
|
base.OnMouseCaptureChanged(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IMessageFilter Members
|
||||||
|
|
||||||
|
public bool PreFilterMessage(ref Message m)
|
||||||
|
{
|
||||||
|
if (dragging)
|
||||||
|
{
|
||||||
|
if (m.Msg == (int)WindowsMessages.WM_CHAR)
|
||||||
|
{
|
||||||
|
if ((int)m.WParam == VK_ESC)
|
||||||
|
{
|
||||||
|
User32.ReleaseCapture();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion IMessageFilter Members
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PipetteUsedArgs : EventArgs
|
||||||
|
{
|
||||||
|
public Color color;
|
||||||
|
|
||||||
|
public PipetteUsedArgs(Color c)
|
||||||
|
{
|
||||||
|
color = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
136
GreenshotImageEditor/Controls/PleaseWaitForm.cs
Normal file
136
GreenshotImageEditor/Controls/PleaseWaitForm.cs
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of PleaseWaitForm.
|
||||||
|
/// </summary>
|
||||||
|
public partial class PleaseWaitForm : Form
|
||||||
|
{
|
||||||
|
private Thread waitFor = null;
|
||||||
|
private string title;
|
||||||
|
|
||||||
|
public PleaseWaitForm()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||||
|
//
|
||||||
|
InitializeComponent();
|
||||||
|
Icon = GreenshotResources.getGreenshotIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prevent the close-window button showing
|
||||||
|
/// </summary>
|
||||||
|
private const int CP_NOCLOSE_BUTTON = 0x200;
|
||||||
|
protected override CreateParams CreateParams
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
CreateParams createParams = base.CreateParams;
|
||||||
|
createParams.ClassStyle = createParams.ClassStyle | CP_NOCLOSE_BUTTON;
|
||||||
|
return createParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Show the "please wait" form, execute the code from the delegate and wait until execution finishes.
|
||||||
|
/// The supplied delegate will be wrapped with a try/catch so this method can return any exception that was thrown.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="title">The title of the form (and Thread)</param>
|
||||||
|
/// <param name="text">The text in the form</param>
|
||||||
|
/// <param name="waitDelegate">delegate { with your code }</param>
|
||||||
|
public void ShowAndWait(string title, string text, ThreadStart waitDelegate)
|
||||||
|
{
|
||||||
|
this.title = title;
|
||||||
|
Text = title;
|
||||||
|
label_pleasewait.Text = text;
|
||||||
|
cancelButton.Text = Language.GetString("CANCEL");
|
||||||
|
|
||||||
|
// Make sure the form is shown.
|
||||||
|
Show();
|
||||||
|
|
||||||
|
// Variable to store the exception, if one is generated, from inside the thread.
|
||||||
|
Exception threadException = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Wrap the passed delegate in a try/catch which makes it possible to save the exception
|
||||||
|
waitFor = new Thread(new ThreadStart(
|
||||||
|
delegate
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
waitDelegate.Invoke();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LOG.Error("invoke error:", ex);
|
||||||
|
threadException = ex;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
waitFor.Name = title;
|
||||||
|
waitFor.IsBackground = true;
|
||||||
|
waitFor.SetApartmentState(ApartmentState.STA);
|
||||||
|
waitFor.Start();
|
||||||
|
|
||||||
|
// Wait until finished
|
||||||
|
while (!waitFor.Join(TimeSpan.FromMilliseconds(100)))
|
||||||
|
{
|
||||||
|
Application.DoEvents();
|
||||||
|
}
|
||||||
|
LOG.DebugFormat("Finished {0}", title);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LOG.Error(ex);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
// Check if an exception occured, if so throw it
|
||||||
|
if (threadException != null)
|
||||||
|
{
|
||||||
|
throw threadException;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called if the cancel button is clicked, will use Thread.Abort()
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void CancelButtonClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Cancel clicked on {0}", title);
|
||||||
|
cancelButton.Enabled = false;
|
||||||
|
waitFor.Abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
102
GreenshotImageEditor/Controls/PleaseWaitForm.designer.cs
generated
Normal file
102
GreenshotImageEditor/Controls/PleaseWaitForm.designer.cs
generated
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls {
|
||||||
|
partial class PleaseWaitForm {
|
||||||
|
/// <summary>
|
||||||
|
/// Designer variable used to keep track of non-visual components.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes resources used by the form.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (disposing) {
|
||||||
|
if (components != null) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method is required for Windows Forms designer support.
|
||||||
|
/// Do not change the method contents inside the source code editor. The Forms designer might
|
||||||
|
/// not be able to load this method if it was changed manually.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent() {
|
||||||
|
this.label_pleasewait = new System.Windows.Forms.Label();
|
||||||
|
this.cancelButton = new System.Windows.Forms.Button();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// label_pleasewait
|
||||||
|
//
|
||||||
|
this.label_pleasewait.AutoSize = true;
|
||||||
|
this.label_pleasewait.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
|
this.label_pleasewait.Location = new System.Drawing.Point(0, 0);
|
||||||
|
this.label_pleasewait.Name = "label_pleasewait";
|
||||||
|
this.label_pleasewait.Padding = new System.Windows.Forms.Padding(10);
|
||||||
|
this.label_pleasewait.Size = new System.Drawing.Size(90, 33);
|
||||||
|
this.label_pleasewait.TabIndex = 0;
|
||||||
|
this.label_pleasewait.Text = "Please wait...";
|
||||||
|
this.label_pleasewait.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
|
||||||
|
this.label_pleasewait.UseWaitCursor = true;
|
||||||
|
//
|
||||||
|
// cancelButton
|
||||||
|
//
|
||||||
|
this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||||
|
this.cancelButton.Location = new System.Drawing.Point(38, 41);
|
||||||
|
this.cancelButton.Name = "cancelButton";
|
||||||
|
this.cancelButton.Size = new System.Drawing.Size(94, 23);
|
||||||
|
this.cancelButton.TabIndex = 1;
|
||||||
|
this.cancelButton.Text = "Cancel";
|
||||||
|
this.cancelButton.UseVisualStyleBackColor = true;
|
||||||
|
this.cancelButton.UseWaitCursor = true;
|
||||||
|
this.cancelButton.Click += new System.EventHandler(this.CancelButtonClick);
|
||||||
|
//
|
||||||
|
// PleaseWaitForm
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.AutoSize = true;
|
||||||
|
this.CancelButton = this.cancelButton;
|
||||||
|
this.ClientSize = new System.Drawing.Size(169, 76);
|
||||||
|
this.Controls.Add(this.cancelButton);
|
||||||
|
this.Controls.Add(this.label_pleasewait);
|
||||||
|
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "PleaseWaitForm";
|
||||||
|
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
|
||||||
|
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
|
||||||
|
this.Text = "Greenshot";
|
||||||
|
this.UseWaitCursor = true;
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
}
|
||||||
|
private System.Windows.Forms.Button cancelButton;
|
||||||
|
private System.Windows.Forms.Label label_pleasewait;
|
||||||
|
}
|
||||||
|
}
|
75
GreenshotImageEditor/Controls/QualityDialog.cs
Normal file
75
GreenshotImageEditor/Controls/QualityDialog.cs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using Greenshot.Plugin;
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of JpegQualityDialog.
|
||||||
|
/// </summary>
|
||||||
|
public partial class QualityDialog : GreenshotForm
|
||||||
|
{
|
||||||
|
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
|
public SurfaceOutputSettings Settings
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QualityDialog(SurfaceOutputSettings outputSettings)
|
||||||
|
{
|
||||||
|
Settings = outputSettings;
|
||||||
|
//
|
||||||
|
// The InitializeComponent() call is required for Windows Forms designer support.
|
||||||
|
//
|
||||||
|
InitializeComponent();
|
||||||
|
Icon = GreenshotResources.getGreenshotIcon();
|
||||||
|
|
||||||
|
checkBox_reduceColors.Checked = Settings.ReduceColors;
|
||||||
|
trackBarJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
|
||||||
|
trackBarJpegQuality.Value = Settings.JPGQuality;
|
||||||
|
textBoxJpegQuality.Enabled = OutputFormat.jpg.Equals(outputSettings.Format);
|
||||||
|
textBoxJpegQuality.Text = Settings.JPGQuality.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Button_okClick(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Settings.JPGQuality = trackBarJpegQuality.Value;
|
||||||
|
Settings.ReduceColors = checkBox_reduceColors.Checked;
|
||||||
|
if (checkbox_dontaskagain.Checked)
|
||||||
|
{
|
||||||
|
conf.OutputFileJpegQuality = Settings.JPGQuality;
|
||||||
|
conf.OutputFilePromptQuality = false;
|
||||||
|
conf.OutputFileReduceColors = Settings.ReduceColors;
|
||||||
|
IniConfig.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TrackBarJpegQualityScroll(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
textBoxJpegQuality.Text = trackBarJpegQuality.Value.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
149
GreenshotImageEditor/Controls/QualityDialog.designer.cs
generated
Normal file
149
GreenshotImageEditor/Controls/QualityDialog.designer.cs
generated
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls {
|
||||||
|
partial class QualityDialog {
|
||||||
|
/// <summary>
|
||||||
|
/// Designer variable used to keep track of non-visual components.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes resources used by the form.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing) {
|
||||||
|
if (components != null) {
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method is required for Windows Forms designer support.
|
||||||
|
/// Do not change the method contents inside the source code editor. The Forms designer might
|
||||||
|
/// not be able to load this method if it was changed manually.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.label_choosejpegquality = new GreenshotPlugin.Controls.GreenshotLabel();
|
||||||
|
this.textBoxJpegQuality = new System.Windows.Forms.TextBox();
|
||||||
|
this.trackBarJpegQuality = new System.Windows.Forms.TrackBar();
|
||||||
|
this.checkbox_dontaskagain = new GreenshotPlugin.Controls.GreenshotCheckBox();
|
||||||
|
this.button_ok = new GreenshotPlugin.Controls.GreenshotButton();
|
||||||
|
this.checkBox_reduceColors = new System.Windows.Forms.CheckBox();
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).BeginInit();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// label_choosejpegquality
|
||||||
|
//
|
||||||
|
this.label_choosejpegquality.Location = new System.Drawing.Point(12, 47);
|
||||||
|
this.label_choosejpegquality.Name = "label_choosejpegquality";
|
||||||
|
this.label_choosejpegquality.Size = new System.Drawing.Size(268, 19);
|
||||||
|
this.label_choosejpegquality.TabIndex = 15;
|
||||||
|
this.label_choosejpegquality.LanguageKey = "jpegqualitydialog_choosejpegquality";
|
||||||
|
//
|
||||||
|
// textBoxJpegQuality
|
||||||
|
//
|
||||||
|
this.textBoxJpegQuality.Location = new System.Drawing.Point(245, 69);
|
||||||
|
this.textBoxJpegQuality.Name = "textBoxJpegQuality";
|
||||||
|
this.textBoxJpegQuality.ReadOnly = true;
|
||||||
|
this.textBoxJpegQuality.Size = new System.Drawing.Size(35, 20);
|
||||||
|
this.textBoxJpegQuality.TabIndex = 16;
|
||||||
|
this.textBoxJpegQuality.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
|
||||||
|
//
|
||||||
|
// trackBarJpegQuality
|
||||||
|
//
|
||||||
|
this.trackBarJpegQuality.LargeChange = 10;
|
||||||
|
this.trackBarJpegQuality.Location = new System.Drawing.Point(12, 69);
|
||||||
|
this.trackBarJpegQuality.Maximum = 100;
|
||||||
|
this.trackBarJpegQuality.Name = "trackBarJpegQuality";
|
||||||
|
this.trackBarJpegQuality.Size = new System.Drawing.Size(233, 45);
|
||||||
|
this.trackBarJpegQuality.TabIndex = 14;
|
||||||
|
this.trackBarJpegQuality.TickFrequency = 10;
|
||||||
|
this.trackBarJpegQuality.Scroll += new System.EventHandler(this.TrackBarJpegQualityScroll);
|
||||||
|
//
|
||||||
|
// checkbox_dontaskagain
|
||||||
|
//
|
||||||
|
this.checkbox_dontaskagain.CheckAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.checkbox_dontaskagain.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.checkbox_dontaskagain.Location = new System.Drawing.Point(12, 106);
|
||||||
|
this.checkbox_dontaskagain.Name = "checkbox_dontaskagain";
|
||||||
|
this.checkbox_dontaskagain.LanguageKey = "qualitydialog_dontaskagain";
|
||||||
|
this.checkbox_dontaskagain.Size = new System.Drawing.Size(268, 37);
|
||||||
|
this.checkbox_dontaskagain.TabIndex = 17;
|
||||||
|
this.checkbox_dontaskagain.TextAlign = System.Drawing.ContentAlignment.TopLeft;
|
||||||
|
this.checkbox_dontaskagain.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// button_ok
|
||||||
|
//
|
||||||
|
this.button_ok.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||||
|
this.button_ok.Location = new System.Drawing.Point(205, 149);
|
||||||
|
this.button_ok.Name = "button_ok";
|
||||||
|
this.button_ok.Size = new System.Drawing.Size(75, 23);
|
||||||
|
this.button_ok.TabIndex = 18;
|
||||||
|
this.button_ok.LanguageKey = "OK";
|
||||||
|
this.button_ok.UseVisualStyleBackColor = true;
|
||||||
|
this.button_ok.Click += new System.EventHandler(this.Button_okClick);
|
||||||
|
//
|
||||||
|
// checkBox_reduceColors
|
||||||
|
//
|
||||||
|
this.checkBox_reduceColors.AutoSize = true;
|
||||||
|
this.checkBox_reduceColors.Location = new System.Drawing.Point(12, 11);
|
||||||
|
this.checkBox_reduceColors.Name = "checkBox_reduceColors";
|
||||||
|
this.checkBox_reduceColors.Size = new System.Drawing.Size(95, 17);
|
||||||
|
this.checkBox_reduceColors.TabIndex = 19;
|
||||||
|
this.checkBox_reduceColors.Text = "settings_reducecolors";
|
||||||
|
this.checkBox_reduceColors.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// QualityDialog
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
|
||||||
|
this.ClientSize = new System.Drawing.Size(299, 184);
|
||||||
|
this.ControlBox = false;
|
||||||
|
this.Controls.Add(this.checkBox_reduceColors);
|
||||||
|
this.Controls.Add(this.button_ok);
|
||||||
|
this.Controls.Add(this.checkbox_dontaskagain);
|
||||||
|
this.Controls.Add(this.label_choosejpegquality);
|
||||||
|
this.Controls.Add(this.textBoxJpegQuality);
|
||||||
|
this.Controls.Add(this.trackBarJpegQuality);
|
||||||
|
this.MaximizeBox = false;
|
||||||
|
this.MinimizeBox = false;
|
||||||
|
this.Name = "QualityDialog";
|
||||||
|
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
|
||||||
|
this.LanguageKey = "qualitydialog_title";
|
||||||
|
((System.ComponentModel.ISupportInitialize)(this.trackBarJpegQuality)).EndInit();
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
private GreenshotPlugin.Controls.GreenshotButton button_ok;
|
||||||
|
private GreenshotPlugin.Controls.GreenshotCheckBox checkbox_dontaskagain;
|
||||||
|
private System.Windows.Forms.TrackBar trackBarJpegQuality;
|
||||||
|
private System.Windows.Forms.TextBox textBoxJpegQuality;
|
||||||
|
private GreenshotPlugin.Controls.GreenshotLabel label_choosejpegquality;
|
||||||
|
private System.Windows.Forms.CheckBox checkBox_reduceColors;
|
||||||
|
}
|
||||||
|
}
|
262
GreenshotImageEditor/Controls/SaveImageFileDialog.cs
Normal file
262
GreenshotImageEditor/Controls/SaveImageFileDialog.cs
Normal file
|
@ -0,0 +1,262 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using Greenshot.Plugin;
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Custom dialog for saving images, wraps SaveFileDialog.
|
||||||
|
/// For some reason SFD is sealed :(
|
||||||
|
/// </summary>
|
||||||
|
public class SaveImageFileDialog : IDisposable
|
||||||
|
{
|
||||||
|
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
|
protected SaveFileDialog saveFileDialog;
|
||||||
|
private FilterOption[] filterOptions;
|
||||||
|
private DirectoryInfo eagerlyCreatedDirectory;
|
||||||
|
private ICaptureDetails captureDetails = null;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (saveFileDialog != null)
|
||||||
|
{
|
||||||
|
saveFileDialog.Dispose();
|
||||||
|
saveFileDialog = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaveImageFileDialog()
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SaveImageFileDialog(ICaptureDetails captureDetails)
|
||||||
|
{
|
||||||
|
this.captureDetails = captureDetails;
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void init()
|
||||||
|
{
|
||||||
|
saveFileDialog = new SaveFileDialog();
|
||||||
|
applyFilterOptions();
|
||||||
|
string initialDirectory = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
initialDirectory = Path.GetDirectoryName(conf.OutputFileAsFullpath);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("OutputFileAsFullpath was set to {0}, ignoring due to problem in path.", conf.OutputFileAsFullpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(initialDirectory) && Directory.Exists(initialDirectory))
|
||||||
|
{
|
||||||
|
saveFileDialog.InitialDirectory = initialDirectory;
|
||||||
|
}
|
||||||
|
else if (Directory.Exists(conf.OutputFilePath))
|
||||||
|
{
|
||||||
|
saveFileDialog.InitialDirectory = conf.OutputFilePath;
|
||||||
|
}
|
||||||
|
// The following property fixes a problem that the directory where we save is locked (bug #2899790)
|
||||||
|
saveFileDialog.RestoreDirectory = true;
|
||||||
|
saveFileDialog.OverwritePrompt = true;
|
||||||
|
saveFileDialog.CheckPathExists = false;
|
||||||
|
saveFileDialog.AddExtension = true;
|
||||||
|
ApplySuggestedValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyFilterOptions()
|
||||||
|
{
|
||||||
|
prepareFilterOptions();
|
||||||
|
string fdf = "";
|
||||||
|
int preselect = 0;
|
||||||
|
for (int i = 0; i < filterOptions.Length; i++)
|
||||||
|
{
|
||||||
|
FilterOption fo = filterOptions[i];
|
||||||
|
fdf += fo.Label + "|*." + fo.Extension + "|";
|
||||||
|
if (conf.OutputFileAsFullpath.EndsWith(fo.Extension, StringComparison.CurrentCultureIgnoreCase)) preselect = i;
|
||||||
|
}
|
||||||
|
fdf = fdf.Substring(0, fdf.Length - 1);
|
||||||
|
saveFileDialog.Filter = fdf;
|
||||||
|
saveFileDialog.FilterIndex = preselect + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareFilterOptions()
|
||||||
|
{
|
||||||
|
OutputFormat[] supportedImageFormats = (OutputFormat[])Enum.GetValues(typeof(OutputFormat));
|
||||||
|
filterOptions = new FilterOption[supportedImageFormats.Length];
|
||||||
|
for (int i = 0; i < filterOptions.Length; i++)
|
||||||
|
{
|
||||||
|
string ifo = supportedImageFormats[i].ToString();
|
||||||
|
if (ifo.ToLower().Equals("jpeg")) ifo = "Jpg"; // we dont want no jpeg files, so let the dialog check for jpg
|
||||||
|
FilterOption fo = new FilterOption();
|
||||||
|
fo.Label = ifo.ToUpper();
|
||||||
|
fo.Extension = ifo.ToLower();
|
||||||
|
filterOptions.SetValue(fo, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// filename exactly as typed in the filename field
|
||||||
|
/// </summary>
|
||||||
|
public string FileName
|
||||||
|
{
|
||||||
|
get { return saveFileDialog.FileName; }
|
||||||
|
set { saveFileDialog.FileName = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// initial directory of the dialog
|
||||||
|
/// </summary>
|
||||||
|
public string InitialDirectory
|
||||||
|
{
|
||||||
|
get { return saveFileDialog.InitialDirectory; }
|
||||||
|
set { saveFileDialog.InitialDirectory = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// returns filename as typed in the filename field with extension.
|
||||||
|
/// if filename field value ends with selected extension, the value is just returned.
|
||||||
|
/// otherwise, the selected extension is appended to the filename.
|
||||||
|
/// </summary>
|
||||||
|
public string FileNameWithExtension
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string fn = saveFileDialog.FileName;
|
||||||
|
// if the filename contains a valid extension, which is the same like the selected filter item's extension, the filename is okay
|
||||||
|
if (fn.EndsWith(Extension, StringComparison.CurrentCultureIgnoreCase)) return fn;
|
||||||
|
// otherwise we just add the selected filter item's extension
|
||||||
|
else return fn + "." + Extension;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
FileName = Path.GetFileNameWithoutExtension(value);
|
||||||
|
Extension = Path.GetExtension(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// gets or sets selected extension
|
||||||
|
/// </summary>
|
||||||
|
public string Extension
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return filterOptions[saveFileDialog.FilterIndex - 1].Extension;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
for (int i = 0; i < filterOptions.Length; i++)
|
||||||
|
{
|
||||||
|
if (value.Equals(filterOptions[i].Extension, StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
saveFileDialog.FilterIndex = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogResult ShowDialog()
|
||||||
|
{
|
||||||
|
DialogResult ret = saveFileDialog.ShowDialog();
|
||||||
|
CleanUp();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sets InitialDirectory and FileName property of a SaveFileDialog smartly, considering default pattern and last used path
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sfd">a SaveFileDialog instance</param>
|
||||||
|
private void ApplySuggestedValues()
|
||||||
|
{
|
||||||
|
// build the full path and set dialog properties
|
||||||
|
FileName = FilenameHelper.GetFilenameWithoutExtensionFromPattern(conf.OutputFileFilenamePattern, captureDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetRootDirFromConfig()
|
||||||
|
{
|
||||||
|
string rootDir = conf.OutputFilePath;
|
||||||
|
rootDir = FilenameHelper.FillVariables(rootDir, false);
|
||||||
|
return rootDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FilterOption
|
||||||
|
{
|
||||||
|
public string Label;
|
||||||
|
public string Extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CleanUp()
|
||||||
|
{
|
||||||
|
// fix for bug #3379053
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (eagerlyCreatedDirectory != null && eagerlyCreatedDirectory.GetFiles().Length == 0 && eagerlyCreatedDirectory.GetDirectories().Length == 0)
|
||||||
|
{
|
||||||
|
eagerlyCreatedDirectory.Delete();
|
||||||
|
eagerlyCreatedDirectory = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("Couldn't cleanup directory due to: {0}", e.Message);
|
||||||
|
eagerlyCreatedDirectory = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string CreateDirectoryIfNotExists(string fullPath)
|
||||||
|
{
|
||||||
|
string dirName = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
dirName = Path.GetDirectoryName(fullPath);
|
||||||
|
DirectoryInfo di = new DirectoryInfo(dirName);
|
||||||
|
if (!di.Exists)
|
||||||
|
{
|
||||||
|
di = Directory.CreateDirectory(dirName);
|
||||||
|
eagerlyCreatedDirectory = di;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error in CreateDirectoryIfNotExists", e);
|
||||||
|
}
|
||||||
|
return dirName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
GreenshotImageEditor/Controls/ToolStripColorButton.cs
Normal file
99
GreenshotImageEditor/Controls/ToolStripColorButton.cs
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin.Controls;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Controls
|
||||||
|
{
|
||||||
|
public class ToolStripColorButton : ToolStripButton, INotifyPropertyChanged, IGreenshotLanguageBindable
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
[Category("Greenshot"), DefaultValue(null), Description("Specifies key of the language file to use when displaying the text.")]
|
||||||
|
public string LanguageKey
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color selectedColor = Color.Transparent;
|
||||||
|
|
||||||
|
public ToolStripColorButton()
|
||||||
|
{
|
||||||
|
Click += ColorButtonClick;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color SelectedColor
|
||||||
|
{
|
||||||
|
get { return selectedColor; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
selectedColor = value;
|
||||||
|
|
||||||
|
Brush brush;
|
||||||
|
if (value != Color.Transparent)
|
||||||
|
{
|
||||||
|
brush = new SolidBrush(value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
brush = new HatchBrush(HatchStyle.Percent50, Color.White, Color.Gray);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Image != null)
|
||||||
|
{
|
||||||
|
using (Graphics graphics = Graphics.FromImage(Image))
|
||||||
|
{
|
||||||
|
graphics.FillRectangle(brush, new Rectangle(0, 13, 16, 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanup GDI Object
|
||||||
|
brush.Dispose();
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
73
GreenshotImageEditor/Controls/ToolStripEx.cs
Normal file
73
GreenshotImageEditor/Controls/ToolStripEx.cs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Controls
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 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
|
||||||
|
/// </summary>
|
||||||
|
internal class ToolStripEx : ToolStrip
|
||||||
|
{
|
||||||
|
private const int WM_MOUSEACTIVATE = 0x21;
|
||||||
|
|
||||||
|
private enum NativeConstants : uint
|
||||||
|
{
|
||||||
|
MA_ACTIVATE = 1,
|
||||||
|
MA_ACTIVATEANDEAT = 2,
|
||||||
|
MA_NOACTIVATE = 3,
|
||||||
|
MA_NOACTIVATEANDEAT = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool clickThrough = false;
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets whether the ToolStripEx honors item clicks when its containing form does not have input focus.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Default value is false, which is the same behavior provided by the base ToolStrip class.
|
||||||
|
/// </remarks>
|
||||||
|
|
||||||
|
public bool ClickThrough
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return clickThrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
m.Result = (IntPtr)NativeConstants.MA_ACTIVATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
90
GreenshotImageEditor/Controls/ToolStripNumericUpDown.cs
Normal file
90
GreenshotImageEditor/Controls/ToolStripNumericUpDown.cs
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Windows.Forms.Design;
|
||||||
|
|
||||||
|
namespace Greenshot.Controls
|
||||||
|
{
|
||||||
|
[ToolStripItemDesignerAvailability(ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)]
|
||||||
|
public class ToolStripNumericUpDown : ToolStripControlHost, INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
public ToolStripNumericUpDown()
|
||||||
|
: base(new NumericUpDown())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NumericUpDown NumericUpDown
|
||||||
|
{
|
||||||
|
get { return Control as NumericUpDown; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public decimal Value
|
||||||
|
{
|
||||||
|
get { return NumericUpDown.Value; }
|
||||||
|
set { NumericUpDown.Value = value; }
|
||||||
|
}
|
||||||
|
public decimal Minimum
|
||||||
|
{
|
||||||
|
get { return NumericUpDown.Minimum; }
|
||||||
|
set { NumericUpDown.Minimum = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public decimal Maximum
|
||||||
|
{
|
||||||
|
get { return NumericUpDown.Maximum; }
|
||||||
|
set { NumericUpDown.Maximum = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public decimal Increment
|
||||||
|
{
|
||||||
|
get { return NumericUpDown.Increment; }
|
||||||
|
set { NumericUpDown.Increment = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int DecimalPlaces
|
||||||
|
{
|
||||||
|
get { return NumericUpDown.DecimalPlaces; }
|
||||||
|
set { NumericUpDown.DecimalPlaces = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnSubscribeControlEvents(Control control)
|
||||||
|
{
|
||||||
|
base.OnSubscribeControlEvents(control);
|
||||||
|
NumericUpDown.ValueChanged += _valueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnUnsubscribeControlEvents(Control control)
|
||||||
|
{
|
||||||
|
base.OnUnsubscribeControlEvents(control);
|
||||||
|
NumericUpDown.ValueChanged -= _valueChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void _valueChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Value"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
GreenshotImageEditor/Core/BinaryStructHelper.cs
Normal file
108
GreenshotImageEditor/Core/BinaryStructHelper.cs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A helper class which does the mashalling for structs
|
||||||
|
/// </summary>
|
||||||
|
public static class BinaryStructHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get a struct from a byte array
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">typeof struct</typeparam>
|
||||||
|
/// <param name="bytes">byte[]</param>
|
||||||
|
/// <returns>struct</returns>
|
||||||
|
public static T FromByteArray<T>(byte[] bytes) where T : struct
|
||||||
|
{
|
||||||
|
IntPtr ptr = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int size = Marshal.SizeOf(typeof(T));
|
||||||
|
ptr = Marshal.AllocHGlobal(size);
|
||||||
|
Marshal.Copy(bytes, 0, ptr, size);
|
||||||
|
return FromIntPtr<T>(ptr);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (ptr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a struct from a byte array
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">typeof struct</typeparam>
|
||||||
|
/// <param name="bytes">byte[]</param>
|
||||||
|
/// <returns>struct</returns>
|
||||||
|
public static T FromIntPtr<T>(IntPtr intPtr) where T : struct
|
||||||
|
{
|
||||||
|
object obj = Marshal.PtrToStructure(intPtr, typeof(T));
|
||||||
|
return (T)obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// copy a struct to a byte array
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">typeof struct</typeparam>
|
||||||
|
/// <param name="obj">struct</param>
|
||||||
|
/// <returns>byte[]</returns>
|
||||||
|
public static byte[] ToByteArray<T>(T obj) where T : struct
|
||||||
|
{
|
||||||
|
IntPtr ptr = IntPtr.Zero;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int size = Marshal.SizeOf(typeof(T));
|
||||||
|
ptr = Marshal.AllocHGlobal(size);
|
||||||
|
Marshal.StructureToPtr(obj, ptr, true);
|
||||||
|
return FromPtrToByteArray<T>(ptr);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (ptr != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
Marshal.FreeHGlobal(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// copy a struct from a pointer to a byte array
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">typeof struct</typeparam>
|
||||||
|
/// <param name="ptr">IntPtr to struct</param>
|
||||||
|
/// <returns>byte[]</returns>
|
||||||
|
public static byte[] FromPtrToByteArray<T>(IntPtr ptr) where T : struct
|
||||||
|
{
|
||||||
|
int size = Marshal.SizeOf(typeof(T));
|
||||||
|
byte[] bytes = new byte[size];
|
||||||
|
Marshal.Copy(ptr, bytes, 0, size);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
247
GreenshotImageEditor/Core/Cache.cs
Normal file
247
GreenshotImageEditor/Core/Cache.cs
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Timers;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Cache class
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TK">Type of key</typeparam>
|
||||||
|
/// <typeparam name="TV">Type of value</typeparam>
|
||||||
|
public class Cache<TK, TV>
|
||||||
|
{
|
||||||
|
private IDictionary<TK, TV> internalCache = new Dictionary<TK, TV>();
|
||||||
|
private object lockObject = new object();
|
||||||
|
private int secondsToExpire = 10;
|
||||||
|
private CacheObjectExpired expiredCallback = null;
|
||||||
|
public delegate void CacheObjectExpired(TK key, TV cacheValue);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize the cache
|
||||||
|
/// </summary>
|
||||||
|
public Cache()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize the cache
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="expiredCallback"></param>
|
||||||
|
public Cache(CacheObjectExpired expiredCallback)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
this.expiredCallback = expiredCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize the cache with a expire setting
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="secondsToExpire"></param>
|
||||||
|
public Cache(int secondsToExpire)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
this.secondsToExpire = secondsToExpire;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initialize the cache with a expire setting
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="secondsToExpire"></param>
|
||||||
|
/// <param name="expiredCallback"></param>
|
||||||
|
public Cache(int secondsToExpire, CacheObjectExpired expiredCallback)
|
||||||
|
: this(expiredCallback)
|
||||||
|
{
|
||||||
|
this.secondsToExpire = secondsToExpire;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enumerable for the values in the cache
|
||||||
|
/// </summary>
|
||||||
|
public IEnumerable<TV> Elements
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<TV> elements = new List<TV>();
|
||||||
|
|
||||||
|
foreach (TV element in internalCache.Values)
|
||||||
|
{
|
||||||
|
elements.Add(element);
|
||||||
|
}
|
||||||
|
foreach (TV element in elements)
|
||||||
|
{
|
||||||
|
yield return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the value by key from the cache
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public TV this[TK key]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
TV result = default(TV);
|
||||||
|
lock (lockObject)
|
||||||
|
{
|
||||||
|
if (internalCache.ContainsKey(key))
|
||||||
|
{
|
||||||
|
result = internalCache[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>true if the cache contains the key</returns>
|
||||||
|
public bool Contains(TK key)
|
||||||
|
{
|
||||||
|
return internalCache.ContainsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a value to the cache
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
public void Add(TK key, TV value)
|
||||||
|
{
|
||||||
|
Add(key, value, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a value to the cache
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="secondsToExpire?">optional value for the seconds to expire</param>
|
||||||
|
public void Add(TK key, TV value, int? secondsToExpire)
|
||||||
|
{
|
||||||
|
lock (lockObject)
|
||||||
|
{
|
||||||
|
var cachedItem = new CachedItem(key, value, secondsToExpire.HasValue ? secondsToExpire.Value : this.secondsToExpire);
|
||||||
|
cachedItem.Expired += delegate(TK cacheKey, TV cacheValue)
|
||||||
|
{
|
||||||
|
if (internalCache.ContainsKey(cacheKey))
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Expiring object with Key: {0}", cacheKey);
|
||||||
|
if (expiredCallback != null)
|
||||||
|
{
|
||||||
|
expiredCallback(cacheKey, cacheValue);
|
||||||
|
}
|
||||||
|
Remove(cacheKey);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Expired old object with Key: {0}", cacheKey);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (internalCache.ContainsKey(key))
|
||||||
|
{
|
||||||
|
internalCache[key] = value;
|
||||||
|
LOG.DebugFormat("Updated item with Key: {0}", key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
internalCache.Add(key, cachedItem);
|
||||||
|
LOG.DebugFormat("Added item with Key: {0}", key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove item from cache
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
public void Remove(TK key)
|
||||||
|
{
|
||||||
|
lock (lockObject)
|
||||||
|
{
|
||||||
|
if (!internalCache.ContainsKey(key))
|
||||||
|
{
|
||||||
|
throw new ApplicationException(String.Format("An object with key ‘{0}’ does not exists in cache", key));
|
||||||
|
}
|
||||||
|
internalCache.Remove(key);
|
||||||
|
LOG.DebugFormat("Removed item with Key: {0}", key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A cache item
|
||||||
|
/// </summary>
|
||||||
|
private class CachedItem
|
||||||
|
{
|
||||||
|
public event CacheObjectExpired Expired;
|
||||||
|
private int secondsToExpire;
|
||||||
|
private readonly Timer _timerEvent;
|
||||||
|
|
||||||
|
public CachedItem(TK key, TV item, int secondsToExpire)
|
||||||
|
{
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("key is not valid");
|
||||||
|
}
|
||||||
|
Key = key;
|
||||||
|
Item = item;
|
||||||
|
this.secondsToExpire = secondsToExpire;
|
||||||
|
if (secondsToExpire > 0)
|
||||||
|
{
|
||||||
|
_timerEvent = new Timer(secondsToExpire * 1000) { AutoReset = false };
|
||||||
|
_timerEvent.Elapsed += timerEvent_Elapsed;
|
||||||
|
_timerEvent.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExpireNow()
|
||||||
|
{
|
||||||
|
_timerEvent.Stop();
|
||||||
|
if (secondsToExpire > 0 && Expired != null)
|
||||||
|
{
|
||||||
|
Expired(Key, Item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timerEvent_Elapsed(object sender, ElapsedEventArgs e)
|
||||||
|
{
|
||||||
|
ExpireNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TK Key { get; private set; }
|
||||||
|
public TV Item { get; private set; }
|
||||||
|
|
||||||
|
public static implicit operator TV(CachedItem a)
|
||||||
|
{
|
||||||
|
return a.Item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
803
GreenshotImageEditor/Core/ClipboardHelper.cs
Normal file
803
GreenshotImageEditor/Core/ClipboardHelper.cs
Normal file
|
@ -0,0 +1,803 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using Greenshot.Plugin;
|
||||||
|
using GreenshotPlugin.UnmanagedHelpers;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of ClipboardHelper.
|
||||||
|
/// </summary>
|
||||||
|
public static class ClipboardHelper
|
||||||
|
{
|
||||||
|
private static readonly Object clipboardLockObject = new Object();
|
||||||
|
private static readonly CoreConfiguration config = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
|
private static readonly string FORMAT_FILECONTENTS = "FileContents";
|
||||||
|
private static readonly string FORMAT_PNG = "PNG";
|
||||||
|
private static readonly string FORMAT_PNG_OFFICEART = "PNG+Office Art";
|
||||||
|
private static readonly string FORMAT_JPG = "JPG";
|
||||||
|
private static readonly string FORMAT_JFIF = "JFIF";
|
||||||
|
private static readonly string FORMAT_JFIF_OFFICEART = "JFIF+Office Art";
|
||||||
|
private static readonly string FORMAT_GIF = "GIF";
|
||||||
|
private static readonly string FORMAT_BITMAP_PLACEHOLDER = "_BITMAP_";
|
||||||
|
|
||||||
|
private static IntPtr nextClipboardViewer = IntPtr.Zero;
|
||||||
|
// Template for the HTML Text on the clipboard
|
||||||
|
// see: http://msdn.microsoft.com/en-us/library/ms649015%28v=vs.85%29.aspx
|
||||||
|
// or: http://msdn.microsoft.com/en-us/library/Aa767917.aspx
|
||||||
|
private const string HTML_CLIPBOARD_STRING = @"Version:0.9
|
||||||
|
StartHTML:<<<<<<<1
|
||||||
|
EndHTML:<<<<<<<2
|
||||||
|
StartFragment:<<<<<<<3
|
||||||
|
EndFragment:<<<<<<<4
|
||||||
|
StartSelection:<<<<<<<3
|
||||||
|
EndSelection:<<<<<<<4
|
||||||
|
<!DOCTYPE>
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>Greenshot capture</TITLE>
|
||||||
|
</HEAD>
|
||||||
|
<BODY>
|
||||||
|
<!--StartFragment -->
|
||||||
|
<img border='0' src='file:///${file}' width='${width}' height='${height}'>
|
||||||
|
<!--EndFragment -->
|
||||||
|
</BODY>
|
||||||
|
</HTML>";
|
||||||
|
private const string HTML_CLIPBOARD_BASE64_STRING = @"Version:0.9
|
||||||
|
StartHTML:<<<<<<<1
|
||||||
|
EndHTML:<<<<<<<2
|
||||||
|
StartFragment:<<<<<<<3
|
||||||
|
EndFragment:<<<<<<<4
|
||||||
|
StartSelection:<<<<<<<3
|
||||||
|
EndSelection:<<<<<<<4
|
||||||
|
<!DOCTYPE>
|
||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<TITLE>Greenshot capture</TITLE>
|
||||||
|
</HEAD>
|
||||||
|
<BODY>
|
||||||
|
<!--StartFragment -->
|
||||||
|
<img border='0' src='data:image/${format};base64,${data}' width='${width}' height='${height}'>
|
||||||
|
<!--EndFragment -->
|
||||||
|
</BODY>
|
||||||
|
</HTML>";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the current "ClipboardOwner" but only if it isn't us!
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>current clipboard owner</returns>
|
||||||
|
private static string GetClipboardOwner()
|
||||||
|
{
|
||||||
|
string owner = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
IntPtr hWnd = User32.GetClipboardOwner();
|
||||||
|
if (hWnd != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
IntPtr pid = IntPtr.Zero;
|
||||||
|
IntPtr tid = User32.GetWindowThreadProcessId(hWnd, out pid);
|
||||||
|
Process me = Process.GetCurrentProcess();
|
||||||
|
Process ownerProcess = Process.GetProcessById(pid.ToInt32());
|
||||||
|
// Exclude myself
|
||||||
|
if (ownerProcess != null && me.Id != ownerProcess.Id)
|
||||||
|
{
|
||||||
|
// Get Process Name
|
||||||
|
owner = ownerProcess.ProcessName;
|
||||||
|
// Try to get the starting Process Filename, this might fail.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
owner = ownerProcess.Modules[0].FileName;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Warn("Non critical error: Couldn't get clipboard owner.", e);
|
||||||
|
}
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The SetDataObject will lock/try/catch clipboard operations making it save and not show exceptions.
|
||||||
|
/// The bool "copy" is used to decided if the information stays on the clipboard after exit.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ido"></param>
|
||||||
|
/// <param name="copy"></param>
|
||||||
|
private static void SetDataObject(IDataObject ido, bool copy)
|
||||||
|
{
|
||||||
|
lock (clipboardLockObject)
|
||||||
|
{
|
||||||
|
int retryCount = 2;
|
||||||
|
while (retryCount >= 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Clipboard.SetDataObject(ido, copy);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Exception ee)
|
||||||
|
{
|
||||||
|
if (retryCount == 0)
|
||||||
|
{
|
||||||
|
string messageText = null;
|
||||||
|
string clipboardOwner = GetClipboardOwner();
|
||||||
|
if (clipboardOwner != null)
|
||||||
|
{
|
||||||
|
messageText = Language.GetFormattedString("clipboard_inuse", clipboardOwner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
messageText = Language.GetString("clipboard_error");
|
||||||
|
}
|
||||||
|
LOG.Error(messageText, ee);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
--retryCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The GetDataObject will lock/try/catch clipboard operations making it save and not show exceptions.
|
||||||
|
/// </summary>
|
||||||
|
public static IDataObject GetDataObject()
|
||||||
|
{
|
||||||
|
lock (clipboardLockObject)
|
||||||
|
{
|
||||||
|
int retryCount = 2;
|
||||||
|
while (retryCount >= 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Clipboard.GetDataObject();
|
||||||
|
}
|
||||||
|
catch (Exception ee)
|
||||||
|
{
|
||||||
|
if (retryCount == 0)
|
||||||
|
{
|
||||||
|
string messageText = null;
|
||||||
|
string clipboardOwner = GetClipboardOwner();
|
||||||
|
if (clipboardOwner != null)
|
||||||
|
{
|
||||||
|
messageText = Language.GetFormattedString("clipboard_inuse", clipboardOwner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
messageText = Language.GetString("clipboard_error");
|
||||||
|
}
|
||||||
|
LOG.Error(messageText, ee);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
--retryCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wrapper for Clipboard.ContainsText, Created for Bug #3432313
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>boolean if there is text on the clipboard</returns>
|
||||||
|
public static bool ContainsText()
|
||||||
|
{
|
||||||
|
IDataObject clipboardData = GetDataObject();
|
||||||
|
return ContainsText(clipboardData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test if the IDataObject contains Text
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObject"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool ContainsText(IDataObject dataObject)
|
||||||
|
{
|
||||||
|
if (dataObject != null)
|
||||||
|
{
|
||||||
|
if (dataObject.GetDataPresent(DataFormats.Text) || dataObject.GetDataPresent(DataFormats.UnicodeText))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wrapper for Clipboard.ContainsImage, specialized for Greenshot, Created for Bug #3432313
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>boolean if there is an image on the clipboard</returns>
|
||||||
|
public static bool ContainsImage()
|
||||||
|
{
|
||||||
|
IDataObject clipboardData = GetDataObject();
|
||||||
|
return ContainsImage(clipboardData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if the IDataObject has an image
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObject"></param>
|
||||||
|
/// <returns>true if an image is there</returns>
|
||||||
|
public static bool ContainsImage(IDataObject dataObject)
|
||||||
|
{
|
||||||
|
if (dataObject != null)
|
||||||
|
{
|
||||||
|
if (dataObject.GetDataPresent(DataFormats.Bitmap)
|
||||||
|
|| dataObject.GetDataPresent(DataFormats.Dib)
|
||||||
|
|| dataObject.GetDataPresent(DataFormats.Tiff)
|
||||||
|
|| dataObject.GetDataPresent(DataFormats.EnhancedMetafile)
|
||||||
|
|| dataObject.GetDataPresent(FORMAT_PNG)
|
||||||
|
|| dataObject.GetDataPresent(FORMAT_JPG)
|
||||||
|
|| dataObject.GetDataPresent(FORMAT_GIF))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
List<string> imageFiles = GetImageFilenames(dataObject);
|
||||||
|
if (imageFiles != null && imageFiles.Count > 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (dataObject.GetDataPresent(FORMAT_FILECONTENTS))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MemoryStream imageStream = dataObject.GetData(FORMAT_FILECONTENTS) as MemoryStream;
|
||||||
|
if (isValidStream(imageStream))
|
||||||
|
{
|
||||||
|
using (Image tmpImage = Image.FromStream(imageStream))
|
||||||
|
{
|
||||||
|
// If we get here, there is an image
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Simple helper to check the stream
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="memoryStream"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static bool isValidStream(MemoryStream memoryStream)
|
||||||
|
{
|
||||||
|
return memoryStream != null && memoryStream.Length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wrapper for Clipboard.GetImage, Created for Bug #3432313
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Image if there is an image on the clipboard</returns>
|
||||||
|
public static Image GetImage()
|
||||||
|
{
|
||||||
|
IDataObject clipboardData = GetDataObject();
|
||||||
|
// Return the first image
|
||||||
|
foreach (Image clipboardImage in GetImages(clipboardData))
|
||||||
|
{
|
||||||
|
return clipboardImage;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all images (multiple if filenames are available) from the dataObject
|
||||||
|
/// Returned images must be disposed by the calling code!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObject"></param>
|
||||||
|
/// <returns>IEnumerable<Image></returns>
|
||||||
|
public static IEnumerable<Image> GetImages(IDataObject dataObject)
|
||||||
|
{
|
||||||
|
// Get single image, this takes the "best" match
|
||||||
|
Image singleImage = GetImage(dataObject);
|
||||||
|
if (singleImage != null)
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Got image from clipboard with size {0} and format {1}", singleImage.Size, singleImage.PixelFormat);
|
||||||
|
yield return singleImage;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// check if files are supplied
|
||||||
|
List<string> imageFiles = GetImageFilenames(dataObject);
|
||||||
|
if (imageFiles != null)
|
||||||
|
{
|
||||||
|
foreach (string imageFile in imageFiles)
|
||||||
|
{
|
||||||
|
Image returnImage = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
returnImage = ImageHelper.LoadImage(imageFile);
|
||||||
|
}
|
||||||
|
catch (Exception streamImageEx)
|
||||||
|
{
|
||||||
|
LOG.Error("Problem retrieving Image from clipboard.", streamImageEx);
|
||||||
|
}
|
||||||
|
if (returnImage != null)
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Got image from clipboard with size {0} and format {1}", returnImage.Size, returnImage.PixelFormat);
|
||||||
|
yield return returnImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get an Image from the IDataObject, don't check for FileDrop
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObject"></param>
|
||||||
|
/// <returns>Image or null</returns>
|
||||||
|
private static Image GetImage(IDataObject dataObject)
|
||||||
|
{
|
||||||
|
Image returnImage = null;
|
||||||
|
if (dataObject != null)
|
||||||
|
{
|
||||||
|
IList<string> formats = GetFormats(dataObject);
|
||||||
|
string[] retrieveFormats;
|
||||||
|
|
||||||
|
// Found a weird bug, where PNG's from Outlook 2010 are clipped
|
||||||
|
// So I build some special logik to get the best format:
|
||||||
|
if (formats != null && formats.Contains(FORMAT_PNG_OFFICEART) && formats.Contains(DataFormats.Dib))
|
||||||
|
{
|
||||||
|
// Outlook ??
|
||||||
|
LOG.Info("Most likely the current clipboard contents come from Outlook, as this has a problem with PNG and others we place the DIB format to the front...");
|
||||||
|
retrieveFormats = new string[] { DataFormats.Dib, FORMAT_BITMAP_PLACEHOLDER, FORMAT_FILECONTENTS, FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JFIF, DataFormats.Tiff, FORMAT_GIF };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
retrieveFormats = new string[] { FORMAT_PNG_OFFICEART, FORMAT_PNG, FORMAT_JFIF_OFFICEART, FORMAT_JPG, FORMAT_JFIF, DataFormats.Tiff, DataFormats.Dib, FORMAT_BITMAP_PLACEHOLDER, FORMAT_FILECONTENTS, FORMAT_GIF };
|
||||||
|
}
|
||||||
|
foreach (string currentFormat in retrieveFormats)
|
||||||
|
{
|
||||||
|
if (FORMAT_BITMAP_PLACEHOLDER.Equals(currentFormat))
|
||||||
|
{
|
||||||
|
LOG.Info("Using default .NET Clipboard.GetImage()");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
returnImage = Clipboard.GetImage();
|
||||||
|
if (returnImage != null)
|
||||||
|
{
|
||||||
|
return returnImage;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.Info("Clipboard.GetImage() didn't return an image.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LOG.Error("Problem retrieving Image via Clipboard.GetImage(): ", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (formats.Contains(currentFormat))
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Found {0}, trying to retrieve.", currentFormat);
|
||||||
|
if (currentFormat == DataFormats.Dib)
|
||||||
|
{
|
||||||
|
returnImage = GetDIBImage(dataObject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
returnImage = GetImageFormat(currentFormat, dataObject);
|
||||||
|
}
|
||||||
|
if (returnImage != null)
|
||||||
|
{
|
||||||
|
return returnImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Couldn't find format {0}.", currentFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// the DIB readed should solve the issue reported here: https://sourceforge.net/projects/greenshot/forums/forum/676083/topic/6354353/index/page/1
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Image</returns>
|
||||||
|
private static Image GetDIBImage(IDataObject dataObejct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// If the EnableSpecialDIBClipboardReader flag in the config is set, use the code from:
|
||||||
|
// http://www.thomaslevesque.com/2009/02/05/wpf-paste-an-image-from-the-clipboard/
|
||||||
|
// to read the DeviceIndependentBitmap from the clipboard, this might fix bug 3576125
|
||||||
|
if (config.EnableSpecialDIBClipboardReader)
|
||||||
|
{
|
||||||
|
MemoryStream dibStream = GetFromDataObject(dataObejct, DataFormats.Dib) as MemoryStream;
|
||||||
|
if (isValidStream(dibStream))
|
||||||
|
{
|
||||||
|
LOG.Info("Found valid DIB stream, trying to process it.");
|
||||||
|
byte[] dibBuffer = new byte[dibStream.Length];
|
||||||
|
dibStream.Read(dibBuffer, 0, dibBuffer.Length);
|
||||||
|
BitmapInfoHeader infoHeader = BinaryStructHelper.FromByteArray<BitmapInfoHeader>(dibBuffer);
|
||||||
|
// Only use this code, when the biCommpression != 0 (BI_RGB)
|
||||||
|
if (infoHeader.biCompression != 0)
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Using special DIB format reader for biCompression {0}", infoHeader.biCompression);
|
||||||
|
int fileHeaderSize = Marshal.SizeOf(typeof(BitmapFileHeader));
|
||||||
|
uint infoHeaderSize = infoHeader.biSize;
|
||||||
|
int fileSize = (int)(fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage);
|
||||||
|
|
||||||
|
BitmapFileHeader fileHeader = new BitmapFileHeader();
|
||||||
|
fileHeader.bfType = BitmapFileHeader.BM;
|
||||||
|
fileHeader.bfSize = fileSize;
|
||||||
|
fileHeader.bfReserved1 = 0;
|
||||||
|
fileHeader.bfReserved2 = 0;
|
||||||
|
fileHeader.bfOffBits = (int)(fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4);
|
||||||
|
|
||||||
|
byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray<BitmapFileHeader>(fileHeader);
|
||||||
|
|
||||||
|
using (MemoryStream bitmapStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
|
||||||
|
bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
|
||||||
|
bitmapStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
using (Image tmpImage = Image.FromStream(bitmapStream))
|
||||||
|
{
|
||||||
|
if (tmpImage != null)
|
||||||
|
{
|
||||||
|
return ImageHelper.Clone(tmpImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Skipping special DIB format reader for biCompression {0}", infoHeader.biCompression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.Info("Skipping special DIB format reader as it's disabled in the configuration.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception dibEx)
|
||||||
|
{
|
||||||
|
LOG.Error("Problem retrieving DIB from clipboard.", dibEx);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to try to get an image in the specified format from the dataObject
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">string with the format</param>
|
||||||
|
/// <param name="dataObject">IDataObject</param>
|
||||||
|
/// <returns>Image or null</returns>
|
||||||
|
private static Image GetImageFormat(string format, IDataObject dataObject)
|
||||||
|
{
|
||||||
|
MemoryStream imageStream = GetFromDataObject(dataObject, format) as MemoryStream;
|
||||||
|
if (isValidStream(imageStream))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (FileStream fs = new FileStream(@"C:\Localdata\test.png", FileMode.OpenOrCreate))
|
||||||
|
{
|
||||||
|
imageStream.WriteTo(fs);
|
||||||
|
}
|
||||||
|
imageStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
using (Image tmpImage = Image.FromStream(imageStream, true, true))
|
||||||
|
{
|
||||||
|
if (tmpImage != null)
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Got image with clipboard format {0} from the clipboard.", format);
|
||||||
|
return ImageHelper.Clone(tmpImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception streamImageEx)
|
||||||
|
{
|
||||||
|
LOG.Error(string.Format("Problem retrieving {0} from clipboard.", format), streamImageEx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wrapper for Clipboard.GetText created for Bug #3432313
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>string if there is text on the clipboard</returns>
|
||||||
|
public static string GetText()
|
||||||
|
{
|
||||||
|
return GetText(GetDataObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get Text from the DataObject
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>string if there is text on the clipboard</returns>
|
||||||
|
public static string GetText(IDataObject dataObject)
|
||||||
|
{
|
||||||
|
if (ContainsText(dataObject))
|
||||||
|
{
|
||||||
|
return (String)dataObject.GetData(DataFormats.Text);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set text to the clipboard
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text"></param>
|
||||||
|
public static void SetClipboardData(string text)
|
||||||
|
{
|
||||||
|
IDataObject ido = new DataObject();
|
||||||
|
ido.SetData(DataFormats.Text, true, text);
|
||||||
|
SetDataObject(ido, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string getHTMLString(ISurface surface, string filename)
|
||||||
|
{
|
||||||
|
string utf8EncodedHTMLString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HTML_CLIPBOARD_STRING));
|
||||||
|
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${width}", surface.Image.Width.ToString());
|
||||||
|
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${height}", surface.Image.Height.ToString());
|
||||||
|
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${file}", filename);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.Append(utf8EncodedHTMLString);
|
||||||
|
sb.Replace("<<<<<<<1", (utf8EncodedHTMLString.IndexOf("<HTML>") + "<HTML>".Length).ToString("D8"));
|
||||||
|
sb.Replace("<<<<<<<2", (utf8EncodedHTMLString.IndexOf("</HTML>")).ToString("D8"));
|
||||||
|
sb.Replace("<<<<<<<3", (utf8EncodedHTMLString.IndexOf("<!--StartFragment -->") + "<!--StartFragment -->".Length).ToString("D8"));
|
||||||
|
sb.Replace("<<<<<<<4", (utf8EncodedHTMLString.IndexOf("<!--EndFragment -->")).ToString("D8"));
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string getHTMLDataURLString(ISurface surface, MemoryStream pngStream)
|
||||||
|
{
|
||||||
|
string utf8EncodedHTMLString = Encoding.GetEncoding(0).GetString(Encoding.UTF8.GetBytes(HTML_CLIPBOARD_BASE64_STRING));
|
||||||
|
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${width}", surface.Image.Width.ToString());
|
||||||
|
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${height}", surface.Image.Height.ToString());
|
||||||
|
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${format}", "png");
|
||||||
|
utf8EncodedHTMLString = utf8EncodedHTMLString.Replace("${data}", Convert.ToBase64String(pngStream.GetBuffer(), 0, (int)pngStream.Length));
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.Append(utf8EncodedHTMLString);
|
||||||
|
sb.Replace("<<<<<<<1", (utf8EncodedHTMLString.IndexOf("<HTML>") + "<HTML>".Length).ToString("D8"));
|
||||||
|
sb.Replace("<<<<<<<2", (utf8EncodedHTMLString.IndexOf("</HTML>")).ToString("D8"));
|
||||||
|
sb.Replace("<<<<<<<3", (utf8EncodedHTMLString.IndexOf("<!--StartFragment -->") + "<!--StartFragment -->".Length).ToString("D8"));
|
||||||
|
sb.Replace("<<<<<<<4", (utf8EncodedHTMLString.IndexOf("<!--EndFragment -->")).ToString("D8"));
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set Object with type Type to the clipboard
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">Type</param>
|
||||||
|
/// <param name="obj">object</param>
|
||||||
|
public static void SetClipboardData(Type type, Object obj)
|
||||||
|
{
|
||||||
|
DataFormats.Format format = DataFormats.GetFormat(type.FullName);
|
||||||
|
|
||||||
|
//now copy to clipboard
|
||||||
|
IDataObject dataObj = new DataObject();
|
||||||
|
dataObj.SetData(format.Name, false, obj);
|
||||||
|
// Use false to make the object dissapear when the application stops.
|
||||||
|
SetDataObject(dataObj, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve a list of all formats currently on the clipboard
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>List<string> with the current formats</returns>
|
||||||
|
public static List<string> GetFormats()
|
||||||
|
{
|
||||||
|
return GetFormats(GetDataObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieve a list of all formats currently in the IDataObject
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>List<string> with the current formats</returns>
|
||||||
|
public static List<string> GetFormats(IDataObject dataObj)
|
||||||
|
{
|
||||||
|
string[] formats = null;
|
||||||
|
|
||||||
|
if (dataObj != null)
|
||||||
|
{
|
||||||
|
formats = dataObj.GetFormats();
|
||||||
|
}
|
||||||
|
if (formats != null)
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Got clipboard formats: {0}", String.Join(",", formats));
|
||||||
|
return new List<string>(formats);
|
||||||
|
}
|
||||||
|
return new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if there is currently something in the dataObject which has the supplied format
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObject">IDataObject</param>
|
||||||
|
/// <param name="format">string with format</param>
|
||||||
|
/// <returns>true if one the format is found</returns>
|
||||||
|
public static bool ContainsFormat(string format)
|
||||||
|
{
|
||||||
|
return ContainsFormat(GetDataObject(), new string[] { format });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if there is currently something on the clipboard which has the supplied format
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">string with format</param>
|
||||||
|
/// <returns>true if one the format is found</returns>
|
||||||
|
public static bool ContainsFormat(IDataObject dataObject, string format)
|
||||||
|
{
|
||||||
|
return ContainsFormat(dataObject, new string[] { format });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if there is currently something on the clipboard which has one of the supplied formats
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="formats">string[] with formats</param>
|
||||||
|
/// <returns>true if one of the formats was found</returns>
|
||||||
|
public static bool ContainsFormat(string[] formats)
|
||||||
|
{
|
||||||
|
return ContainsFormat(GetDataObject(), formats);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if there is currently something on the clipboard which has one of the supplied formats
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObject">IDataObject</param>
|
||||||
|
/// <param name="formats">string[] with formats</param>
|
||||||
|
/// <returns>true if one of the formats was found</returns>
|
||||||
|
public static bool ContainsFormat(IDataObject dataObject, string[] formats)
|
||||||
|
{
|
||||||
|
bool formatFound = false;
|
||||||
|
List<string> currentFormats = GetFormats(dataObject);
|
||||||
|
if (currentFormats == null || currentFormats.Count == 0 || formats == null || formats.Length == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach (string format in formats)
|
||||||
|
{
|
||||||
|
if (currentFormats.Contains(format))
|
||||||
|
{
|
||||||
|
formatFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formatFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get Object of type Type from the clipboard
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">Type to get</param>
|
||||||
|
/// <returns>object from clipboard</returns>
|
||||||
|
public static Object GetClipboardData(Type type)
|
||||||
|
{
|
||||||
|
string format = type.FullName;
|
||||||
|
return GetClipboardData(format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get Object for format from IDataObject
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObj">IDataObject</param>
|
||||||
|
/// <param name="type">Type to get</param>
|
||||||
|
/// <returns>object from IDataObject</returns>
|
||||||
|
public static Object GetFromDataObject(IDataObject dataObj, Type type)
|
||||||
|
{
|
||||||
|
if (type != null)
|
||||||
|
{
|
||||||
|
return GetFromDataObject(dataObj, type.FullName);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get ImageFilenames from the IDataObject
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObject">IDataObject</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static List<string> GetImageFilenames(IDataObject dataObject)
|
||||||
|
{
|
||||||
|
List<string> filenames = new List<string>();
|
||||||
|
string[] dropFileNames = (string[])dataObject.GetData(DataFormats.FileDrop);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (dropFileNames != null && dropFileNames.Length > 0)
|
||||||
|
{
|
||||||
|
foreach (string filename in dropFileNames)
|
||||||
|
{
|
||||||
|
string ext = Path.GetExtension(filename).ToLower();
|
||||||
|
if ((ext == ".jpg") || (ext == ".jpeg") || (ext == ".tiff") || (ext == ".gif") || (ext == ".png") || (ext == ".bmp") || (ext == ".ico") || (ext == ".wmf"))
|
||||||
|
{
|
||||||
|
filenames.Add(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LOG.Warn("Ignoring an issue with getting the dropFilenames from the clipboard: ", ex);
|
||||||
|
}
|
||||||
|
return filenames;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get Object for format from IDataObject
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataObj">IDataObject</param>
|
||||||
|
/// <param name="format">format to get</param>
|
||||||
|
/// <returns>object from IDataObject</returns>
|
||||||
|
public static Object GetFromDataObject(IDataObject dataObj, string format)
|
||||||
|
{
|
||||||
|
if (dataObj != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return dataObj.GetData(format);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error in GetClipboardData.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get Object for format from the clipboard
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">format to get</param>
|
||||||
|
/// <returns>object from clipboard</returns>
|
||||||
|
public static Object GetClipboardData(string format)
|
||||||
|
{
|
||||||
|
return GetFromDataObject(GetDataObject(), format);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
376
GreenshotImageEditor/Core/Effects.cs
Normal file
376
GreenshotImageEditor/Core/Effects.cs
Normal file
|
@ -0,0 +1,376 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using GreenshotPlugin;
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
|
||||||
|
namespace Greenshot.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface to describe an effect
|
||||||
|
/// </summary>
|
||||||
|
public interface IEffect
|
||||||
|
{
|
||||||
|
Image Apply(Image sourceImage, out Point offsetChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DropShadowEffect
|
||||||
|
/// </summary>
|
||||||
|
public class DropShadowEffect : IEffect
|
||||||
|
{
|
||||||
|
public DropShadowEffect()
|
||||||
|
{
|
||||||
|
Darkness = 0.6f;
|
||||||
|
ShadowSize = 9;
|
||||||
|
ShadowOffset = new Point(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Darkness
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public int ShadowSize
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public Point ShadowOffset
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
return ImageHelper.CreateShadow(sourceImage, Darkness, ShadowSize, ShadowOffset, out offsetChange, PixelFormat.Format32bppArgb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TornEdgeEffect extends on DropShadowEffect
|
||||||
|
/// </summary>
|
||||||
|
public class TornEdgeEffect : DropShadowEffect
|
||||||
|
{
|
||||||
|
public TornEdgeEffect()
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
ShadowSize = 7;
|
||||||
|
ToothHeight = 12;
|
||||||
|
HorizontalToothRange = 20;
|
||||||
|
VerticalToothRange = 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ToothHeight
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public int HorizontalToothRange
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public int VerticalToothRange
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
using (Image tmpTornImage = ImageHelper.CreateTornEdge(sourceImage, ToothHeight, HorizontalToothRange, VerticalToothRange))
|
||||||
|
{
|
||||||
|
return ImageHelper.CreateShadow(tmpTornImage, Darkness, ShadowSize, ShadowOffset, out offsetChange, PixelFormat.Format32bppArgb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GrayscaleEffect
|
||||||
|
/// </summary>
|
||||||
|
public class GrayscaleEffect : IEffect
|
||||||
|
{
|
||||||
|
public Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
offsetChange = Point.Empty;
|
||||||
|
return ImageHelper.CreateGrayscale(sourceImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MonochromeEffect
|
||||||
|
/// </summary>
|
||||||
|
public class MonochromeEffect : IEffect
|
||||||
|
{
|
||||||
|
private byte threshold;
|
||||||
|
|
||||||
|
/// <param name="threshold">Threshold for monochrome filter (0 - 255), lower value means less black</param>
|
||||||
|
public MonochromeEffect(byte threshold)
|
||||||
|
{
|
||||||
|
this.threshold = threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
offsetChange = Point.Empty;
|
||||||
|
return ImageHelper.CreateMonochrome(sourceImage, threshold);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AdjustEffect
|
||||||
|
/// </summary>
|
||||||
|
public class AdjustEffect : IEffect
|
||||||
|
{
|
||||||
|
public AdjustEffect()
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
Contrast = 1f;
|
||||||
|
Brightness = 1f;
|
||||||
|
Gamma = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float Contrast
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public float Brightness
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public float Gamma
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
offsetChange = Point.Empty;
|
||||||
|
return ImageHelper.Adjust(sourceImage, Brightness, Contrast, Gamma);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ReduceColorsEffect
|
||||||
|
/// </summary>
|
||||||
|
public class ReduceColorsEffect : IEffect
|
||||||
|
{
|
||||||
|
public ReduceColorsEffect()
|
||||||
|
: base()
|
||||||
|
{
|
||||||
|
Colors = 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Colors
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
offsetChange = Point.Empty;
|
||||||
|
using (WuQuantizer quantizer = new WuQuantizer((Bitmap)sourceImage))
|
||||||
|
{
|
||||||
|
int colorCount = quantizer.GetColorCount();
|
||||||
|
if (colorCount > Colors)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return quantizer.GetQuantizedImage(Colors);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// InvertEffect
|
||||||
|
/// </summary>
|
||||||
|
public class InvertEffect : IEffect
|
||||||
|
{
|
||||||
|
public Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
offsetChange = Point.Empty;
|
||||||
|
return ImageHelper.CreateNegative(sourceImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// BorderEffect
|
||||||
|
/// </summary>
|
||||||
|
public class BorderEffect : IEffect
|
||||||
|
{
|
||||||
|
public BorderEffect()
|
||||||
|
{
|
||||||
|
Width = 2;
|
||||||
|
Color = Color.Black;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color Color
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public int Width
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
return ImageHelper.CreateBorder(sourceImage, Width, Color, sourceImage.PixelFormat, out offsetChange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RotateEffect
|
||||||
|
/// </summary>
|
||||||
|
public class RotateEffect : IEffect
|
||||||
|
{
|
||||||
|
public RotateEffect(int angle)
|
||||||
|
{
|
||||||
|
Angle = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Angle
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
offsetChange = Point.Empty;
|
||||||
|
RotateFlipType flipType;
|
||||||
|
if (Angle == 90)
|
||||||
|
{
|
||||||
|
flipType = RotateFlipType.Rotate90FlipNone;
|
||||||
|
}
|
||||||
|
else if (Angle == -90 || Angle == 270)
|
||||||
|
{
|
||||||
|
flipType = RotateFlipType.Rotate270FlipNone;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Currently only an angle of 90 or -90 (270) is supported.");
|
||||||
|
}
|
||||||
|
return ImageHelper.RotateFlip(sourceImage, flipType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ResizeEffect
|
||||||
|
/// </summary>
|
||||||
|
public class ResizeEffect : IEffect
|
||||||
|
{
|
||||||
|
public ResizeEffect(int width, int height, bool maintainAspectRatio)
|
||||||
|
{
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
MaintainAspectRatio = maintainAspectRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Width
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public int Height
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public bool MaintainAspectRatio
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
offsetChange = Point.Empty;
|
||||||
|
return ImageHelper.ResizeImage(sourceImage, MaintainAspectRatio, Width, Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ResizeCanvasEffect
|
||||||
|
/// </summary>
|
||||||
|
public class ResizeCanvasEffect : IEffect
|
||||||
|
{
|
||||||
|
public ResizeCanvasEffect(int left, int right, int top, int bottom)
|
||||||
|
{
|
||||||
|
Left = left;
|
||||||
|
Right = right;
|
||||||
|
Top = top;
|
||||||
|
Bottom = bottom;
|
||||||
|
BackgroundColor = Color.Empty; // Uses the default background color depending on the format
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Left
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public int Right
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public int Top
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public int Bottom
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public Color BackgroundColor
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image Apply(Image sourceImage, out Point offsetChange)
|
||||||
|
{
|
||||||
|
// Make sure the elements move according to the offset the effect made the bitmap move
|
||||||
|
offsetChange = new Point(Left, Top);
|
||||||
|
return ImageHelper.ResizeCanvas(sourceImage, BackgroundColor, Left, Right, Top, Bottom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
101
GreenshotImageEditor/Core/EncryptionHelper.cs
Normal file
101
GreenshotImageEditor/Core/EncryptionHelper.cs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
public static class EncryptionHelper
|
||||||
|
{
|
||||||
|
private const string RGBIV = "dlgjowejgogkklwj";
|
||||||
|
private const string KEY = "lsjvkwhvwujkagfauguwcsjgu2wueuff";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A simply rijndael aes encryption, can be used to store passwords
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ClearText">the string to call upon</param>
|
||||||
|
/// <returns>an encryped string in base64 form</returns>
|
||||||
|
public static string Encrypt(this string ClearText)
|
||||||
|
{
|
||||||
|
string returnValue = ClearText;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] clearTextBytes = Encoding.ASCII.GetBytes(ClearText);
|
||||||
|
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
|
||||||
|
|
||||||
|
using (MemoryStream ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
|
||||||
|
byte[] key = Encoding.ASCII.GetBytes(KEY);
|
||||||
|
CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write);
|
||||||
|
|
||||||
|
cs.Write(clearTextBytes, 0, clearTextBytes.Length);
|
||||||
|
|
||||||
|
cs.Close();
|
||||||
|
returnValue = Convert.ToBase64String(ms.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LOG.ErrorFormat("Error encrypting, error: ", ex.Message);
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A simply rijndael aes decryption, can be used to store passwords
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="EncryptedText">a base64 encoded rijndael encrypted string</param>
|
||||||
|
/// <returns>Decrypeted text</returns>
|
||||||
|
public static string Decrypt(this string EncryptedText)
|
||||||
|
{
|
||||||
|
string returnValue = EncryptedText;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] encryptedTextBytes = Convert.FromBase64String(EncryptedText);
|
||||||
|
using (MemoryStream ms = new MemoryStream())
|
||||||
|
{
|
||||||
|
SymmetricAlgorithm rijn = SymmetricAlgorithm.Create();
|
||||||
|
|
||||||
|
byte[] rgbIV = Encoding.ASCII.GetBytes(RGBIV);
|
||||||
|
byte[] key = Encoding.ASCII.GetBytes(KEY);
|
||||||
|
|
||||||
|
CryptoStream cs = new CryptoStream(ms, rijn.CreateDecryptor(key, rgbIV),
|
||||||
|
CryptoStreamMode.Write);
|
||||||
|
|
||||||
|
cs.Write(encryptedTextBytes, 0, encryptedTextBytes.Length);
|
||||||
|
|
||||||
|
cs.Close();
|
||||||
|
returnValue = Encoding.ASCII.GetString(ms.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LOG.ErrorFormat("Error decrypting {0}, error: ", EncryptedText, ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
122
GreenshotImageEditor/Core/EnumExtensions.cs
Normal file
122
GreenshotImageEditor/Core/EnumExtensions.cs
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
public static class EnumerationExtensions
|
||||||
|
{
|
||||||
|
public static bool Has<T>(this Enum type, T value)
|
||||||
|
{
|
||||||
|
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (underlyingType == typeof(int))
|
||||||
|
{
|
||||||
|
return (((int)(object)type & (int)(object)value) == (int)(object)value);
|
||||||
|
}
|
||||||
|
else if (underlyingType == typeof(uint))
|
||||||
|
{
|
||||||
|
return (((uint)(object)type & (uint)(object)value) == (uint)(object)value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Is<T>(this Enum type, T value)
|
||||||
|
{
|
||||||
|
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (underlyingType == typeof(int))
|
||||||
|
{
|
||||||
|
return (int)(object)type == (int)(object)value;
|
||||||
|
}
|
||||||
|
else if (underlyingType == typeof(uint))
|
||||||
|
{
|
||||||
|
return (uint)(object)type == (uint)(object)value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a flag to an enum
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T Add<T>(this Enum type, T value)
|
||||||
|
{
|
||||||
|
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (underlyingType == typeof(int))
|
||||||
|
{
|
||||||
|
return (T)(object)(((int)(object)type | (int)(object)value));
|
||||||
|
}
|
||||||
|
else if (underlyingType == typeof(uint))
|
||||||
|
{
|
||||||
|
return (T)(object)(((uint)(object)type | (uint)(object)value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format("Could not append value '{0}' to enumerated type '{1}'.", value, typeof(T).Name), ex);
|
||||||
|
}
|
||||||
|
throw new ArgumentException(string.Format("Could not append value '{0}' to enumerated type '{1}'.", value, typeof(T).Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove a flag from an enum type
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T Remove<T>(this Enum type, T value)
|
||||||
|
{
|
||||||
|
Type underlyingType = Enum.GetUnderlyingType(value.GetType());
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (underlyingType == typeof(int))
|
||||||
|
{
|
||||||
|
return (T)(object)(((int)(object)type & ~(int)(object)value));
|
||||||
|
}
|
||||||
|
else if (underlyingType == typeof(uint))
|
||||||
|
{
|
||||||
|
return (T)(object)(((uint)(object)type & ~(uint)(object)value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format("Could not remove value '{0}' from enumerated type '{1}'.", value, typeof(T).Name), ex);
|
||||||
|
}
|
||||||
|
throw new ArgumentException(string.Format("Could not remove value '{0}' from enumerated type '{1}'.", value, typeof(T).Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1171
GreenshotImageEditor/Core/FastBitmap.cs
Normal file
1171
GreenshotImageEditor/Core/FastBitmap.cs
Normal file
File diff suppressed because it is too large
Load diff
545
GreenshotImageEditor/Core/FilenameHelper.cs
Normal file
545
GreenshotImageEditor/Core/FilenameHelper.cs
Normal file
|
@ -0,0 +1,545 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using Greenshot.Plugin;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
public static class FilenameHelper
|
||||||
|
{
|
||||||
|
private static readonly Regex VAR_REGEXP = new Regex(@"\${(?<variable>[^:}]+)[:]?(?<parameters>[^}]*)}", RegexOptions.Compiled);
|
||||||
|
private static readonly Regex SPLIT_REGEXP = new Regex(";(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", RegexOptions.Compiled);
|
||||||
|
private const int MAX_TITLE_LENGTH = 80;
|
||||||
|
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
|
private const string UNSAFE_REPLACEMENT = "_";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove invalid characters from the fully qualified filename
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fullpath">string with the full path to a file</param>
|
||||||
|
/// <returns>string with the full path to a file, without invalid characters</returns>
|
||||||
|
public static string MakeFQFilenameSafe(string fullPath)
|
||||||
|
{
|
||||||
|
string path = MakePathSafe(Path.GetDirectoryName(fullPath));
|
||||||
|
string filename = MakeFilenameSafe(Path.GetFileName(fullPath));
|
||||||
|
// Make the fullpath again and return
|
||||||
|
return Path.Combine(path, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove invalid characters from the filename
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fullpath">string with the full path to a file</param>
|
||||||
|
/// <returns>string with the full path to a file, without invalid characters</returns>
|
||||||
|
public static string MakeFilenameSafe(string filename)
|
||||||
|
{
|
||||||
|
// Make the filename save!
|
||||||
|
if (filename != null)
|
||||||
|
{
|
||||||
|
foreach (char disallowed in Path.GetInvalidFileNameChars())
|
||||||
|
{
|
||||||
|
filename = filename.Replace(disallowed.ToString(), UNSAFE_REPLACEMENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove invalid characters from the path
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fullpath">string with the full path to a file</param>
|
||||||
|
/// <returns>string with the full path to a file, without invalid characters</returns>
|
||||||
|
public static string MakePathSafe(string path)
|
||||||
|
{
|
||||||
|
// Make the path save!
|
||||||
|
if (path != null)
|
||||||
|
{
|
||||||
|
foreach (char disallowed in Path.GetInvalidPathChars())
|
||||||
|
{
|
||||||
|
path = path.Replace(disallowed.ToString(), UNSAFE_REPLACEMENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetFilenameWithoutExtensionFromPattern(string pattern)
|
||||||
|
{
|
||||||
|
return GetFilenameWithoutExtensionFromPattern(pattern, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetFilenameWithoutExtensionFromPattern(string pattern, ICaptureDetails captureDetails)
|
||||||
|
{
|
||||||
|
return FillPattern(pattern, captureDetails, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetFilenameFromPattern(string pattern, OutputFormat imageFormat)
|
||||||
|
{
|
||||||
|
return GetFilenameFromPattern(pattern, imageFormat, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetFilenameFromPattern(string pattern, OutputFormat imageFormat, ICaptureDetails captureDetails)
|
||||||
|
{
|
||||||
|
return FillPattern(pattern, captureDetails, true) + "." + imageFormat.ToString().ToLower();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return a filename for the current image format (png,jpg etc) with the default file pattern
|
||||||
|
/// that is specified in the configuration
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">A string with the format</param>
|
||||||
|
/// <returns>The filename which should be used to save the image</returns>
|
||||||
|
public static string GetFilename(OutputFormat format, ICaptureDetails captureDetails)
|
||||||
|
{
|
||||||
|
string pattern = conf.OutputFileFilenamePattern;
|
||||||
|
if (pattern == null || string.IsNullOrEmpty(pattern.Trim()))
|
||||||
|
{
|
||||||
|
pattern = "greenshot ${capturetime}";
|
||||||
|
}
|
||||||
|
return GetFilenameFromPattern(pattern, format, captureDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will be called by the regexp.replace as a MatchEvaluator delegate!
|
||||||
|
/// Will delegate this to the MatchVarEvaluatorInternal and catch any exceptions
|
||||||
|
/// <param name="match">What are we matching?</param>
|
||||||
|
/// <param name="captureDetails">The detail, can be null</param>
|
||||||
|
/// <param name="processVars">Variables from the process</param>
|
||||||
|
/// <param name="userVars">Variables from the user</param>
|
||||||
|
/// <param name="machineVars">Variables from the machine</param>
|
||||||
|
/// <returns>string with the match replacement</returns>
|
||||||
|
private static string MatchVarEvaluator(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars, bool filenameSafeMode)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return MatchVarEvaluatorInternal(match, captureDetails, processVars, userVars, machineVars, filenameSafeMode);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error in MatchVarEvaluatorInternal", e);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will be called by the regexp.replace as a MatchEvaluator delegate!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="match">What are we matching?</param>
|
||||||
|
/// <param name="captureDetails">The detail, can be null</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static string MatchVarEvaluatorInternal(Match match, ICaptureDetails captureDetails, IDictionary processVars, IDictionary userVars, IDictionary machineVars, bool filenameSafeMode)
|
||||||
|
{
|
||||||
|
// some defaults
|
||||||
|
int padWidth = 0;
|
||||||
|
int startIndex = 0;
|
||||||
|
int endIndex = 0;
|
||||||
|
char padChar = ' ';
|
||||||
|
string dateFormat = "yyyy-MM-dd HH-mm-ss";
|
||||||
|
|
||||||
|
string replaceValue = "";
|
||||||
|
string variable = match.Groups["variable"].Value;
|
||||||
|
string parameters = match.Groups["parameters"].Value;
|
||||||
|
|
||||||
|
if (parameters != null && parameters.Length > 0)
|
||||||
|
{
|
||||||
|
string[] parms = SPLIT_REGEXP.Split(parameters);
|
||||||
|
foreach (string parameter in parms)
|
||||||
|
{
|
||||||
|
switch (parameter.Substring(0, 1))
|
||||||
|
{
|
||||||
|
case "p":
|
||||||
|
string[] padParams = parameter.Substring(1).Split(new char[] { ',' });
|
||||||
|
try
|
||||||
|
{
|
||||||
|
padWidth = int.Parse(padParams[0]);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
};
|
||||||
|
if (padParams.Length > 1)
|
||||||
|
{
|
||||||
|
padChar = padParams[1][0];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "d":
|
||||||
|
dateFormat = parameter.Substring(1);
|
||||||
|
if (dateFormat.StartsWith("\""))
|
||||||
|
{
|
||||||
|
dateFormat = dateFormat.Substring(1);
|
||||||
|
}
|
||||||
|
if (dateFormat.EndsWith("\""))
|
||||||
|
{
|
||||||
|
dateFormat = dateFormat.Substring(0, dateFormat.Length - 1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "s":
|
||||||
|
string range = parameter.Substring(1);
|
||||||
|
string[] rangelist = range.Split(new char[] { ',' });
|
||||||
|
if (rangelist.Length > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
startIndex = int.Parse(rangelist[0]);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rangelist.Length > 1)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
endIndex = int.Parse(rangelist[1]);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (processVars != null && processVars.Contains(variable))
|
||||||
|
{
|
||||||
|
replaceValue = (string)processVars[variable];
|
||||||
|
if (filenameSafeMode)
|
||||||
|
{
|
||||||
|
replaceValue = MakePathSafe(replaceValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (userVars != null && userVars.Contains(variable))
|
||||||
|
{
|
||||||
|
replaceValue = (string)userVars[variable];
|
||||||
|
if (filenameSafeMode)
|
||||||
|
{
|
||||||
|
replaceValue = MakePathSafe(replaceValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (machineVars != null && machineVars.Contains(variable))
|
||||||
|
{
|
||||||
|
replaceValue = (string)machineVars[variable];
|
||||||
|
if (filenameSafeMode)
|
||||||
|
{
|
||||||
|
replaceValue = MakePathSafe(replaceValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (captureDetails != null && captureDetails.MetaData != null && captureDetails.MetaData.ContainsKey(variable))
|
||||||
|
{
|
||||||
|
replaceValue = captureDetails.MetaData[variable];
|
||||||
|
if (filenameSafeMode)
|
||||||
|
{
|
||||||
|
replaceValue = MakePathSafe(replaceValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Handle other variables
|
||||||
|
// Default use "now" for the capture take´n
|
||||||
|
DateTime capturetime = DateTime.Now;
|
||||||
|
// Use default application name for title
|
||||||
|
string title = Application.ProductName;
|
||||||
|
|
||||||
|
// Check if we have capture details
|
||||||
|
if (captureDetails != null)
|
||||||
|
{
|
||||||
|
capturetime = captureDetails.DateTime;
|
||||||
|
if (captureDetails.Title != null)
|
||||||
|
{
|
||||||
|
title = captureDetails.Title;
|
||||||
|
if (title.Length > MAX_TITLE_LENGTH)
|
||||||
|
{
|
||||||
|
title = title.Substring(0, MAX_TITLE_LENGTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (variable)
|
||||||
|
{
|
||||||
|
case "domain":
|
||||||
|
replaceValue = Environment.UserDomainName;
|
||||||
|
break;
|
||||||
|
case "user":
|
||||||
|
replaceValue = Environment.UserName;
|
||||||
|
break;
|
||||||
|
case "hostname":
|
||||||
|
replaceValue = Environment.MachineName;
|
||||||
|
break;
|
||||||
|
case "YYYY":
|
||||||
|
if (padWidth == 0)
|
||||||
|
{
|
||||||
|
padWidth = -4;
|
||||||
|
padChar = '0';
|
||||||
|
}
|
||||||
|
replaceValue = capturetime.Year.ToString();
|
||||||
|
break;
|
||||||
|
case "MM":
|
||||||
|
replaceValue = capturetime.Month.ToString();
|
||||||
|
if (padWidth == 0)
|
||||||
|
{
|
||||||
|
padWidth = -2;
|
||||||
|
padChar = '0';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "DD":
|
||||||
|
replaceValue = capturetime.Day.ToString();
|
||||||
|
if (padWidth == 0)
|
||||||
|
{
|
||||||
|
padWidth = -2;
|
||||||
|
padChar = '0';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "hh":
|
||||||
|
if (padWidth == 0)
|
||||||
|
{
|
||||||
|
padWidth = -2;
|
||||||
|
padChar = '0';
|
||||||
|
}
|
||||||
|
replaceValue = capturetime.Hour.ToString();
|
||||||
|
break;
|
||||||
|
case "mm":
|
||||||
|
if (padWidth == 0)
|
||||||
|
{
|
||||||
|
padWidth = -2;
|
||||||
|
padChar = '0';
|
||||||
|
}
|
||||||
|
replaceValue = capturetime.Minute.ToString();
|
||||||
|
break;
|
||||||
|
case "ss":
|
||||||
|
if (padWidth == 0)
|
||||||
|
{
|
||||||
|
padWidth = -2;
|
||||||
|
padChar = '0';
|
||||||
|
}
|
||||||
|
replaceValue = capturetime.Second.ToString();
|
||||||
|
break;
|
||||||
|
case "now":
|
||||||
|
replaceValue = DateTime.Now.ToString(dateFormat);
|
||||||
|
if (filenameSafeMode)
|
||||||
|
{
|
||||||
|
replaceValue = MakeFilenameSafe(replaceValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "capturetime":
|
||||||
|
replaceValue = capturetime.ToString(dateFormat);
|
||||||
|
if (filenameSafeMode)
|
||||||
|
{
|
||||||
|
replaceValue = MakeFilenameSafe(replaceValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "NUM":
|
||||||
|
conf.OutputFileIncrementingNumber++;
|
||||||
|
IniConfig.Save();
|
||||||
|
replaceValue = conf.OutputFileIncrementingNumber.ToString();
|
||||||
|
if (padWidth == 0)
|
||||||
|
{
|
||||||
|
padWidth = -6;
|
||||||
|
padChar = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case "title":
|
||||||
|
replaceValue = title;
|
||||||
|
if (filenameSafeMode)
|
||||||
|
{
|
||||||
|
replaceValue = MakeFilenameSafe(replaceValue);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "MyPictures":
|
||||||
|
replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
|
||||||
|
break;
|
||||||
|
case "MyMusic":
|
||||||
|
replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
|
||||||
|
break;
|
||||||
|
case "MyDocuments":
|
||||||
|
replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
|
||||||
|
break;
|
||||||
|
case "Personal":
|
||||||
|
replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
||||||
|
break;
|
||||||
|
case "Desktop":
|
||||||
|
replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||||
|
break;
|
||||||
|
case "ApplicationData":
|
||||||
|
replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||||
|
break;
|
||||||
|
case "LocalApplicationData":
|
||||||
|
replaceValue = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// do padding
|
||||||
|
if (padWidth > 0)
|
||||||
|
{
|
||||||
|
replaceValue = replaceValue.PadRight(padWidth, padChar);
|
||||||
|
}
|
||||||
|
else if (padWidth < 0)
|
||||||
|
{
|
||||||
|
replaceValue = replaceValue.PadLeft(-padWidth, padChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
// do substring
|
||||||
|
if (startIndex != 0 || endIndex != 0)
|
||||||
|
{
|
||||||
|
if (startIndex < 0)
|
||||||
|
{
|
||||||
|
startIndex = replaceValue.Length + startIndex;
|
||||||
|
}
|
||||||
|
if (endIndex < 0)
|
||||||
|
{
|
||||||
|
endIndex = replaceValue.Length + endIndex;
|
||||||
|
}
|
||||||
|
if (endIndex != 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
replaceValue = replaceValue.Substring(startIndex, endIndex);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
replaceValue = replaceValue.Substring(startIndex);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return replaceValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// "Simply" fill the pattern with environment variables
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pattern">String with pattern ${var}</param>
|
||||||
|
/// <param name="filenameSafeMode">true to make sure everything is filenamesafe</param>
|
||||||
|
/// <returns>Filled string</returns>
|
||||||
|
public static string FillVariables(string pattern, bool filenameSafeMode)
|
||||||
|
{
|
||||||
|
IDictionary processVars = null;
|
||||||
|
IDictionary userVars = null;
|
||||||
|
IDictionary machineVars = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error retrieving EnvironmentVariableTarget.Process", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error retrieving EnvironmentVariableTarget.User", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error retrieving EnvironmentVariableTarget.Machine", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return VAR_REGEXP.Replace(pattern,
|
||||||
|
delegate(Match m)
|
||||||
|
{
|
||||||
|
return MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fill the pattern wit the supplied details
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pattern">Pattern</param>
|
||||||
|
/// <param name="captureDetails">CaptureDetails</param>
|
||||||
|
/// <param name="filenameSafeMode">Should the result be made "filename" safe?</param>
|
||||||
|
/// <returns>Filled pattern</returns>
|
||||||
|
public static string FillPattern(string pattern, ICaptureDetails captureDetails, bool filenameSafeMode)
|
||||||
|
{
|
||||||
|
IDictionary processVars = null;
|
||||||
|
IDictionary userVars = null;
|
||||||
|
IDictionary machineVars = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
processVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Process);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error retrieving EnvironmentVariableTarget.Process", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
userVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error retrieving EnvironmentVariableTarget.User", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
machineVars = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error retrieving EnvironmentVariableTarget.Machine", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return VAR_REGEXP.Replace(pattern,
|
||||||
|
delegate(Match m)
|
||||||
|
{
|
||||||
|
return MatchVarEvaluator(m, captureDetails, processVars, userVars, machineVars, filenameSafeMode);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// adding additional data for bug tracking
|
||||||
|
e.Data.Add("title", captureDetails.Title);
|
||||||
|
e.Data.Add("pattern", pattern);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
GreenshotImageEditor/Core/GreenshotResources.cs
Normal file
54
GreenshotImageEditor/Core/GreenshotResources.cs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Centralized storage of the icons & bitmaps
|
||||||
|
/// </summary>
|
||||||
|
public static class GreenshotResources
|
||||||
|
{
|
||||||
|
private static ComponentResourceManager greenshotResources = new ComponentResourceManager(typeof(GreenshotResources));
|
||||||
|
|
||||||
|
public static Image getImage(string imageName)
|
||||||
|
{
|
||||||
|
return (Image)greenshotResources.GetObject(imageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Icon getIcon(string imageName)
|
||||||
|
{
|
||||||
|
return (Icon)greenshotResources.GetObject(imageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Icon getGreenshotIcon()
|
||||||
|
{
|
||||||
|
return getIcon("Greenshot.Icon");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Image getGreenshotImage()
|
||||||
|
{
|
||||||
|
return getImage("Greenshot.Image");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
471
GreenshotImageEditor/Core/GreenshotResources.resx
Normal file
471
GreenshotImageEditor/Core/GreenshotResources.resx
Normal file
|
@ -0,0 +1,471 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
|
<data name="Greenshot.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
AAABAAUAAAAAAAEACAClFwAAVgAAADAwAAABAAgAqA4AAPsXAAAgIAAAAQAIAKgIAACjJgAAGBgAAAEA
|
||||||
|
CADIBgAASy8AABAQAAABAAgAaAUAABM2AACJUE5HDQoaCgAAAA1JSERSAAABAAAAAQAIBgAAAFxyqGYA
|
||||||
|
ABdsSURBVHja7Z1fqFVVHsf3YQqnUTJQSJMcujkK3UHuFW5geBXGYK5B0EP6Gto8zIsG8zKY82rCvKXP
|
||||||
|
6bv2FqQP9eAfEhS8Eilozo0xTAOFbGycKLjTd9u6nnvvXnuvvff6/dbea30/cEioPPucs9Z3/dbv72By
|
||||||
|
cnI2I4QkyYACQEi6UAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMB
|
||||||
|
ICRhKACEJAwFgJCEoQAQkjAUAEIShgJASMJQAAhJGAoAIQlDASAkYSgAhCQMBYCQhKEAEJIwFABCEoYC
|
||||||
|
QEjCUAAISRgKACEJQwEgJGEoAIQkDAWAkIShABCSMBQAQhKGAkBIwlAACEkYCgAhCUMBICRhKACEJAwF
|
||||||
|
gJCEoQAQkjAUAEIShgJASMJQAAhJmOgF4MllP2dP/+GH/M8rx77L7t9Ylv304Ins4e0l2X/v/Db04xES
|
||||||
|
lCgF4Her/pc9v+PbbNXkvezpdT9Y/7uHd5Zkt8+tzL4++Wz2/ZdLQz82IepEJQDY+Ov33Myen/q29v97
|
||||||
|
7/Ly7Nqx32f3ppeH/hiEqBGNAIzsvJVv/ieX/tzq75n5cE12/eja/JpASOxEIQBj715vdOrb+P7G0uyz
|
||||||
|
fRspAiR6ei8Avje/gSJAUqDXArBh97+z9btviv398AtABAiJld4KwIrx+9kr738u/j5XjoxkMyfWhP64
|
||||||
|
hIjQWwF45fDn2Yqx++Lv89MPT2Sf7pzgVYBESS8FQOv0N1w/tjYPERISG70UgIn3rmarttxTez9YAad2
|
||||||
|
bA79sQnxTu8EAKm9Ux+fV3/fiwdeyu6cXRH64xPild4JANJ7Jw5eVX9fJAhdOTwS+uMT4pXeCYB06M9G
|
||||||
|
m5AgfBYoRDJ/BihK+vk/v8nuXn6G6cckGL0TAO37vwGFQ5/setn5v0cFItKTYbFUpSfDx4DrBYqSKAZE
|
||||||
|
k94JgFb4r4iPtk5W/jcoSBrdN9NYpGBpfHHkRVYnEhUoADWoEgCUIGPzty1IAkxAIhr0TgBCXQFQG3B6
|
||||||
|
zybrv8fGH3nzltf3/PrUs9nl99arf1aSDr0TgC46ASWfiSJAJOmdAIQKA9qyATWyEi8fWp87CAnxTe8E
|
||||||
|
IFQi0Om3Ny1yzOFZth29lD216kfR92Y9ApHCSQDg2cZJh38ivIWFj4aaprEmQleaDTalegDYsIUANa8j
|
||||||
|
vAoQCawCgE0OrzZi2S4nHJxk8Fojni19UnWhGAjfz/YTF714/F35dNcEOxkTrxQKAE62F3Z902hxw1xF
|
||||||
|
Tz3pEFbocmCI49j+6+LvPwxDg8Q38wQAJj7CbGWttF2B1/ziuy+JWQN41q3HpsVPYFsRUIhwZFUokpC6
|
||||||
|
zAkA7vY4VX1uKNydLxwYFctqkz6Fy+7dUyfPq5r/hlOvbaYzkHgjFwCJzW+ACODUklq0kk1BbactrI/t
|
||||||
|
xy+KfJ4qPntnY+16ATxvPiTll985d+gOXZ1gqRlHrrYzl4Rn8Kcdm2ex+X2Y/Takm2v6zsK7c25FfvLb
|
||||||
|
REvbCTlMHQHAc+YFSTWuKvjs8DOwKCkNBn89sWbWdwprEdIOLJxwsAbaWDGuDsyQAuDyPeKUx3fRxkkK
|
||||||
|
0YYI0iKIm8E/ZzOVRCCNZBaE5nDiNYlg4L6Pze+y4LtsAfgQQgN+M4gAOyHFi5oAAK3mmhACbAS8sFlt
|
||||||
|
mwGnHBY3XnVOOtylt31wSetrm0eZAEg5RZmKHC+qAlC3qYYvYBI/tfpxMhOskLaRidfPnFX/HMCWDCRd
|
||||||
|
I9HE+Ui6j6oAgKKc+j6CGgBJx2kRNgHVyEpkPUKcqAtALNls8DWM7p1RfU9bY1KtpCTWI8SHugA0XUTm
|
||||||
|
Pr983YNHBUm/nnaI1+NUgnl6+9xKNesiRC5AkfWk7ZCMxYIjj1AXgDo5Adhk8OjDueVq3sJMhoUBp5W0
|
||||||
|
uapZlWj73rQrI2kFxEVnBaBNQRKAEKC5pmQIS9MKKHLCheqNwHTkeOicAGBR407rq9JP+sTS6Algu/uH
|
||||||
|
6o7EKUnxoC4ASDVFlWAR2PwSacnSIiBZmgwfBwSz6MQN1R/RRz6HaSwDTGMZoo+6ANgWj9TmN0iKgNSz
|
||||||
|
l21+EKpFepPaDmx4+HIwIcn2PeHvxTUH/hsKgg7qAmBLKNEIZUmGICECcMj5+gwu/RT6IACIUvxx779q
|
||||||
|
iyPeAwcFk49kURUA25htrVCWRjIL8gPW77nZ2HmJZ/zq+HNOJnaXBcCXLweWG/wfdDrKoCoANjNccyFr
|
||||||
|
hLGaFCVh48P0xeZ3NX+7KgC++0vgKjR9aAPzDwRQFYCiPPYQlXWaYSxbAhMwzThMQVJdQglAmSNXqrkM
|
||||||
|
BBKiQxHwy+Dv08tnNRaR7eTVTmQBsVS3dS0KIN2nscopSuoz+PPOiVnp5ppld+8QvfXKTrA+Eaovgc2R
|
||||||
|
q2GRxPLbdYW8J6B0c03bgglVV29zRvYRbQG1fXeabdJZmuyPua7AIZpJhOysE0s6q8RU4jJsWYmvHr8g
|
||||||
|
PiLNIN1jMiXmzQXwOd/epZ1UqDssiOUU0a5KLHLkhkhJZlWiHxZNBoJZjsQNjYaSFAA/aH2PNudfiCEp
|
||||||
|
NkuE1MM6GxDWAF51hKBu9laIphqGmARAOo0alM1JCOHI5ZQkP1ROBzZDJeamAw8tMvwIZqhE3caaIKQP
|
||||||
|
4KOtk0HeVwrJ4S5lMfiQDVLb/IZmPeNluH9jWb6GU7paOI0HlyLUhJ1QzUmlkRCBqgScLrdIXwgOMli1
|
||||||
|
VdcVfGYcaKgbiV0MggoA0PQeG2LuauNzwCssPMTcyyy7EFOSDa4CgI0Pv1aTdYZrLRrLxCoEgzf2bcwF
|
||||||
|
IFRNtnYYC6TQ0KLtiHfXgqQu+3F8VmhqzbTQZlEtQNNhGU3RvgbElARUhSlKwintcvrhaoScDZi+rjkS
|
||||||
|
Xb0C4Do0vv+aV8eo9Mj7EJQWA9UZl9UGzXqAWJW8CmwINOPAgBQUJhng+IL1d/fyM43M3C4mc0nWJMSW
|
||||||
|
hORUDSi9abSsAOlR5akSYkpSmSNXemhLTDkIzuXA0uaPRjJLTLH/LhGiLNnmyNVKioplLdXqByBdjil5
|
||||||
|
FYilBLiLhIgEFG1ATX9SLKHk2g1BpMsxJUQg1Xu/FhqzCYexbT7t3hIxHCqNOgJJz/fzFRqExx93tb7/
|
||||||
|
SH1As67DtvG0U5JjcAg2EgCN5ppNu8kaYKlg87O9tA6wAuB8k07qsm26UENS+l5W3rgnoJYn1DV9E6SU
|
||||||
|
wtlFpEOC+H3P7B4vFPUQCWWg70lljQVAe148Tph5zTV/nSqDxWDi2DF4ZfuOpEOwbLOFapDad/9Sq67A
|
||||||
|
MThBiH98i4BLc5kQJcmg7z0KWwlAzEU1pB2w1pCK29Yn4DoTIEQyEui7I7CVALRpygAT3qSnDoPUVPzY
|
||||||
|
dN71nyYDUgx1CpIABaAZrQeD1GnKgAUBpx4WRZV3H7He2+dW1pqUQ7oJfvfckYvGMhX3dJjUMPXrXi1D
|
||||||
|
lJWDvlvBagLQpjxVqyiJ6LCwGw+sPjiT2zhx6QRshrgA+CrLZFIPKSNUg9m+1wSICgCUHt1pfHpn+25y
|
||||||
|
ERlC9CaMobdEKwEoK4iQ/EEoAqQIbT9ADOuwlQDYYqDSQyIBcxDIQrSrEouGpPQNkUQgDYdMWVooSRct
|
||||||
|
KyCG0x+0EoCiQgjNFlGx/AjEHxrrL6bDp7EA2DafdjgmBjOM+EW6MKjvBUDDNBaAoo0XwhMbU3824g+p
|
||||||
|
5iCx+Z4aCYBt04UoyYylNRPxj28RiG3zg9oCUNYXMFQ2Fq8BxAbSjyEEbSJSrgVJfaSWAFQ5P0IVZMR0
|
||||||
|
JyP+aVqUBOsSab6xnfrDOAsAvowLB0atKogveerj80E+RN/zsYke+cj78fuPhqQUhAtx2qM2wUzHih0n
|
||||||
|
AUDCDzz+Zd1/Qk6IoQCQpiBpDdOSQs3GDE2pAODUx2RUFyWkABDSPxYJgGms2cQECuUDkG5TTkisDP5y
|
||||||
|
dG0uAGiqCRO/jaczVF+2vpdkEhKKweTkZKty4GFQ+utjFntd6nQlIoQ8xqsAINQyundG9QP0vSsrISHx
|
||||||
|
KgAhQoExZmcRooVXAQCaAxq1h5MQEhveBUBzRDPDf4S0w7sAAI0GjW1mEhBCHiEiAECyMAimPwqSYizO
|
||||||
|
IEQTMQGAQxAi0LYd+EK4+Qnxx+CtwyOzUll0EAHkBviyBLj5CfHL4OCDJ2al+5v58Am4FCQRQuqR1wJo
|
||||||
|
NNdEdGD9npu1Q4QYvghPP1N9CfHPXDGQVlcdMyA0HxQ5fr+wdgCbHjXZSPChuU+IHHMCELKiztRk85Qn
|
||||||
|
RJc5AWBcnZD0mNcPgFV1hKTFPAFoUlePWQDos7Z83YNF4T6E7XCHx995+9xK3ucJ6RiNBQCbHuG9OnPY
|
||||||
|
cM2An4HVe4R0g9oCAM/9+P5rrQYwwsuPXoO0CAgJSy0B8NnwA9cDTBeiNUBIOJwFgLPWCIkPpyiAdKsv
|
||||||
|
TvYhJAyVeQAaE39jmrdOSJ+ozATUGvjJ5p6E6FNaC4B8/YmDV9Ue5vTbmxgZIESR0mpA7XHfGlWJhJDH
|
||||||
|
5AJQdPprNvcchunIhOiRjwYr6qyLTL+x/dfVH4gRAUL0sPYE1OzvPwxbfROih1UAtO//BkYDCNHDKgDb
|
||||||
|
jl7y3tHXBdQJoPEnIUQeqwC8fuZskAeiABCiR+euABQAQvTonADMfLgmrxIkhMhjFQCN+X5FhGxOSkhq
|
||||||
|
WAVAOw3YoNWenBBSMRtw6uT5wr79UrAzMSG6lArA6L6ZbOTNW2oPQ/OfEF1KBQD1AFuPTatYAegJ8OnO
|
||||||
|
Cc7+I0SRyvHgWs5AtgYjRJ9KAQDSWYFM/yUkDE4CIHkVgOMPiT80/QnRx0kAAHoDIjnIpwhw8xMSFmcB
|
||||||
|
ABjtPfHeVS8ZgjD70f2Hm5+QcNQSAEOTsWCGh3eW5FOB2PSDkPA0EgADhAAvF4sAJz42PT39hHSHVgJg
|
||||||
|
wNUAPoKVY98t+nd3Lz+Td/qlqU9I9/AiAISQfkIBICRhFglAmTmPKj0MD2W1HiFxMCcAKP+FQ2/VlnuV
|
||||||
|
/xM8+SjagUOPd3tC+svgjX0bZ8f3X2sU0kMBz1fHn8vFgEJASP+YNx68KbAILhwY5Vw/QnqGFwEAsAaQ
|
||||||
|
2ccEH0L6gzcBABAB5PbTEggL/DnL1z3IVow/StBCohasNDhv8cLvA6GmM5d4FQDAxh5hQMXmC7u+yR25
|
||||||
|
rgVbaMEORy6zM9PFuwAA1vfrgroMbP6mlZqoypw+tIGWW4KICAD47J2Nec4AkQM5GyjR9tWshT0Z00NM
|
||||||
|
ADjhRxaJ/gzg61PP5s5ckgZiAgDY418GnPxo09Ykd8MFjmhPB1EBoEkpg8bYNl7h0kBUAOgM9A+8/GP7
|
||||||
|
r4u/D8KGn+x6OfTHJcKICgAXkX9ePX5BzPRfCFu1x4+oAICPtk6G/ozRoHX6Gyjg8UMB6BFoyOpSremT
|
||||||
|
iwdeYnp3xFAAegI8/1Mfn1d/35kP12RXDo+E/vhECApAT0Be/yvvf67+vr4mNpu6BPaH7BaiAsBkIH9o
|
||||||
|
zWgsoq6Iw1rJu0X/sunxKkpWgrCgYSycjExBDoeoANB89EcfBAAFSev33Myen/q21t8PMTAdpoguogJw
|
||||||
|
+u1NVHdPdF0AfDwfLEakITN7VA8xAWAIyS9dFQCf4+IAG8voIiYAzCf3y8jOW9no3pkg720TAN/ViMMw
|
||||||
|
CUkHEQHA6Q/PMb29/ggVBShz5ErWJLC7lA4iAsDkERleP3NW/T1tjlyNKwkPEnm8CwA9/3KEyAQscuTC
|
||||||
|
27/12LT3XgRF8Copi1cBYDMJWdDsc+LgVbX3szlyx969XjvU1xT2mJTFmwDw5NchdDUgHH/bT1xUOf0N
|
||||||
|
7Cshx+BvZ1fMtjErcUp8ceRF3vmV0HIG2lKAtSsSy56FtCefDYhFhTBTHSHgfMBwaJjgtiSuEH4IcOq1
|
||||||
|
zVxnAsybDgznDu6ZEAQMllhoaiIkdP/GsrxVFE/8cEjG30FZDF7zCjJMmxZlWNdPrf5x3sRrrGMzJCVl
|
||||||
|
Fo0HJ/1ASgSqEnBChCJB3WiAGZSyesvdUsGCkxGHGT5zij0QKQA9BiKA64APk9w1BbfrAoCNP7pvptF3
|
||||||
|
kqI/iwIQAXDMITGnqWmO5q2I4LgU4XRZAHylS+P7gBim4HMYvHV4ZJaDIvsPrAH4b7AJXK8FyNuAI7fO
|
||||||
|
PbirAuDbMYrIAzpax74v5vIA4ODDF5ziPSg2YAbDkYvpQXDmGnCiYbPDAdbUzA0lAGXp5VJRkRRSkRcl
|
||||||
|
AuFUgDkY84cmzdEYSlKEbcqUdE1C7DkIhZmAUL4LB0aTD5GQxYQoS7alJGslRcVcj2BNBWY5JikC14vt
|
||||||
|
xy+qvqctzVzTGol1zmVpLUAKdyBSH+1rQNHm0+6PEGuhW2UxEOf7kYVobj7bxtNOSY61KtGpGpCTYslC
|
||||||
|
NDYgNt2Z3eOLTv9QQ1JibHTjJADs708WolEWbEtLDtUeLcZrgHM/AFoBZCHIM4A/QEIEyjZbqA7JMR6E
|
||||||
|
zgIQo/qR9kiIQNVa0+xItJDYRt05CwD7/BMbCA3CJ9C2MhF3foT7qtqBh0pGAskKAGjTlAEnBRbKcGoq
|
||||||
|
ZsM9vL0kyvhqiiBJCKPBmlgDOPWvH13rtBYoAP6oJQB1/QBw1qBSDUUqZYsC1gXEoG5hCukm5jevihLg
|
||||||
|
d799bmX21fHnah0CKPcdefOW+ueK0QoWEQBsfDhqmqg0HC2oyaYQxAHWAiw/vAxtLT86Af3hVQAQGoIJ
|
||||||
|
6EOd2WWY2AgVBoyxJsCbAEi0qILiIgsxtuwr0p6pk+dVW5ODGKdd1xIAW0GEZJPK2Msx+wKcuGiqieaa
|
||||||
|
w45c9BaAOQ+zXnNzaIcCY7z/A2cBQIjm1I7Nhf9O2ivLHIQwQNjh2YdTz6XdGDYJQnhw5kpbbdpViTGa
|
||||||
|
/8BZAGxFQVr14THmYXcZONrQVbeJmY3DAp596Q2jZQXEWggEnAUg9JioWE2wrgFTf3z/NS/XOVzfpg9t
|
||||||
|
ELsaaA0pjfnwcRIAm/mvHY6p6llP2iGR1ivdWEZ6YGrs108nAbDdf7SnxNAhKIdkYY+0CEjNK0xhvVUK
|
||||||
|
QOh+bAuJtTVTSKRHjQHpzeRbBFJpjlspALbYZ6hsLF4D/KOVWivtScehBP9FG6sU1gpqElIZR14qAGWb
|
||||||
|
LVRBRtMMQdMr3/zT4KNXfp/RDqdpWHA4nFxDl8PUKUiKBasAVJ20oQSgbj42FgJers+KRZDSoEjtwhrN
|
||||||
|
eHpekPTLK09gKhADnPZm0jVesZv7RSwSANeZACFSMYGrALQ1B/E+8P7Gfhpo/45lCWXSDFt+WN8pbviF
|
||||||
|
zAmASd5wzeIKNSfeRQB8nWquDSr6SihHLtvLdYfBP75cOosFjlcdReziFQDebHSm8f1csVYmhnLkxppW
|
||||||
|
20cajwfX7stuKFs8ks905chIdJ7hUCLeZNaEmX4MqwXFSAtDljgY4Mg1d3riRmMBCDEjDtjSMjVOs9hM
|
||||||
|
1y5acQtBlAI9Jqq6Sg1T9zqbMo0FAJlj2z64pP7ARX0JtZ4ltlFpXReAtqKeWky/CY0FAGw7ekk0e2wh
|
||||||
|
NtNRcyHHdH/tqgD4zkzEukFEJxbh9kkrAZDKwbZRZIJrJ7KEDGP5posCIJWWjFRkvCdFYD6tBABohQNt
|
||||||
|
iyZEh9hYykNDdde1WVHSNQkxNvVsS2sB0Iol22oSQuQjxFIiKl1Ka8MmoBqRpZiucD5oLQBA+iSxpSVr
|
||||||
|
m/+GWJqThJiya7tCaSYlsaL0MV4EAEi1Zyo7bUNlsoEmE2IQrVi95W7+3PjzcFgLd1QsShPH1lqg2s01
|
||||||
|
bb+npj8iFgvOB94EAPheTFXmWqhMNlAnJwDOUjxrnasKPNcIX0nnHWiLaNHpG0LIaQU8wqsAANwrIQRt
|
||||||
|
CkxgYqOXXNXi77oA+KhP1whhaWV12k7eENN+Y8zsbIJ3AQCmnXTdrrJ1M7i6LAA+n026pZZGc9eyzroh
|
||||||
|
HLmMCDxCRAAMJn/b5HAXLTAzGNTUZNchlBcblE1KljjRpEVA2gy3CWYoRy6IbdJvE0QFoIjhmuy299tQ
|
||||||
|
6chlyUCSVklfm2uWNZcJ6ciNcdRXXdQFwDchGpPYUpI1FrN0RpsPH44BgoXvqUzotbNJh4mtuKsJ/wfb
|
||||||
|
mhgAeoKg9wAAAABJRU5ErkJggigAAAAwAAAAYAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8
|
||||||
|
PDwAOkE+ADpEPwA5RUAAN01DADdORAA4SUEAOExDADVRRAA0VUYANFhHADNaSAA0WUgAMl1JAC9nTQAu
|
||||||
|
ak4ALWxPADFgSwAwY0wAMGRMAC1uUAAscVEAKnRSACp3VAApeVQAKH1WACeAVwAmg1gAJYVZACSIWgAk
|
||||||
|
i1wAIo1cACGSXgAhlF8AH5lhAB6cYgAdn2QAIJZgACCYYQAcomQAG6ZmABykZQAbqGcAGqpoABmtaQAX
|
||||||
|
smsAFrVsABixagAVuW4AFLxvABO/cAAUvnAADs52ABLAcQARx3MAEcd0ABDKdAAO0HcADdJ4AAzWeQAL
|
||||||
|
2XoADNh6AAndfAAH5X8ACOJ+AAjkfwAH5oAABumBAATuggAD8oUABPCEAAL1hQAB+IcAAfqIAAD+iQBx
|
||||||
|
/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAIkAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb
|
||||||
|
/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAwcAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK
|
||||||
|
/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABAUAAAWnAAAHSQAACOsAAAqc8AAMLwAADR
|
||||||
|
/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAvJgAAUEEAAHBbAACQdAAAsI4AAM+pAADw
|
||||||
|
wwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAAAAAALxQAAFAiAABwMAAAkD4AALBNAADP
|
||||||
|
WwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD///8AAAAAAC8DAABQBAAAcAYAAJAJAACw
|
||||||
|
CgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/1NEA////AAAAAAAvAA4AUAAXAHAAIQCQ
|
||||||
|
ACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/scgA/9HfAP///wAAAAAALwAgAFAANgBw
|
||||||
|
AEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/kdwA/7HlAP/R8AD///8AAAAAACwALwBL
|
||||||
|
AFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2cf8A95H/APmx/wD70f8A////AAAAAAAb
|
||||||
|
AC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0Uf8AwnH/AM+R/wDcsf8A69H/AP///wAA
|
||||||
|
AAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBYMf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD/
|
||||||
|
//8AAAAAAiYwJgIHSkpKSkkzBz1KSkEMAAAAJkpKSkAHPUpKSko7AAAAAAAAAAAAAAAAAAAAOUpKSj0C
|
||||||
|
SUpKSkoqAAIUFAIAAAACSUpKSkohHkpKSkodAAAAAAAAAAAAAAAAAgAUSkpKSkoXKUpKSkkMAAAAAAAA
|
||||||
|
AAAMSkpKSkorAB05ORsAAAAAAAAAAAAAAAAARBQZSkpKSkobAB4zLAwAAAAAAAAAAAAAQ0pKSkoZAAAA
|
||||||
|
BSQxHgIAAAAAAAAAAAAASkIFRUpKSkkFAAAAAAAAAAAAAAAAAAAAD0FKSSoAAAADQEpKSjMAAAAAAAAA
|
||||||
|
AAAASkoFFUJKQxcAAAAAAAAAAAAAAAAAAAAAAAIRBRMPAQAeSkpKSkoMAAAAAAAAAAAASkYCAAAHAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAHOUpKQg0mSkpKSkoOAAAAAAAAAAAASR4AAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAApSkpKSjgRSkpKSkMCAAAAAAAAAAAAEQAAAAAAAAAAAAAAAAAAAAAAAAACKkE9GQA4SkpKSkUB
|
||||||
|
HERKPhMAAAAAAAAAAAAAOUlBFwAAAAAAAAAAAAAAAAAAAAAvSkpKSRcvSkpKSj0AAAEHAAAAAAAAAAAA
|
||||||
|
AAAASkpKSREAAAAAAAAAAAAAAAAAAAJFSkpKSjAKQ0pKRxUAAAAAAAAAAAAAAAAAAAAASkpKSiYAAAAA
|
||||||
|
AAAAAAAAAAAAAAdGSkpKSjAABx4gCQAAAAAAAAAAAAAAAAAAAAAASkpKSh4AAAAAAAAAAAAAAAAAAAAs
|
||||||
|
SUpKShUAAAAAAAAAAAAAAAAAAAAAAAAAAAAASkpKQwUAAAAAAAAAAAAAAAAAAAACJEE5FwAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAIzcsDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAXMzMXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABlKSkpKGwAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlKSkpKPQAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj1KSkpKQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAHyNKSkpKKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAALwIqRUUsAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAEXIQ8A
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAATdKSkokAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAF0pKSkpKDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAASjcFJkpKSkpKFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIaIREAAAAAAAAA
|
||||||
|
AAAASko1D0pKSkpJBwAAAAAAAgAAAAAAAAAAAAAAAAAAAAAABj1KSkkeAAAAAAAAAAAASkpKAClKSkke
|
||||||
|
AgAAAAAAAAAAAAACAAAAAAAAAAACAgAAIUpKSkpFAgAAAAAAAAAASkpDAAAMFQURBQAAAAACAAAAAgAA
|
||||||
|
AAAAAAAAAjBKSTACL0pKSkpKCQAAAAAAAAAASkohAAAAEUFKSS8CAAAAAAAAAAAAAAAAAAAAKkpKSkoo
|
||||||
|
HEpKSkpDAAAAAAAAAAAALhcAAAAAPUpKSkoeAAAAAAIAAAAAAh4zLAwAQUpKSko+ATFKSkYVAAAAAAAA
|
||||||
|
AAAACS09LgkHSkpKSkozAAAAAAAAAAAAL0pKSkYJOkpKSko5AAANFAMAAAAAAAAAAAAAPkpKSkEHRkpK
|
||||||
|
SkopAAIAAAwXBQIHSUpKSkojGEpKSkkXAAAAAAAAAAAAAAAAAAAASkpKSkoZHkpKSkMFAAAAKUpKSR4M
|
||||||
|
SkpKSkoqABAtLw8AAAAAAAAAAAAAAAAAAAAASkpKSkoaABQpIQcAAAATSkpKSkkMPUpKSkoUAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAQ0pKSkYHAAAAGz5DKwceSkpKSkoXDDlKQx4AAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAEThGORMAAAAXSkpKSjAUSkpKSkoMAAICAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAx
|
||||||
|
SkpKSkkCMEpKSSoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwSkpKSkUCABUhDgAC
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSkpKSisCAAAAAAAAAQAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFTg9JgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAgAAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAEAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
|
||||||
|
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
|
||||||
|
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
|
||||||
|
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
|
||||||
|
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIA
|
||||||
|
AAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAA
|
||||||
|
AKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCAAAAAAAApEIAAAAAAACkQgAAAAAAAKRCKAAAACAAAABA
|
||||||
|
AAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADw9PQA6QT4AOkQ/ADlGQAA3TUMAN05EADhJQQA4
|
||||||
|
TEMANVFFADRVRgAzWkgANFhIADJdSQAvZk0ALmlOADFhSgAwY0wAMGRMAC1tUAArc1IALHJRACp1UgAq
|
||||||
|
d1QAKXlUACh9VgAngFcAJoJYACWGWgAliVsAJItcACOOXAAkjFwAIZJeACGVXwAfmWEAHpxiAB2fZAAg
|
||||||
|
lmAAIJhhAByhZAAbp2cAHKVmABuoZwAaqWgAF7JrABezbAAXtWwAGLBqABa4bQAUvXAADs52ABLBcQAR
|
||||||
|
xXMAEch0AA7QdwAN0ngADNV5AAvaegAK3HwACeB9AAjlfwAH5oAABumBAAPyhQAE8YQAA/SFAAH4hwAB
|
||||||
|
+ogAAP6JAACwNgAAz0AAAPBKABH/WwAx/3EAUf+HAHH/nQCR/7IAsf/JANH/3wD///8AAAAAAAIvAAAE
|
||||||
|
UAAABnAAAAiQAAAKsAAAC88AAA7wAAAg/xIAPf8xAFv/UQB5/3EAmP+RALX/sQDU/9EA////AAAAAAAU
|
||||||
|
LwAAIlAAADBwAAA9kAAATLAAAFnPAABn8AAAeP8RAIr/MQCc/1EArv9xAMD/kQDS/7EA5P/RAP///wAA
|
||||||
|
AAAAJi8AAEBQAABacAAAdJAAAI6wAACpzwAAwvAAANH/EQDY/zEA3v9RAOP/cQDp/5EA7/+xAPb/0QD/
|
||||||
|
//8AAAAAAC8mAABQQQAAcFsAAJB0AACwjgAAz6kAAPDDAAD/0hEA/9gxAP/dUQD/5HEA/+qRAP/wsQD/
|
||||||
|
9tEA////AAAAAAAvFAAAUCIAAHAwAACQPgAAsE0AAM9bAADwaQAA/3kRAP+KMQD/nVEA/69xAP/BkQD/
|
||||||
|
0rEA/+XRAP///wAAAAAALwMAAFAEAABwBgAAkAkAALAKAADPDAAA8A4AAP8gEgD/PjEA/1xRAP96cQD/
|
||||||
|
l5EA/7axAP/U0QD///8AAAAAAC8ADgBQABcAcAAhAJAAKwCwADYAzwBAAPAASQD/EVoA/zFwAP9RhgD/
|
||||||
|
cZwA/5GyAP+xyAD/0d8A////AAAAAAAvACAAUAA2AHAATACQAGIAsAB4AM8AjgDwAKQA/xGzAP8xvgD/
|
||||||
|
UccA/3HRAP+R3AD/seUA/9HwAP///wAAAAAALAAvAEsAUABpAHAAhwCQAKUAsADEAM8A4QDwAPAR/wDy
|
||||||
|
Mf8A9FH/APZx/wD3kf8A+bH/APvR/wD///8AAAAAABsALwAtAFAAPwBwAFIAkABjALAAdgDPAIgA8ACZ
|
||||||
|
Ef8ApjH/ALRR/wDCcf8Az5H/ANyx/wDr0f8A////AAAAAAAIAC8ADgBQABUAcAAbAJAAIQCwACYAzwAs
|
||||||
|
APAAPhH/AFgx/wBxUf8AjHH/AKaR/wC/sf8A2tH/AP///wAAABg2KgdEQ0M2DzY4EgAANkRDHDpEQzkA
|
||||||
|
AAAAAAAAAAEIREREITZDQyYAAAAAAAdDREQ1ETg4EQAAAAAAAAAAOxJEREQpBx8WAAAAAAAAADpERCEA
|
||||||
|
AB81KQAAAAAAAABEGy1EOwUAAAAAAAAAAAAABx8YDAARQ0REGQAAAAAAAEQNAAIAAAAAAAAAAAAAAAAA
|
||||||
|
Cz5DORZDQ0MfAAAAAAAAGAAAAAAAAAAAAAAAAAAfKgsmQ0NDFjFDOAcAAAAAAAA+QBsAAAAAAAAAAAAA
|
||||||
|
JkRDQBlDQ0MLAAIAAAAAAAAAAEREPwAAAAAAAAAAAAAwQ0NDBRwuFAAAAAAAAAAAAAAAREQ+AAAAAAAA
|
||||||
|
AAAAABRDQzEAAAAAAAAAAAAAAAAAAAA0Ng4AAAAAAAAAAAAAAAcPAAAAAAAAAAAAAAAAAAAAAAAcOC4C
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACURERCYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAS
|
||||||
|
REREKQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsrQzkFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAADQAAIS0RAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABACFEREEDAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAEMcLURERAsAAAAAAAAAAAAAAAAAAAACJi4LAAAAAAAAREENQUQ0AAAAAAAAAAAAAAAAAAIA
|
||||||
|
ACpERDwAAAAAAABEPAAHER8YAAAAAAAAAAAAAAAYQUEXNURERAIAAAAAADURAAA2REQjAAAAAAAABx8W
|
||||||
|
ADxERDsUQ0QvAAAAAAAAHjsxB0RERDYAAAAAAAA6REQhOERENgAHCwAAAAAAAABEREQjNUREHgAAJjsw
|
||||||
|
CERERDULMzELAAAAAAAAAAAAAERERCQCFhYUAw9EREQhNkRDGwAAAAAAAAAAAAAAAAAAJEA1BwAIQEQ+
|
||||||
|
FERERCYCFxEAAAAAAAAAAAAAAAAAAAAAAAAAACFEREQZKUA1AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
DUREQwsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFCcNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAGAAAADAAAAAB
|
||||||
|
AAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPDw8ADpBPgA6RD8AOkRAADdPRAA4SkEAOExDADZRRAA1
|
||||||
|
VUYAM1pIADJeSQAxYEsAMGRMAC1tUAArc1IALHFRACp1UgAqd1QAKXlUACh9VgAngFcAJoJYACWFWQAk
|
||||||
|
iVsAJItcACONXAAkjFwAIpFeACGUXwAfmmIAHp5jACCWYAAgmGEAHaFkABumZgAcpGUAGqpoABitaQAV
|
||||||
|
uW4AFL5wAA/NdgASwXEAEcVzABDJdAAO0HcADdN4AAzVeQAL2HoACdx8AAjhfQAI5H8AB+eAAAbqgQAE
|
||||||
|
7oMABPCEAAH4hwAB+ogAAP6JAFH/yABx/9MAkf/cALH/5QDR//AA////AAAAAAAALw4AAFAYAABwIgAA
|
||||||
|
kCwAALA2AADPQAAA8EoAEf9bADH/cQBR/4cAcf+dAJH/sgCx/8kA0f/fAP///wAAAAAAAi8AAARQAAAG
|
||||||
|
cAAACJAAAAqwAAALzwAADvAAACD/EgA9/zEAW/9RAHn/cQCY/5EAtf+xANT/0QD///8AAAAAABQvAAAi
|
||||||
|
UAAAMHAAAD2QAABMsAAAWc8AAGfwAAB4/xEAiv8xAJz/UQCu/3EAwP+RANL/sQDk/9EA////AAAAAAAm
|
||||||
|
LwAAQFAAAFpwAAB0kAAAjrAAAKnPAADC8AAA0f8RANj/MQDe/1EA4/9xAOn/kQDv/7EA9v/RAP///wAA
|
||||||
|
AAAALyYAAFBBAABwWwAAkHQAALCOAADPqQAA8MMAAP/SEQD/2DEA/91RAP/kcQD/6pEA//CxAP/20QD/
|
||||||
|
//8AAAAAAC8UAABQIgAAcDAAAJA+AACwTQAAz1sAAPBpAAD/eREA/4oxAP+dUQD/r3EA/8GRAP/SsQD/
|
||||||
|
5dEA////AAAAAAAvAwAAUAQAAHAGAACQCQAAsAoAAM8MAADwDgAA/yASAP8+MQD/XFEA/3pxAP+XkQD/
|
||||||
|
trEA/9TRAP///wAAAAAALwAOAFAAFwBwACEAkAArALAANgDPAEAA8ABJAP8RWgD/MXAA/1GGAP9xnAD/
|
||||||
|
kbIA/7HIAP/R3wD///8AAAAAAC8AIABQADYAcABMAJAAYgCwAHgAzwCOAPAApAD/EbMA/zG+AP9RxwD/
|
||||||
|
cdEA/5HcAP+x5QD/0fAA////AAAAAAAsAC8ASwBQAGkAcACHAJAApQCwAMQAzwDhAPAA8BH/APIx/wD0
|
||||||
|
Uf8A9nH/APeR/wD5sf8A+9H/AP///wAAAAAAGwAvAC0AUAA/AHAAUgCQAGMAsAB2AM8AiADwAJkR/wCm
|
||||||
|
Mf8AtFH/AMJx/wDPkf8A3LH/AOvR/wD///8AAAAAAAgALwAOAFAAFQBwABsAkAAhALAAJgDPACwA8AA+
|
||||||
|
Ef8AWDH/AHFR/wCMcf8AppH/AL+x/wDa0f8A////AAAMLSQhOTkTISMDADI5JC45LQAAAAAAABEmOTkR
|
||||||
|
LCcDAAAAAzg5KAYYGAQAAAAAADgUOC0DAAAAAwAAABEkDQMkOTQDAwAAADAAAwAAAwAAAAAAAAAkOScn
|
||||||
|
OTgGAAAAAB0RAAAAAAAAAAAkNhoyOTYEHg8AAAAAADk5CQAAAAAAAwM4OS8PJxQAAAAAAAMAADk4CAAD
|
||||||
|
AAAAAAAjMxgDAAADAAAAAAAAABEZDQAAAAAAAAAAAAAAAAAAAAAAAwAAAA85OREAAAADAAAAAAMAAAAA
|
||||||
|
AAAAAAAAABs5ORQAAAEAAAAAAwAAAAAAAAMAAAAAAA8WIAsAAAAAAAAAAAAAAAMAAAAAAwAAAAEGNjka
|
||||||
|
AAAAAAAAAAADAAAAAAAAAAAAADYWOTklAAAAAAAAAAAAAAADIycEAAAAADkgGiUKAAAAAAAAAAABGhoO
|
||||||
|
OTkhAAAAACgHACo5HgAAAAAADwsUOTkbNjgRAwAAACYxDjg5LwAABwMaOTgbOTkPAwYAAAAAADk5Jxoo
|
||||||
|
DwAbOTEhOTkMDAwAAAAAAAAAACo1EQAZNiQnOTkJHBMBAAMAAAMAAAMAAAAAAAAwOTgLJxwAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAWNCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQABAAEAAQAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAQAAAAIAAAAAEACAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8PT0AOkE+ADlGQAA3TUMAOElBADhMQwA1U0UANVVGADNbSQAy
|
||||||
|
XUkALmtPAC5sTwAxYUsAMGJMAC1vUAArc1IAK3RTACh8VgAngFcAJ4FYACaEWQAkiVsAH5piACGVYAAg
|
||||||
|
mGEAHKJlABunZwAaqWgAGa1pABa1bAAYsGoAFbtvABS8bwAPzXYAEsJyABHEcgAQynUADtF4AAzVeQAL
|
||||||
|
2nsACt18AAjifgAI5X8ABuuCAATvgwAD84UABPCEAAL2hgAB+YgAAP6JAABQNwAAcEwAAJBjAACweQAA
|
||||||
|
z48AAPCmABH/tAAx/74AUf/IAHH/0wCR/9wAsf/lANH/8AD///8AAAAAAAAvDgAAUBgAAHAiAACQLAAA
|
||||||
|
sDYAAM9AAADwSgAR/1sAMf9xAFH/hwBx/50Akf+yALH/yQDR/98A////AAAAAAACLwAABFAAAAZwAAAI
|
||||||
|
kAAACrAAAAvPAAAO8AAAIP8SAD3/MQBb/1EAef9xAJj/kQC1/7EA1P/RAP///wAAAAAAFC8AACJQAAAw
|
||||||
|
cAAAPZAAAEywAABZzwAAZ/AAAHj/EQCK/zEAnP9RAK7/cQDA/5EA0v+xAOT/0QD///8AAAAAACYvAABA
|
||||||
|
UAAAWnAAAHSQAACOsAAAqc8AAMLwAADR/xEA2P8xAN7/UQDj/3EA6f+RAO//sQD2/9EA////AAAAAAAv
|
||||||
|
JgAAUEEAAHBbAACQdAAAsI4AAM+pAADwwwAA/9IRAP/YMQD/3VEA/+RxAP/qkQD/8LEA//bRAP///wAA
|
||||||
|
AAAALxQAAFAiAABwMAAAkD4AALBNAADPWwAA8GkAAP95EQD/ijEA/51RAP+vcQD/wZEA/9KxAP/l0QD/
|
||||||
|
//8AAAAAAC8DAABQBAAAcAYAAJAJAACwCgAAzwwAAPAOAAD/IBIA/z4xAP9cUQD/enEA/5eRAP+2sQD/
|
||||||
|
1NEA////AAAAAAAvAA4AUAAXAHAAIQCQACsAsAA2AM8AQADwAEkA/xFaAP8xcAD/UYYA/3GcAP+RsgD/
|
||||||
|
scgA/9HfAP///wAAAAAALwAgAFAANgBwAEwAkABiALAAeADPAI4A8ACkAP8RswD/Mb4A/1HHAP9x0QD/
|
||||||
|
kdwA/7HlAP/R8AD///8AAAAAACwALwBLAFAAaQBwAIcAkAClALAAxADPAOEA8ADwEf8A8jH/APRR/wD2
|
||||||
|
cf8A95H/APmx/wD70f8A////AAAAAAAbAC8ALQBQAD8AcABSAJAAYwCwAHYAzwCIAPAAmRH/AKYx/wC0
|
||||||
|
Uf8AwnH/AM+R/wDcsf8A69H/AP///wAAAAAACAAvAA4AUAAVAHAAGwCQACEAsAAmAM8ALADwAD4R/wBY
|
||||||
|
Mf8AcVH/AIxx/wCmkf8Av7H/ANrR/wD///8AAiUZLScLDgAtJSQiAAAAAB0rHQcFAAAAHBgFJhgAAAAV
|
||||||
|
AAAAAAAACwwwHiscAAAALxEAAAAAEDEcJRMAAAAAACoQAAAAAAUbCAAAAAAAAAAUKQcAAAAAAAAAAAAA
|
||||||
|
AAAAGi0IAAAAAAAAAAAAAAAAAAQWIgAAAAAAAAAAAAAAAAAoIi4CAAAAAAAAABkfAAAAIwAeFwAAAAcF
|
||||||
|
JiUhKwEAACcaLiYAEQwvJh8fAAEAAAApHgYdEjEkGRUAAAAAAAAAAAAJMR0UDAAAAAAAAAAAAAAAAA0C
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="Checkerboard.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAwBQTFRFgICA////
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODgHVgAAAAlwSFlzAAAOvgAA
|
||||||
|
Dr4B6kKxwAAAABZJREFUGFdjYAABRhAAs4hlkq4DZDgACywAM12jTsYAAAAASUVORK5CYII=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="Email.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAnBJREFUOE+dk11I
|
||||||
|
k1Ecxs+2q1DLqwRvvCgoM6mLvoTAC6WLSrDUYBcSGK6y6EMzc6a2NnERlVKhSEMTYWSyksTZh7KZGboU
|
||||||
|
HNmUKemcupnuI5tuqHs6/7cSUenrwMPhPf/n97wPB46IrVrHCwuTxCJR5EbxbHiUZHQnEzE2uhj18Wsw
|
||||||
|
zPPLGgQmdErli9Ws8C2VX8wFX9y0rmiWnJ9/dg38Qc02dZdKUlQ3DrcuBINIfQTItMDJWiBHByj1gMEK
|
||||||
|
0OxY9rkrywEvb7OQdzclR6tKDjRUV522qh7Kl5q6unDqQTnuNbZD89qEyhYTNK9M0PcMwLewgOsFh5oH
|
||||||
|
70oSbXfYBmZUiM8P1Se06Z4WBP5UvarFALffj+q6goDjTXJTf7k4nWVmp159ayhDnVYu1Ot7tvmnImB+
|
||||||
|
ztX4Y6dZUYMRzrk5VD4uxPueWmTlpVxmCVlZF1wuG8pqVJj0eKA+s5cHRMNm2Iapvn3wjCRirGOHUF2j
|
||||||
|
12PY7Ubx/SJ4vJMglsXLZJcWefrI+Ge09PZCGr8V105sQU3xdgx0HYHfJ4O5ebdQXVNXjLb2Csy4x0EM
|
||||||
|
sexgRka2f2kJvkAAEzz9VmkCatWR0JaEoqkiDJ26cDxRh2LQ6YSyQgGna0zwEkMs25+envON13P7fII+
|
||||||
|
2e3QGo1rVN/RAZPFvOwjhli2RyrNdfNEh9eL0elpdFutsPMmLl55peiMZuQhLzHEsl1paXlf5udhdTjQ
|
||||||
|
abEIu21mZl2t9BBDLItOSpKP8HSj2Yx+Xn9oauq3Ig95iSGWRcTFKVr57Q/zv9pnZ/9K5CWGWBYaG5sZ
|
||||||
|
EhNT+j8idt0X+S+H3wE2DYYIXysH6QAAAABJRU5ErkJggg==
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="Printer.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAm1JREFUOE+Nkl9I
|
||||||
|
U1Ecx39T31o9SBq97cWHiUIimKiQ0zFbbcJ1U2YkBtLuFYkQnMrcdKQyEUIwWk+GDy58EfUhmYoTRtKE
|
||||||
|
HitI8kGZIkEW/oF0um/nd3OyYUnn8rn3nMPn+733wNXYe3spOTQajVXMb55vpE/CiUTiqyB91+b1Ugry
|
||||||
|
j3gcWwcH2Nzfx8benspsJALhyII8qaeHUiHJ7U5F+Xl0hM3dXXzZ2cGn7W183NpCcG4OPISrmNvbdQZF
|
||||||
|
IaZOlolsNhvVOZ1U29XFtO4fH+ObeGtqyYuJCSTJM5s9Aqqqr1ez6s1ut5OtqYksHR1tB6Lg++HhhRL+
|
||||||
|
Ej4OO+yqmbOCDLGwCuSsrKznLpcLl8EOu5wRBRkkSdJ1t9vdtyPOrCgK+vv74fV6L+DxeODz+VQnFouh
|
||||||
|
u7u7j7NksVj0o6Oj42tra3A4HOjs7ITT6URzczMkqQ7V1UaUl1egpOQ2zOZ7qjM/v4yBgcFxzlJNTU3l
|
||||||
|
1NTU8urqKoxGowjLMJnMqKioFME7aRiNd1VndnYRIyOBZc6SwWBwRKPR9XA4jKKiIjQ0PBSS9a+YTLWq
|
||||||
|
4xTX5OTbdc5SWVnZk1AohGAwCJ1OB7v9EazWB/+EnbGxMUxPT4OzVFxc7IpE3mFmJoS2tqcYHg5gaOgl
|
||||||
|
/P5ACq/E/A+tre1YXPygwlnS6/XupaUVLCysoLGx8b9IFnCWcnJyWrKzsweZzMzMIf5l7weA1++BN9HP
|
||||||
|
MPhacEv2o8o1iV8nJ2An6XOWxIK0Wi1dy82lG6Wlz9SfPmWcJhJg4qeniIsnO+xyhrPnBVcLC0lbUPD4
|
||||||
|
Sn6+/zLYUd2zgt/AGvcWHCMAZwAAAABJRU5ErkJggg==
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="Clipboard.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAW1JREFUOE+NkL1L
|
||||||
|
QlEYh9/b4NzS1BgNShBRQQ3VGEGr/0BDBEG0uLRIFIREIX2ANhgZKphj/4PLASOi0i4SYWWmWH5y/bhv
|
||||||
|
5yc4HTl04YHD+z4893AMGvB53S7Hg+1cNQxjBGtm/p4YerrdvXlsDfJ7s7MlCp4ukgD7U3QX8mx+ZDIm
|
||||||
|
A5wx6+/hKiEs0+drnNiY5WTynlOpZ85mcz1wxgw7OHCVwPECCXlVDoev2ec75EDggiORGMfjCQ5dXrHf
|
||||||
|
f8LRaAwKw1UCR/MkbLns2Da/mOZAsIMDVwn45ki0pWB1OlrgwFUCBzMkrG6X662WFjhwlcDeNIlGu82/
|
||||||
|
zaYWOHCVgHeSRFX+vVSraYEDVwnsuEj8WBbnKxUtcOAqAY+TREleP1cua4EDVwlsj5MoNBr8WixqgQNX
|
||||||
|
CWyNkfis19ksFLTAgasE1kdJvMsHTOfzWuDAVQLuYRJf8oHeqlUtcOAqgRUHBZcdJP4D3H7gDzdsNup2
|
||||||
|
mXizAAAAAElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="Save.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAXJJREFUOE+lk0FL
|
||||||
|
AkEYhlvwv3jzoiDoQdCbdEnYf6CrqCgoHgRRAk/9EQVLdEGyFiQNMS+dvHnoEkgglGAmCL7NO6RMIZvU
|
||||||
|
wsMO3zzzzGk0ACf/+hjQNO1ccKlXKsYx0OUZeflXoFmtVsUS2P4CHboi0FQDrXK5jM12i/VmYwsduiLQ
|
||||||
|
UgNmqVTCuzj8tlrZQoeuCJhqoFMsFvG6XmO2WNhCh64IdNRAt1Ao4EXc/jSf20KHrgh01YCVy+Uwnkzw
|
||||||
|
vFzaQoeuCFhqoJfJZBCLxY6Crgj01EA/lUrB4/HA7XYfhHs78vk8A301MIzH4/B6vRiNHjAY3H+DM+7p
|
||||||
|
ug6fz4dsNsvAUA2Mo9Eo/H4/LOsOTqdTYprXEs64x0AwGEQ6nWZgrAYeDcNAIBBAu30r/6Reb0t2MwbC
|
||||||
|
4TCSySQDj/uAeEyngqnL5fpoNG4QCoUktVpHspsxEIlEkEgk+AKnaoAP8kwwczgcF4fg3g+u9gEu/son
|
||||||
|
bfJW/NwRDyIAAAAASUVORK5CYII=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
<data name="Close.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
|
||||||
|
YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAUNJREFUOE+lk79L
|
||||||
|
QlEcxW9/gqCrm6vg4uYoOAgOrqLk4ioP0r2Glhp0SSjoF1FE0BIUDU3RdIOGoKBVGlpapaHTObeuCPe6
|
||||||
|
9ITD5fs9n3Pue8JbAWBS/VSQRvPwKR/j3JgaZXVqPv5TzPOXLhYoZDEcQidVWyhw3qzfn3tBAWH7PRjg
|
||||||
|
uV7HV5JAM6USyX50u86btlrOCwoOCR7Q+Oz1cFcu473dhmbppdFwu8dq1e3EBgU0zB6NXQJvzSaui0U8
|
||||||
|
VCq4LZWwn8vhLJ+HPDFiowUEzITADsGrQgFHmYzTSTYL7eSJiRZs0timRoTGhC956wXDXtrJEyM2eAIt
|
||||||
|
t34Be8NgTPLELCuQYe8Z9tK8ZBf+ieuEnxj20rzB26SYF7zCGsGEoVeW6NTMoJFiXlDAkFllqMOwTs2+
|
||||||
|
IOYFBf/9oFJ9ibr0B4f94vVG3bWDAAAAAElFTkSuQmCC
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
1525
GreenshotImageEditor/Core/ImageHelper.cs
Normal file
1525
GreenshotImageEditor/Core/ImageHelper.cs
Normal file
File diff suppressed because it is too large
Load diff
630
GreenshotImageEditor/Core/ImageOutput.cs
Normal file
630
GreenshotImageEditor/Core/ImageOutput.cs
Normal file
|
@ -0,0 +1,630 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using Greenshot.Plugin;
|
||||||
|
using GreenshotPlugin.Controls;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using Encoder = System.Drawing.Imaging.Encoder;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of ImageOutput.
|
||||||
|
/// </summary>
|
||||||
|
public static class ImageOutput
|
||||||
|
{
|
||||||
|
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
|
private static readonly int PROPERTY_TAG_SOFTWARE_USED = 0x0131;
|
||||||
|
private static Cache<string, string> tmpFileCache = new Cache<string, string>(10 * 60 * 60, RemoveExpiredTmpFile);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a PropertyItem (Metadata) to store with the image.
|
||||||
|
/// For the possible ID's see: http://msdn.microsoft.com/de-de/library/system.drawing.imaging.propertyitem.id(v=vs.80).aspx
|
||||||
|
/// This code uses Reflection to create a PropertyItem, although it's not adviced it's not as stupid as having a image in the project so we can read a PropertyItem from that!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">ID</param>
|
||||||
|
/// <param name="text">Text</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static PropertyItem CreatePropertyItem(int id, string text)
|
||||||
|
{
|
||||||
|
PropertyItem propertyItem = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ConstructorInfo ci = typeof(PropertyItem).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public, null, new Type[] { }, null);
|
||||||
|
propertyItem = (PropertyItem)ci.Invoke(null);
|
||||||
|
// Make sure it's of type string
|
||||||
|
propertyItem.Type = 2;
|
||||||
|
// Set the ID
|
||||||
|
propertyItem.Id = id;
|
||||||
|
// Set the text
|
||||||
|
byte[] byteString = ASCIIEncoding.ASCII.GetBytes(text + " ");
|
||||||
|
// Set Zero byte for String end.
|
||||||
|
byteString[byteString.Length - 1] = 0;
|
||||||
|
propertyItem.Value = byteString;
|
||||||
|
propertyItem.Len = text.Length + 1;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("Error creating a PropertyItem: {0}", e.Message);
|
||||||
|
}
|
||||||
|
return propertyItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region save
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves ISurface to stream with specified output settings
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="surface">ISurface to save</param>
|
||||||
|
/// <param name="stream">Stream to save to</param>
|
||||||
|
/// <param name="outputSettings">SurfaceOutputSettings</param>
|
||||||
|
public static void SaveToStream(ISurface surface, Stream stream, SurfaceOutputSettings outputSettings)
|
||||||
|
{
|
||||||
|
Image imageToSave = null;
|
||||||
|
bool disposeImage = CreateImageFromSurface(surface, outputSettings, out imageToSave);
|
||||||
|
SaveToStream(imageToSave, surface, stream, outputSettings);
|
||||||
|
// cleanup if needed
|
||||||
|
if (disposeImage && imageToSave != null)
|
||||||
|
{
|
||||||
|
imageToSave.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves image to stream with specified quality
|
||||||
|
/// To prevent problems with GDI version of before Windows 7:
|
||||||
|
/// the stream is checked if it's seekable and if needed a MemoryStream as "cache" is used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="imageToSave">image to save</param>
|
||||||
|
/// <param name="surface">surface for the elements, needed if the greenshot format is used</param>
|
||||||
|
/// <param name="stream">Stream to save to</param>
|
||||||
|
/// <param name="outputSettings">SurfaceOutputSettings</param>
|
||||||
|
public static void SaveToStream(Image imageToSave, ISurface surface, Stream stream, SurfaceOutputSettings outputSettings)
|
||||||
|
{
|
||||||
|
ImageFormat imageFormat = null;
|
||||||
|
bool useMemoryStream = false;
|
||||||
|
MemoryStream memoryStream = null;
|
||||||
|
if (outputSettings.Format == OutputFormat.greenshot && surface == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Surface needs to be se when using OutputFormat.Greenshot");
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (outputSettings.Format)
|
||||||
|
{
|
||||||
|
case OutputFormat.bmp:
|
||||||
|
imageFormat = ImageFormat.Bmp;
|
||||||
|
break;
|
||||||
|
case OutputFormat.gif:
|
||||||
|
imageFormat = ImageFormat.Gif;
|
||||||
|
break;
|
||||||
|
case OutputFormat.jpg:
|
||||||
|
imageFormat = ImageFormat.Jpeg;
|
||||||
|
break;
|
||||||
|
case OutputFormat.tiff:
|
||||||
|
imageFormat = ImageFormat.Tiff;
|
||||||
|
break;
|
||||||
|
case OutputFormat.greenshot:
|
||||||
|
case OutputFormat.png:
|
||||||
|
default:
|
||||||
|
// Problem with non-seekable streams most likely doesn't happen with Windows 7 (OS Version 6.1 and later)
|
||||||
|
// http://stackoverflow.com/questions/8349260/generic-gdi-error-on-one-machine-but-not-the-other
|
||||||
|
if (!stream.CanSeek)
|
||||||
|
{
|
||||||
|
int majorVersion = Environment.OSVersion.Version.Major;
|
||||||
|
int minorVersion = Environment.OSVersion.Version.Minor;
|
||||||
|
if (majorVersion < 6 || (majorVersion == 6 && minorVersion == 0))
|
||||||
|
{
|
||||||
|
useMemoryStream = true;
|
||||||
|
LOG.Warn("Using memorystream prevent an issue with saving to a non seekable stream.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imageFormat = ImageFormat.Png;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LOG.DebugFormat("Saving image to stream with Format {0} and PixelFormat {1}", imageFormat, imageToSave.PixelFormat);
|
||||||
|
|
||||||
|
// Check if we want to use a memory stream, to prevent a issue which happens with Windows before "7".
|
||||||
|
// The save is made to the targetStream, this is directed to either the MemoryStream or the original
|
||||||
|
Stream targetStream = stream;
|
||||||
|
if (useMemoryStream)
|
||||||
|
{
|
||||||
|
memoryStream = new MemoryStream();
|
||||||
|
targetStream = memoryStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageFormat == ImageFormat.Jpeg)
|
||||||
|
{
|
||||||
|
bool foundEncoder = false;
|
||||||
|
foreach (ImageCodecInfo imageCodec in ImageCodecInfo.GetImageEncoders())
|
||||||
|
{
|
||||||
|
if (imageCodec.FormatID == imageFormat.Guid)
|
||||||
|
{
|
||||||
|
EncoderParameters parameters = new EncoderParameters(1);
|
||||||
|
parameters.Param[0] = new EncoderParameter(Encoder.Quality, outputSettings.JPGQuality);
|
||||||
|
// Removing transparency if it's not supported in the output
|
||||||
|
if (Image.IsAlphaPixelFormat(imageToSave.PixelFormat))
|
||||||
|
{
|
||||||
|
Image nonAlphaImage = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb);
|
||||||
|
AddTag(nonAlphaImage);
|
||||||
|
nonAlphaImage.Save(targetStream, imageCodec, parameters);
|
||||||
|
nonAlphaImage.Dispose();
|
||||||
|
nonAlphaImage = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddTag(imageToSave);
|
||||||
|
imageToSave.Save(targetStream, imageCodec, parameters);
|
||||||
|
}
|
||||||
|
foundEncoder = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundEncoder)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("No JPG encoder found, this should not happen.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Removing transparency if it's not supported in the output
|
||||||
|
if (imageFormat != ImageFormat.Png && Image.IsAlphaPixelFormat(imageToSave.PixelFormat))
|
||||||
|
{
|
||||||
|
Image nonAlphaImage = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb);
|
||||||
|
AddTag(nonAlphaImage);
|
||||||
|
nonAlphaImage.Save(targetStream, imageFormat);
|
||||||
|
nonAlphaImage.Dispose();
|
||||||
|
nonAlphaImage = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AddTag(imageToSave);
|
||||||
|
imageToSave.Save(targetStream, imageFormat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we used a memory stream, we need to stream the memory stream to the original stream.
|
||||||
|
if (useMemoryStream)
|
||||||
|
{
|
||||||
|
memoryStream.WriteTo(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output the surface elements, size and marker to the stream
|
||||||
|
if (outputSettings.Format == OutputFormat.greenshot)
|
||||||
|
{
|
||||||
|
using (MemoryStream tmpStream = new MemoryStream())
|
||||||
|
{
|
||||||
|
long bytesWritten = surface.SaveElementsToStream(tmpStream);
|
||||||
|
using (BinaryWriter writer = new BinaryWriter(tmpStream))
|
||||||
|
{
|
||||||
|
writer.Write(bytesWritten);
|
||||||
|
Version v = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
|
byte[] marker = Encoding.ASCII.GetBytes(String.Format("Greenshot{0:00}.{1:00}", v.Major, v.Minor));
|
||||||
|
writer.Write(marker);
|
||||||
|
tmpStream.WriteTo(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
if (memoryStream != null)
|
||||||
|
{
|
||||||
|
memoryStream.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create an image from a surface with the settings from the output settings applied
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="surface"></param>
|
||||||
|
/// <param name="outputSettings"></param>
|
||||||
|
/// <param name="imageToSave"></param>
|
||||||
|
/// <returns>true if the image must be disposed</returns>
|
||||||
|
public static bool CreateImageFromSurface(ISurface surface, SurfaceOutputSettings outputSettings, out Image imageToSave)
|
||||||
|
{
|
||||||
|
bool disposeImage = false;
|
||||||
|
ImageFormat imageFormat = null;
|
||||||
|
switch (outputSettings.Format)
|
||||||
|
{
|
||||||
|
case OutputFormat.bmp:
|
||||||
|
imageFormat = ImageFormat.Bmp;
|
||||||
|
break;
|
||||||
|
case OutputFormat.gif:
|
||||||
|
imageFormat = ImageFormat.Gif;
|
||||||
|
break;
|
||||||
|
case OutputFormat.jpg:
|
||||||
|
imageFormat = ImageFormat.Jpeg;
|
||||||
|
break;
|
||||||
|
case OutputFormat.tiff:
|
||||||
|
imageFormat = ImageFormat.Tiff;
|
||||||
|
break;
|
||||||
|
case OutputFormat.greenshot:
|
||||||
|
case OutputFormat.png:
|
||||||
|
default:
|
||||||
|
imageFormat = ImageFormat.Png;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outputSettings.Format == OutputFormat.greenshot || outputSettings.SaveBackgroundOnly)
|
||||||
|
{
|
||||||
|
// We save the image of the surface, this should not be disposed
|
||||||
|
imageToSave = surface.Image;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We create the export image of the surface to save
|
||||||
|
imageToSave = surface.GetImageForExport();
|
||||||
|
disposeImage = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following block of modifications should be skipped when saving the greenshot format, no effects or otherwise!
|
||||||
|
if (outputSettings.Format != OutputFormat.greenshot)
|
||||||
|
{
|
||||||
|
Image tmpImage;
|
||||||
|
if (outputSettings.Effects != null && outputSettings.Effects.Count > 0)
|
||||||
|
{
|
||||||
|
// apply effects, if there are any
|
||||||
|
Point ignoreOffset;
|
||||||
|
tmpImage = ImageHelper.ApplyEffects((Bitmap)imageToSave, outputSettings.Effects, out ignoreOffset);
|
||||||
|
if (tmpImage != null)
|
||||||
|
{
|
||||||
|
if (disposeImage)
|
||||||
|
{
|
||||||
|
imageToSave.Dispose();
|
||||||
|
}
|
||||||
|
imageToSave = tmpImage;
|
||||||
|
disposeImage = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for color reduction, forced or automatically, only when the DisableReduceColors is false
|
||||||
|
if (!outputSettings.DisableReduceColors && (conf.OutputFileAutoReduceColors || outputSettings.ReduceColors))
|
||||||
|
{
|
||||||
|
bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat);
|
||||||
|
if (outputSettings.ReduceColors || (!isAlpha && conf.OutputFileAutoReduceColors))
|
||||||
|
{
|
||||||
|
using (WuQuantizer quantizer = new WuQuantizer((Bitmap)imageToSave))
|
||||||
|
{
|
||||||
|
int colorCount = quantizer.GetColorCount();
|
||||||
|
LOG.InfoFormat("Image with format {0} has {1} colors", imageToSave.PixelFormat, colorCount);
|
||||||
|
if (outputSettings.ReduceColors || colorCount < 256)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LOG.Info("Reducing colors on bitmap to 256.");
|
||||||
|
tmpImage = quantizer.GetQuantizedImage(256);
|
||||||
|
if (disposeImage)
|
||||||
|
{
|
||||||
|
imageToSave.Dispose();
|
||||||
|
}
|
||||||
|
imageToSave = tmpImage;
|
||||||
|
// Make sure the "new" image is disposed
|
||||||
|
disposeImage = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Warn("Error occurred while Quantizing the image, ignoring and using original. Error: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isAlpha && !outputSettings.ReduceColors)
|
||||||
|
{
|
||||||
|
LOG.Info("Skipping 'optional' color reduction as the image has alpha");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return disposeImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add the greenshot property!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="imageToSave"></param>
|
||||||
|
private static void AddTag(Image imageToSave)
|
||||||
|
{
|
||||||
|
// Create meta-data
|
||||||
|
PropertyItem softwareUsedPropertyItem = CreatePropertyItem(PROPERTY_TAG_SOFTWARE_USED, "Greenshot");
|
||||||
|
if (softwareUsedPropertyItem != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
imageToSave.SetPropertyItem(softwareUsedPropertyItem);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("Couldn't set property {0}", softwareUsedPropertyItem.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load a Greenshot surface
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fullPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static ISurface LoadGreenshotSurface(string fullPath, ISurface returnSurface)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(fullPath))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Image fileImage = null;
|
||||||
|
LOG.InfoFormat("Loading image from file {0}", fullPath);
|
||||||
|
// Fixed lock problem Bug #3431881
|
||||||
|
using (Stream surfaceFileStream = File.OpenRead(fullPath))
|
||||||
|
{
|
||||||
|
// And fixed problem that the bitmap stream is disposed... by Cloning the image
|
||||||
|
// This also ensures the bitmap is correctly created
|
||||||
|
|
||||||
|
// We create a copy of the bitmap, so everything else can be disposed
|
||||||
|
surfaceFileStream.Position = 0;
|
||||||
|
using (Image tmpImage = Image.FromStream(surfaceFileStream, true, true))
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Loaded {0} with Size {1}x{2} and PixelFormat {3}", fullPath, tmpImage.Width, tmpImage.Height, tmpImage.PixelFormat);
|
||||||
|
fileImage = ImageHelper.Clone(tmpImage);
|
||||||
|
}
|
||||||
|
// Start at -14 read "GreenshotXX.YY" (XX=Major, YY=Minor)
|
||||||
|
const int markerSize = 14;
|
||||||
|
surfaceFileStream.Seek(-markerSize, SeekOrigin.End);
|
||||||
|
string greenshotMarker;
|
||||||
|
using (StreamReader streamReader = new StreamReader(surfaceFileStream))
|
||||||
|
{
|
||||||
|
greenshotMarker = streamReader.ReadToEnd();
|
||||||
|
if (greenshotMarker == null || !greenshotMarker.StartsWith("Greenshot"))
|
||||||
|
{
|
||||||
|
throw new ArgumentException(string.Format("{0} is not a Greenshot file!", fullPath));
|
||||||
|
}
|
||||||
|
LOG.InfoFormat("Greenshot file format: {0}", greenshotMarker);
|
||||||
|
const int filesizeLocation = 8 + markerSize;
|
||||||
|
surfaceFileStream.Seek(-filesizeLocation, SeekOrigin.End);
|
||||||
|
long bytesWritten = 0;
|
||||||
|
using (BinaryReader reader = new BinaryReader(surfaceFileStream))
|
||||||
|
{
|
||||||
|
bytesWritten = reader.ReadInt64();
|
||||||
|
surfaceFileStream.Seek(-(bytesWritten + filesizeLocation), SeekOrigin.End);
|
||||||
|
returnSurface.LoadElementsFromStream(surfaceFileStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fileImage != null)
|
||||||
|
{
|
||||||
|
returnSurface.Image = fileImage;
|
||||||
|
LOG.InfoFormat("Information about file {0}: {1}x{2}-{3} Resolution {4}x{5}", fullPath, fileImage.Width, fileImage.Height, fileImage.PixelFormat, fileImage.HorizontalResolution, fileImage.VerticalResolution);
|
||||||
|
}
|
||||||
|
return returnSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves image to specific path with specified quality
|
||||||
|
/// </summary>
|
||||||
|
public static void Save(ISurface surface, string fullPath, bool allowOverwrite, SurfaceOutputSettings outputSettings, bool copyPathToClipboard)
|
||||||
|
{
|
||||||
|
fullPath = FilenameHelper.MakeFQFilenameSafe(fullPath);
|
||||||
|
string path = Path.GetDirectoryName(fullPath);
|
||||||
|
|
||||||
|
// check whether path exists - if not create it
|
||||||
|
DirectoryInfo di = new DirectoryInfo(path);
|
||||||
|
if (!di.Exists)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(di.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!allowOverwrite && File.Exists(fullPath))
|
||||||
|
{
|
||||||
|
ArgumentException throwingException = new ArgumentException("File '" + fullPath + "' already exists.");
|
||||||
|
throwingException.Data.Add("fullPath", fullPath);
|
||||||
|
throw throwingException;
|
||||||
|
}
|
||||||
|
LOG.DebugFormat("Saving surface to {0}", fullPath);
|
||||||
|
// Create the stream and call SaveToStream
|
||||||
|
using (FileStream stream = new FileStream(fullPath, FileMode.Create, FileAccess.Write))
|
||||||
|
{
|
||||||
|
SaveToStream(surface, stream, outputSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copyPathToClipboard)
|
||||||
|
{
|
||||||
|
ClipboardHelper.SetClipboardData(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the OutputFormat for a filename
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fullPath">filename (can be a complete path)</param>
|
||||||
|
/// <returns>OutputFormat</returns>
|
||||||
|
public static OutputFormat FormatForFilename(string fullPath)
|
||||||
|
{
|
||||||
|
// Fix for bug 2912959
|
||||||
|
string extension = fullPath.Substring(fullPath.LastIndexOf(".") + 1);
|
||||||
|
OutputFormat format = OutputFormat.png;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (extension != null)
|
||||||
|
{
|
||||||
|
format = (OutputFormat)Enum.Parse(typeof(OutputFormat), extension.ToLower());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ArgumentException ae)
|
||||||
|
{
|
||||||
|
LOG.Warn("Couldn't parse extension: " + extension, ae);
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion save
|
||||||
|
|
||||||
|
#region save-as
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save with showing a dialog
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="surface"></param>
|
||||||
|
/// <param name="captureDetails"></param>
|
||||||
|
/// <returns>Path to filename</returns>
|
||||||
|
public static string SaveWithDialog(ISurface surface, ICaptureDetails captureDetails)
|
||||||
|
{
|
||||||
|
string returnValue = null;
|
||||||
|
using (SaveImageFileDialog saveImageFileDialog = new SaveImageFileDialog(captureDetails))
|
||||||
|
{
|
||||||
|
DialogResult dialogResult = saveImageFileDialog.ShowDialog();
|
||||||
|
if (dialogResult.Equals(DialogResult.OK))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string fileNameWithExtension = saveImageFileDialog.FileNameWithExtension;
|
||||||
|
SurfaceOutputSettings outputSettings = new SurfaceOutputSettings(FormatForFilename(fileNameWithExtension));
|
||||||
|
if (conf.OutputFilePromptQuality)
|
||||||
|
{
|
||||||
|
QualityDialog qualityDialog = new QualityDialog(outputSettings);
|
||||||
|
qualityDialog.ShowDialog();
|
||||||
|
}
|
||||||
|
// TODO: For now we always overwrite, should be changed
|
||||||
|
Save(surface, fileNameWithExtension, true, outputSettings, conf.OutputFileCopyPathToClipboard);
|
||||||
|
returnValue = fileNameWithExtension;
|
||||||
|
IniConfig.Save();
|
||||||
|
}
|
||||||
|
catch (ExternalException)
|
||||||
|
{
|
||||||
|
MessageBox.Show(Language.GetFormattedString("error_nowriteaccess", saveImageFileDialog.FileName).Replace(@"\\", @"\"), Language.GetString("error"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion save-as
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a tmpfile which has the name like in the configured pattern.
|
||||||
|
/// Used e.g. by the email export
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="surface"></param>
|
||||||
|
/// <param name="captureDetails"></param>
|
||||||
|
/// <param name="outputSettings"></param>
|
||||||
|
/// <returns>Path to image file</returns>
|
||||||
|
public static string SaveNamedTmpFile(ISurface surface, ICaptureDetails captureDetails, SurfaceOutputSettings outputSettings)
|
||||||
|
{
|
||||||
|
string pattern = conf.OutputFileFilenamePattern;
|
||||||
|
if (pattern == null || string.IsNullOrEmpty(pattern.Trim()))
|
||||||
|
{
|
||||||
|
pattern = "greenshot ${capturetime}";
|
||||||
|
}
|
||||||
|
string filename = FilenameHelper.GetFilenameFromPattern(pattern, outputSettings.Format, captureDetails);
|
||||||
|
// Prevent problems with "other characters", which causes a problem in e.g. Outlook 2007 or break our HTML
|
||||||
|
filename = Regex.Replace(filename, @"[^\d\w\.]", "_");
|
||||||
|
// Remove multiple "_"
|
||||||
|
filename = Regex.Replace(filename, @"_+", "_");
|
||||||
|
string tmpFile = Path.Combine(Path.GetTempPath(), filename);
|
||||||
|
|
||||||
|
LOG.Debug("Creating TMP File: " + tmpFile);
|
||||||
|
|
||||||
|
// 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
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Save(surface, tmpFile, true, outputSettings, false);
|
||||||
|
tmpFileCache.Add(tmpFile, tmpFile);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// Show the problem
|
||||||
|
MessageBox.Show(e.Message, "Error");
|
||||||
|
// when save failed we present a SaveWithDialog
|
||||||
|
tmpFile = SaveWithDialog(surface, captureDetails);
|
||||||
|
}
|
||||||
|
return tmpFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to create a temp image file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="image"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string SaveToTmpFile(ISurface surface, SurfaceOutputSettings outputSettings, string destinationPath)
|
||||||
|
{
|
||||||
|
string tmpFile = Path.GetRandomFileName() + "." + outputSettings.Format.ToString();
|
||||||
|
// Prevent problems with "other characters", which could cause problems
|
||||||
|
tmpFile = Regex.Replace(tmpFile, @"[^\d\w\.]", "");
|
||||||
|
if (destinationPath == null)
|
||||||
|
{
|
||||||
|
destinationPath = Path.GetTempPath();
|
||||||
|
}
|
||||||
|
string tmpPath = Path.Combine(destinationPath, tmpFile);
|
||||||
|
LOG.Debug("Creating TMP File : " + tmpPath);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Save(surface, tmpPath, true, outputSettings, false);
|
||||||
|
tmpFileCache.Add(tmpPath, tmpPath);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return tmpPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cleanup all created tmpfiles
|
||||||
|
/// </summary>
|
||||||
|
public static void RemoveTmpFiles()
|
||||||
|
{
|
||||||
|
foreach (string tmpFile in tmpFileCache.Elements)
|
||||||
|
{
|
||||||
|
if (File.Exists(tmpFile))
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Removing old temp file {0}", tmpFile);
|
||||||
|
File.Delete(tmpFile);
|
||||||
|
}
|
||||||
|
tmpFileCache.Remove(tmpFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cleanup handler for expired tempfiles
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename"></param>
|
||||||
|
/// <param name="alsoTheFilename"></param>
|
||||||
|
private static void RemoveExpiredTmpFile(string filekey, object filename)
|
||||||
|
{
|
||||||
|
string path = filename as string;
|
||||||
|
if (path != null && File.Exists(path))
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Removing expired file {0}", path);
|
||||||
|
File.Delete(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
89
GreenshotImageEditor/Core/LOG.cs
Normal file
89
GreenshotImageEditor/Core/LOG.cs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin
|
||||||
|
{
|
||||||
|
// Workaround for removing log4net
|
||||||
|
public static class LOG
|
||||||
|
{
|
||||||
|
public static bool IsDebugEnabled
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Warn(string text)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WarnFormat(string format, params object[] args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Warn(Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Warn(string text, Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Error(string text)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ErrorFormat(string format, params object[] args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Error(Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Error(string text, Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Info(string text)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void InfoFormat(string format, params object[] args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Debug(string text)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DebugFormat(string text, params object[] args)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Debug(string text, Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
863
GreenshotImageEditor/Core/Language.cs
Normal file
863
GreenshotImageEditor/Core/Language.cs
Normal file
|
@ -0,0 +1,863 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
public delegate void LanguageChangedHandler(object sender, EventArgs e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This class supplies the GUI with translations, based upon keys.
|
||||||
|
/// The language resources are loaded from the language files found on fixed or supplied paths
|
||||||
|
/// </summary>
|
||||||
|
public class Language
|
||||||
|
{
|
||||||
|
private static List<string> languagePaths = new List<string>();
|
||||||
|
private static IDictionary<string, List<LanguageFile>> languageFiles = new Dictionary<string, List<LanguageFile>>();
|
||||||
|
private static IDictionary<string, string> helpFiles = new Dictionary<string, string>();
|
||||||
|
private const string DEFAULT_LANGUAGE = "en-US";
|
||||||
|
private const string HELP_FILENAME_PATTERN = @"help-*.html";
|
||||||
|
private const string LANGUAGE_FILENAME_PATTERN = @"language*.xml";
|
||||||
|
private static Regex PREFIX_REGEXP = new Regex(@"language_([a-zA-Z0-9]+).*");
|
||||||
|
private static Regex IETF_CLEAN_REGEXP = new Regex(@"[^a-zA-Z]+");
|
||||||
|
private static Regex IETF_REGEXP = new Regex(@"^.*([a-zA-Z]{2}-[a-zA-Z]{2})\.xml$");
|
||||||
|
private const string LANGUAGE_GROUPS_KEY = @"SYSTEM\CurrentControlSet\Control\Nls\Language Groups";
|
||||||
|
private static List<string> unsupportedLanguageGroups = new List<string>();
|
||||||
|
private static IDictionary<string, string> resources = new Dictionary<string, string>();
|
||||||
|
private static string currentLanguage = null;
|
||||||
|
|
||||||
|
public static event LanguageChangedHandler LanguageChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static initializer for the language code
|
||||||
|
/// </summary>
|
||||||
|
static Language()
|
||||||
|
{
|
||||||
|
/*try
|
||||||
|
{
|
||||||
|
string applicationDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||||
|
string applicationFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||||
|
|
||||||
|
// PAF Path
|
||||||
|
AddPath(Path.Combine(applicationFolder, @"App\Greenshot\Languages"));
|
||||||
|
|
||||||
|
// Application data path
|
||||||
|
AddPath(Path.Combine(applicationDataFolder, @"Greenshot\Languages\"));
|
||||||
|
|
||||||
|
// Startup path
|
||||||
|
AddPath(Path.Combine(applicationFolder, @"Languages"));
|
||||||
|
}
|
||||||
|
catch (Exception pathException)
|
||||||
|
{
|
||||||
|
LOG.Error(pathException);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (RegistryKey languageGroupsKey = Registry.LocalMachine.OpenSubKey(LANGUAGE_GROUPS_KEY, false))
|
||||||
|
{
|
||||||
|
if (languageGroupsKey != null)
|
||||||
|
{
|
||||||
|
string[] groups = languageGroupsKey.GetValueNames();
|
||||||
|
foreach (string group in groups)
|
||||||
|
{
|
||||||
|
string groupValue = (string)languageGroupsKey.GetValue(group);
|
||||||
|
bool isGroupNotInstalled = "0".Equals(groupValue);
|
||||||
|
if (isGroupNotInstalled)
|
||||||
|
{
|
||||||
|
unsupportedLanguageGroups.Add(group.ToLower());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Warn("Couldn't read the installed language groups.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
coreConfig = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
|
ScanFiles();
|
||||||
|
if (!string.IsNullOrEmpty(coreConfig.Language))
|
||||||
|
{
|
||||||
|
CurrentLanguage = coreConfig.Language;
|
||||||
|
if (CurrentLanguage != null && CurrentLanguage != coreConfig.Language)
|
||||||
|
{
|
||||||
|
coreConfig.Language = CurrentLanguage;
|
||||||
|
IniConfig.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentLanguage == null)
|
||||||
|
{
|
||||||
|
LOG.Warn("Couldn't set language from configuration, changing to default. Installation problem?");
|
||||||
|
CurrentLanguage = DEFAULT_LANGUAGE;
|
||||||
|
if (CurrentLanguage != null)
|
||||||
|
{
|
||||||
|
coreConfig.Language = CurrentLanguage;
|
||||||
|
IniConfig.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentLanguage == null)
|
||||||
|
{
|
||||||
|
LOG.Error("Couldn't set language, installation problem?");
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Internal method to add a path to the paths that will be scanned for language files!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns>true if the path exists and is added</returns>
|
||||||
|
private static bool AddPath(string path)
|
||||||
|
{
|
||||||
|
if (!languagePaths.Contains(path))
|
||||||
|
{
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Adding language path {0}", path);
|
||||||
|
languagePaths.Add(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Not adding non existing language path {0}", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a new path to the paths that will be scanned for language files!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns>true if the path exists and is added</returns>
|
||||||
|
public static bool AddLanguageFilePath(string path)
|
||||||
|
{
|
||||||
|
if (!languagePaths.Contains(path))
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("New language path {0}", path);
|
||||||
|
if (AddPath(path))
|
||||||
|
{
|
||||||
|
ScanFiles();
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load the files for the specified ietf
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ietf"></param>
|
||||||
|
private static void LoadFiles(string ietf)
|
||||||
|
{
|
||||||
|
ietf = ReformatIETF(ietf);
|
||||||
|
if (!languageFiles.ContainsKey(ietf))
|
||||||
|
{
|
||||||
|
LOG.ErrorFormat("No language {0} available.", ietf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<LanguageFile> filesToLoad = languageFiles[ietf];
|
||||||
|
foreach (LanguageFile fileToLoad in filesToLoad)
|
||||||
|
{
|
||||||
|
LoadResources(fileToLoad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load the language resources from the scanned files
|
||||||
|
/// </summary>
|
||||||
|
private static void Reload()
|
||||||
|
{
|
||||||
|
resources.Clear();
|
||||||
|
LoadFiles(DEFAULT_LANGUAGE);
|
||||||
|
if (currentLanguage != null && !currentLanguage.Equals(DEFAULT_LANGUAGE))
|
||||||
|
{
|
||||||
|
LoadFiles(currentLanguage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get or set the current language
|
||||||
|
/// </summary>
|
||||||
|
public static string CurrentLanguage
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return currentLanguage;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
string ietf = FindBestIETFMatch(value);
|
||||||
|
if (!languageFiles.ContainsKey(ietf))
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("No match for language {0} found!", ietf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (currentLanguage == null || !currentLanguage.Equals(ietf))
|
||||||
|
{
|
||||||
|
currentLanguage = ietf;
|
||||||
|
Reload();
|
||||||
|
if (LanguageChanged != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LanguageChanged(null, null);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.Debug("CurrentLanguage not changed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Try to find the best match for the supplied IETF
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputIETF"></param>
|
||||||
|
/// <returns>IETF</returns>
|
||||||
|
private static string FindBestIETFMatch(string inputIETF)
|
||||||
|
{
|
||||||
|
string returnIETF = inputIETF;
|
||||||
|
if (string.IsNullOrEmpty(returnIETF))
|
||||||
|
{
|
||||||
|
returnIETF = DEFAULT_LANGUAGE;
|
||||||
|
}
|
||||||
|
returnIETF = ReformatIETF(returnIETF);
|
||||||
|
if (!languageFiles.ContainsKey(returnIETF))
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("Unknown language {0}, trying best match!", returnIETF);
|
||||||
|
if (returnIETF.Length == 5)
|
||||||
|
{
|
||||||
|
returnIETF = returnIETF.Substring(0, 2);
|
||||||
|
}
|
||||||
|
foreach (string availableIETF in languageFiles.Keys)
|
||||||
|
{
|
||||||
|
if (availableIETF.StartsWith(returnIETF))
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Found language {0}, best match for {1}!", availableIETF, returnIETF);
|
||||||
|
returnIETF = availableIETF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnIETF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This helper method clears all non alpha characters from the IETF, and does a reformatting.
|
||||||
|
/// This prevents problems with multiple formats or typos.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputIETF"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static string ReformatIETF(string inputIETF)
|
||||||
|
{
|
||||||
|
string returnIETF = null;
|
||||||
|
if (!string.IsNullOrEmpty(inputIETF))
|
||||||
|
{
|
||||||
|
returnIETF = inputIETF.ToLower();
|
||||||
|
returnIETF = IETF_CLEAN_REGEXP.Replace(returnIETF, "");
|
||||||
|
if (returnIETF.Length == 4)
|
||||||
|
{
|
||||||
|
returnIETF = returnIETF.Substring(0, 2) + "-" + returnIETF.Substring(2, 2).ToUpper();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnIETF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return a list of all the supported languages
|
||||||
|
/// </summary>
|
||||||
|
public static IList<LanguageFile> SupportedLanguages
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
IList<LanguageFile> languages = new List<LanguageFile>();
|
||||||
|
// Loop over all languages with all the files in there
|
||||||
|
foreach (List<LanguageFile> langs in languageFiles.Values)
|
||||||
|
{
|
||||||
|
// Loop over all the files for a language
|
||||||
|
foreach (LanguageFile langFile in langs)
|
||||||
|
{
|
||||||
|
// Only take the ones without prefix, these are the "base" language files
|
||||||
|
if (langFile.Prefix == null)
|
||||||
|
{
|
||||||
|
languages.Add(langFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return languages;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the path to the help-file
|
||||||
|
/// </summary>
|
||||||
|
public static string HelpFilePath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (helpFiles.ContainsKey(currentLanguage))
|
||||||
|
{
|
||||||
|
return helpFiles[currentLanguage];
|
||||||
|
}
|
||||||
|
return helpFiles[DEFAULT_LANGUAGE];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load the resources from the language file
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="languageFile">File to load from</param>
|
||||||
|
private static void LoadResources(LanguageFile languageFile)
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Loading language file {0}", languageFile.Filepath);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XmlDocument xmlDocument = new XmlDocument();
|
||||||
|
xmlDocument.Load(languageFile.Filepath);
|
||||||
|
XmlNodeList resourceNodes = xmlDocument.GetElementsByTagName("resource");
|
||||||
|
foreach (XmlNode resourceNode in resourceNodes)
|
||||||
|
{
|
||||||
|
string key = resourceNode.Attributes["name"].Value;
|
||||||
|
if (!string.IsNullOrEmpty(languageFile.Prefix))
|
||||||
|
{
|
||||||
|
key = languageFile.Prefix + "." + key;
|
||||||
|
}
|
||||||
|
string text = resourceNode.InnerText;
|
||||||
|
if (!string.IsNullOrEmpty(text))
|
||||||
|
{
|
||||||
|
text = text.Trim();
|
||||||
|
}
|
||||||
|
if (!resources.ContainsKey(key))
|
||||||
|
{
|
||||||
|
resources.Add(key, text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resources[key] = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Could not load language file " + languageFile.Filepath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Load the language file information
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="languageFilePath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static LanguageFile LoadFileInfo(string languageFilePath)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
XmlDocument xmlDocument = new XmlDocument();
|
||||||
|
xmlDocument.Load(languageFilePath);
|
||||||
|
XmlNodeList nodes = xmlDocument.GetElementsByTagName("language");
|
||||||
|
if (nodes.Count > 0)
|
||||||
|
{
|
||||||
|
LanguageFile languageFile = new LanguageFile();
|
||||||
|
languageFile.Filepath = languageFilePath;
|
||||||
|
XmlNode node = nodes.Item(0);
|
||||||
|
languageFile.Description = node.Attributes["description"].Value;
|
||||||
|
if (node.Attributes["ietf"] != null)
|
||||||
|
{
|
||||||
|
languageFile.Ietf = ReformatIETF(node.Attributes["ietf"].Value);
|
||||||
|
}
|
||||||
|
if (node.Attributes["version"] != null)
|
||||||
|
{
|
||||||
|
languageFile.Version = new Version(node.Attributes["version"].Value);
|
||||||
|
}
|
||||||
|
if (node.Attributes["prefix"] != null)
|
||||||
|
{
|
||||||
|
languageFile.Prefix = node.Attributes["prefix"].Value.ToLower();
|
||||||
|
}
|
||||||
|
if (node.Attributes["languagegroup"] != null)
|
||||||
|
{
|
||||||
|
string languageGroup = node.Attributes["languagegroup"].Value;
|
||||||
|
languageFile.LanguageGroup = languageGroup.ToLower();
|
||||||
|
}
|
||||||
|
return languageFile;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new XmlException("Root element <language> is missing");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Could not load language file " + languageFilePath, e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Scan the files in all directories
|
||||||
|
/// </summary>
|
||||||
|
private static void ScanFiles()
|
||||||
|
{
|
||||||
|
languageFiles.Clear();
|
||||||
|
helpFiles.Clear();
|
||||||
|
foreach (string languagePath in languagePaths)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(languagePath))
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Skipping non existing language path {0}", languagePath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
LOG.InfoFormat("Searching language directory '{0}' for language files with pattern '{1}'", languagePath, LANGUAGE_FILENAME_PATTERN);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (string languageFilepath in Directory.GetFiles(languagePath, LANGUAGE_FILENAME_PATTERN, SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
//LOG.DebugFormat("Found language file: {0}", languageFilepath);
|
||||||
|
LanguageFile languageFile = LoadFileInfo(languageFilepath);
|
||||||
|
if (languageFile == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(languageFile.Ietf))
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("Fixing missing ietf in language-file {0}", languageFilepath);
|
||||||
|
string languageFilename = Path.GetFileName(languageFilepath);
|
||||||
|
if (IETF_REGEXP.IsMatch(languageFilename))
|
||||||
|
{
|
||||||
|
string replacementIETF = IETF_REGEXP.Replace(languageFilename, "$1");
|
||||||
|
languageFile.Ietf = ReformatIETF(replacementIETF);
|
||||||
|
LOG.InfoFormat("Fixed IETF to {0}", languageFile.Ietf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.ErrorFormat("Missing ietf , no recover possible... skipping language-file {0}!", languageFilepath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we can display the file
|
||||||
|
if (!string.IsNullOrEmpty(languageFile.LanguageGroup) && unsupportedLanguageGroups.Contains(languageFile.LanguageGroup))
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Skipping unsuported (not able to display) language {0} from file {1}", languageFile.Description, languageFilepath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build prefix, based on the filename, but only if it's not set in the file itself.
|
||||||
|
if (string.IsNullOrEmpty(languageFile.Prefix))
|
||||||
|
{
|
||||||
|
string languageFilename = Path.GetFileNameWithoutExtension(languageFilepath);
|
||||||
|
if (PREFIX_REGEXP.IsMatch(languageFilename))
|
||||||
|
{
|
||||||
|
languageFile.Prefix = PREFIX_REGEXP.Replace(languageFilename, "$1");
|
||||||
|
if (!string.IsNullOrEmpty(languageFile.Prefix))
|
||||||
|
{
|
||||||
|
languageFile.Prefix = languageFile.Prefix.Replace("plugin", "").ToLower();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<LanguageFile> currentFiles = null;
|
||||||
|
if (languageFiles.ContainsKey(languageFile.Ietf))
|
||||||
|
{
|
||||||
|
currentFiles = languageFiles[languageFile.Ietf];
|
||||||
|
bool needToAdd = true;
|
||||||
|
List<LanguageFile> deleteList = new List<LanguageFile>();
|
||||||
|
foreach (LanguageFile compareWithLangfile in currentFiles)
|
||||||
|
{
|
||||||
|
if ((languageFile.Prefix == null && compareWithLangfile.Prefix == null) || (languageFile.Prefix != null && languageFile.Prefix.Equals(compareWithLangfile.Prefix)))
|
||||||
|
{
|
||||||
|
if (compareWithLangfile.Version > languageFile.Version)
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("Skipping {0}:{1}:{2} as {3}:{4}:{5} is newer", languageFile.Filepath, languageFile.Prefix, languageFile.Version, compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version);
|
||||||
|
needToAdd = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("Found {0}:{1}:{2} and deleting {3}:{4}:{5}", languageFile.Filepath, languageFile.Prefix, languageFile.Version, compareWithLangfile.Filepath, compareWithLangfile.Prefix, compareWithLangfile.Version);
|
||||||
|
deleteList.Add(compareWithLangfile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needToAdd)
|
||||||
|
{
|
||||||
|
foreach (LanguageFile deleteFile in deleteList)
|
||||||
|
{
|
||||||
|
currentFiles.Remove(deleteFile);
|
||||||
|
}
|
||||||
|
LOG.InfoFormat("Added language {0} from: {1}", languageFile.Description, languageFile.Filepath);
|
||||||
|
currentFiles.Add(languageFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentFiles = new List<LanguageFile>();
|
||||||
|
currentFiles.Add(languageFile);
|
||||||
|
languageFiles.Add(languageFile.Ietf, currentFiles);
|
||||||
|
LOG.InfoFormat("Added language {0} from: {1}", languageFile.Description, languageFile.Filepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (DirectoryNotFoundException)
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Non existing language directory: {0}", languagePath);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error trying for read directory " + languagePath, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now find the help files
|
||||||
|
LOG.InfoFormat("Searching language directory '{0}' for help files with pattern '{1}'", languagePath, HELP_FILENAME_PATTERN);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (string helpFilepath in Directory.GetFiles(languagePath, HELP_FILENAME_PATTERN, SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Found help file: {0}", helpFilepath);
|
||||||
|
string helpFilename = Path.GetFileName(helpFilepath);
|
||||||
|
string ietf = ReformatIETF(helpFilename.Replace(".html", "").Replace("help-", ""));
|
||||||
|
if (!helpFiles.ContainsKey(ietf))
|
||||||
|
{
|
||||||
|
helpFiles.Add(ietf, helpFilepath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.WarnFormat("skipping help file {0}, already a file with the same IETF {1} found!", helpFilepath, ietf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (DirectoryNotFoundException)
|
||||||
|
{
|
||||||
|
LOG.InfoFormat("Non existing language directory: {0}", languagePath);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOG.Error("Error trying for read directory " + languagePath, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if a resource with prefix.key exists
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefix"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>true if available</returns>
|
||||||
|
public static bool hasKey(string prefix, Enum key)
|
||||||
|
{
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return hasKey(prefix + "." + key.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if a resource with key exists
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>true if available</returns>
|
||||||
|
public static bool hasKey(Enum key)
|
||||||
|
{
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return hasKey(key.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if a resource with prefix.key exists
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefix"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>true if available</returns>
|
||||||
|
public static bool hasKey(string prefix, string key)
|
||||||
|
{
|
||||||
|
return hasKey(prefix + "." + key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if a resource with key exists
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>true if available</returns>
|
||||||
|
public static bool hasKey(string key)
|
||||||
|
{
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return resources.ContainsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TryGet method which combines hasKey & GetString
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="languageString">out string</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryGetString(string key, out string languageString)
|
||||||
|
{
|
||||||
|
return resources.TryGetValue(key, out languageString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TryGet method which combines hasKey & GetString
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefix">string with prefix</param>
|
||||||
|
/// <param name="key">string with key</param>
|
||||||
|
/// <param name="languageString">out string</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryGetString(string prefix, string key, out string languageString)
|
||||||
|
{
|
||||||
|
return resources.TryGetValue(prefix + "." + key, out languageString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Translate(object key)
|
||||||
|
{
|
||||||
|
string typename = key.GetType().Name;
|
||||||
|
string enumKey = typename + "." + key.ToString();
|
||||||
|
if (hasKey(enumKey))
|
||||||
|
{
|
||||||
|
return GetString(enumKey);
|
||||||
|
}
|
||||||
|
return key.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the resource for key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>resource or a "string ###key### not found"</returns>
|
||||||
|
public static string GetString(Enum key)
|
||||||
|
{
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return GetString(key.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the resource for prefix.key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefix"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>resource or a "string ###prefix.key### not found"</returns>
|
||||||
|
public static string GetString(string prefix, Enum key)
|
||||||
|
{
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return GetString(prefix + "." + key.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the resource for prefix.key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="prefix"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>resource or a "string ###prefix.key### not found"</returns>
|
||||||
|
public static string GetString(string prefix, string key)
|
||||||
|
{
|
||||||
|
return GetString(prefix + "." + key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the resource for key
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>resource or a "string ###key### not found"</returns>
|
||||||
|
public static string GetString(string key)
|
||||||
|
{
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
string returnValue;
|
||||||
|
if (!resources.TryGetValue(key, out returnValue))
|
||||||
|
{
|
||||||
|
return "string ###" + key + "### not found";
|
||||||
|
}
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the resource for key, format with with string.format an supply the parameters
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>formatted resource or a "string ###key### not found"</returns>
|
||||||
|
public static string GetFormattedString(Enum key, object param)
|
||||||
|
{
|
||||||
|
return GetFormattedString(key.ToString(), param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the resource for prefix.key, format with with string.format an supply the parameters
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>formatted resource or a "string ###prefix.key### not found"</returns>
|
||||||
|
public static string GetFormattedString(string prefix, Enum key, object param)
|
||||||
|
{
|
||||||
|
return GetFormattedString(prefix, key.ToString(), param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the resource for prefix.key, format with with string.format an supply the parameters
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>formatted resource or a "string ###prefix.key### not found"</returns>
|
||||||
|
public static string GetFormattedString(string prefix, string key, object param)
|
||||||
|
{
|
||||||
|
return GetFormattedString(prefix + "." + key, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the resource for key, format with with string.format an supply the parameters
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns>formatted resource or a "string ###key### not found"</returns>
|
||||||
|
public static string GetFormattedString(string key, object param)
|
||||||
|
{
|
||||||
|
string returnValue;
|
||||||
|
if (!resources.TryGetValue(key, out returnValue))
|
||||||
|
{
|
||||||
|
return "string ###" + key + "### not found";
|
||||||
|
}
|
||||||
|
return String.Format(returnValue, param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This class contains the information about a language file
|
||||||
|
/// </summary>
|
||||||
|
public class LanguageFile : IEquatable<LanguageFile>
|
||||||
|
{
|
||||||
|
public string Description
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Ietf
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Version Version
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string LanguageGroup
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Filepath
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Prefix
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Overload equals so we can delete a entry from a collection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool Equals(LanguageFile other)
|
||||||
|
{
|
||||||
|
if (Prefix != null)
|
||||||
|
{
|
||||||
|
if (!Prefix.Equals(other.Prefix))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (other.Prefix != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Ietf != null)
|
||||||
|
{
|
||||||
|
if (!Ietf.Equals(other.Ietf))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (other.Ietf != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Version != null)
|
||||||
|
{
|
||||||
|
if (!Version.Equals(other.Version))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (other.Version != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Filepath != null)
|
||||||
|
{
|
||||||
|
if (!Filepath.Equals(other.Filepath))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (other.Filepath != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
100
GreenshotImageEditor/Core/Objects.cs
Normal file
100
GreenshotImageEditor/Core/Objects.cs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
public static class Objects
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Perform a deep Copy of the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of object being copied.</typeparam>
|
||||||
|
/// <param name="source">The object instance to copy.</param>
|
||||||
|
/// <returns>The copied object.</returns>
|
||||||
|
public static T Clone<T>(this T source)
|
||||||
|
{
|
||||||
|
if (!typeof(T).IsSerializable)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The type must be serializable.", "source");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't serialize a null object, simply return the default for that object
|
||||||
|
if (ReferenceEquals(source, null))
|
||||||
|
{
|
||||||
|
return default(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
IFormatter formatter = new BinaryFormatter();
|
||||||
|
Stream stream = new MemoryStream();
|
||||||
|
using (stream)
|
||||||
|
{
|
||||||
|
formatter.Serialize(stream, source);
|
||||||
|
stream.Seek(0, SeekOrigin.Begin);
|
||||||
|
return (T)formatter.Deserialize(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CloneTo<T>(this T source, T destination)
|
||||||
|
{
|
||||||
|
Type type = typeof(T);
|
||||||
|
FieldInfo[] myObjectFields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
|
||||||
|
foreach (FieldInfo fi in myObjectFields)
|
||||||
|
{
|
||||||
|
fi.SetValue(destination, fi.GetValue(source));
|
||||||
|
}
|
||||||
|
PropertyInfo[] myObjectProperties = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
|
||||||
|
foreach (PropertyInfo pi in myObjectProperties)
|
||||||
|
{
|
||||||
|
if (pi.CanWrite)
|
||||||
|
{
|
||||||
|
pi.SetValue(destination, pi.GetValue(source, null), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CompareLists<T>(IList<T> l1, IList<T> l2)
|
||||||
|
{
|
||||||
|
if (l1.Count != l2.Count)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int matched = 0;
|
||||||
|
foreach (T item in l1)
|
||||||
|
{
|
||||||
|
if (!l2.Contains(item))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
matched++;
|
||||||
|
}
|
||||||
|
return matched == l1.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
770
GreenshotImageEditor/Core/QuantizerHelper.cs
Normal file
770
GreenshotImageEditor/Core/QuantizerHelper.cs
Normal file
|
@ -0,0 +1,770 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
internal class WuColorCube
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the red minimum.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The red minimum.</value>
|
||||||
|
public Int32 RedMinimum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the red maximum.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The red maximum.</value>
|
||||||
|
public Int32 RedMaximum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the green minimum.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The green minimum.</value>
|
||||||
|
public Int32 GreenMinimum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the green maximum.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The green maximum.</value>
|
||||||
|
public Int32 GreenMaximum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the blue minimum.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The blue minimum.</value>
|
||||||
|
public Int32 BlueMinimum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the blue maximum.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The blue maximum.</value>
|
||||||
|
public Int32 BlueMaximum { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the cube volume.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The volume.</value>
|
||||||
|
public Int32 Volume { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class WuQuantizer : IDisposable
|
||||||
|
{
|
||||||
|
private const Int32 MAXCOLOR = 512;
|
||||||
|
private const Int32 RED = 2;
|
||||||
|
private const Int32 GREEN = 1;
|
||||||
|
private const Int32 BLUE = 0;
|
||||||
|
private const Int32 SIDESIZE = 33;
|
||||||
|
private const Int32 MAXSIDEINDEX = 32;
|
||||||
|
private const Int32 MAXVOLUME = SIDESIZE * SIDESIZE * SIDESIZE;
|
||||||
|
|
||||||
|
// To count the colors
|
||||||
|
private int colorCount = 0;
|
||||||
|
|
||||||
|
private Int32[] reds;
|
||||||
|
private Int32[] greens;
|
||||||
|
private Int32[] blues;
|
||||||
|
private Int32[] sums;
|
||||||
|
|
||||||
|
private Int64[, ,] weights;
|
||||||
|
private Int64[, ,] momentsRed;
|
||||||
|
private Int64[, ,] momentsGreen;
|
||||||
|
private Int64[, ,] momentsBlue;
|
||||||
|
private Single[, ,] moments;
|
||||||
|
|
||||||
|
private byte[] tag;
|
||||||
|
|
||||||
|
private WuColorCube[] cubes;
|
||||||
|
private Bitmap sourceBitmap;
|
||||||
|
private Bitmap resultBitmap;
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (resultBitmap != null)
|
||||||
|
{
|
||||||
|
resultBitmap.Dispose();
|
||||||
|
resultBitmap = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// See <see cref="IColorQuantizer.Prepare"/> for more details.
|
||||||
|
/// </summary>
|
||||||
|
public WuQuantizer(Bitmap sourceBitmap)
|
||||||
|
{
|
||||||
|
this.sourceBitmap = sourceBitmap;
|
||||||
|
// Make sure the color count variables are reset
|
||||||
|
BitArray bitArray = new BitArray((int)Math.Pow(2, 24));
|
||||||
|
colorCount = 0;
|
||||||
|
|
||||||
|
// creates all the cubes
|
||||||
|
cubes = new WuColorCube[MAXCOLOR];
|
||||||
|
|
||||||
|
// initializes all the cubes
|
||||||
|
for (Int32 cubeIndex = 0; cubeIndex < MAXCOLOR; cubeIndex++)
|
||||||
|
{
|
||||||
|
cubes[cubeIndex] = new WuColorCube();
|
||||||
|
}
|
||||||
|
|
||||||
|
// resets the reference minimums
|
||||||
|
cubes[0].RedMinimum = 0;
|
||||||
|
cubes[0].GreenMinimum = 0;
|
||||||
|
cubes[0].BlueMinimum = 0;
|
||||||
|
|
||||||
|
// resets the reference maximums
|
||||||
|
cubes[0].RedMaximum = MAXSIDEINDEX;
|
||||||
|
cubes[0].GreenMaximum = MAXSIDEINDEX;
|
||||||
|
cubes[0].BlueMaximum = MAXSIDEINDEX;
|
||||||
|
|
||||||
|
weights = new Int64[SIDESIZE, SIDESIZE, SIDESIZE];
|
||||||
|
momentsRed = new Int64[SIDESIZE, SIDESIZE, SIDESIZE];
|
||||||
|
momentsGreen = new Int64[SIDESIZE, SIDESIZE, SIDESIZE];
|
||||||
|
momentsBlue = new Int64[SIDESIZE, SIDESIZE, SIDESIZE];
|
||||||
|
moments = new Single[SIDESIZE, SIDESIZE, SIDESIZE];
|
||||||
|
|
||||||
|
Int32[] table = new Int32[256];
|
||||||
|
|
||||||
|
for (Int32 tableIndex = 0; tableIndex < 256; ++tableIndex)
|
||||||
|
{
|
||||||
|
table[tableIndex] = tableIndex * tableIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a bitmap to store the initial match, which is just as good as an array and saves us 2x the storage
|
||||||
|
using (IFastBitmap sourceFastBitmap = FastBitmap.Create(sourceBitmap))
|
||||||
|
{
|
||||||
|
IFastBitmapWithBlend sourceFastBitmapWithBlend = sourceFastBitmap as IFastBitmapWithBlend;
|
||||||
|
sourceFastBitmap.Lock();
|
||||||
|
using (FastChunkyBitmap destinationFastBitmap = FastBitmap.CreateEmpty(sourceBitmap.Size, PixelFormat.Format8bppIndexed, Color.White) as FastChunkyBitmap)
|
||||||
|
{
|
||||||
|
destinationFastBitmap.Lock();
|
||||||
|
for (int y = 0; y < sourceFastBitmap.Height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < sourceFastBitmap.Width; x++)
|
||||||
|
{
|
||||||
|
Color color;
|
||||||
|
if (sourceFastBitmapWithBlend == null)
|
||||||
|
{
|
||||||
|
color = sourceFastBitmap.GetColorAt(x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = sourceFastBitmapWithBlend.GetBlendedColorAt(x, y);
|
||||||
|
}
|
||||||
|
// To count the colors
|
||||||
|
int index = color.ToArgb() & 0x00ffffff;
|
||||||
|
// Check if we already have this color
|
||||||
|
if (!bitArray.Get(index))
|
||||||
|
{
|
||||||
|
// If not, add 1 to the single colors
|
||||||
|
colorCount++;
|
||||||
|
bitArray.Set(index, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Int32 indexRed = (color.R >> 3) + 1;
|
||||||
|
Int32 indexGreen = (color.G >> 3) + 1;
|
||||||
|
Int32 indexBlue = (color.B >> 3) + 1;
|
||||||
|
|
||||||
|
weights[indexRed, indexGreen, indexBlue]++;
|
||||||
|
momentsRed[indexRed, indexGreen, indexBlue] += color.R;
|
||||||
|
momentsGreen[indexRed, indexGreen, indexBlue] += color.G;
|
||||||
|
momentsBlue[indexRed, indexGreen, indexBlue] += color.B;
|
||||||
|
moments[indexRed, indexGreen, indexBlue] += table[color.R] + table[color.G] + table[color.B];
|
||||||
|
|
||||||
|
// Store the initial "match"
|
||||||
|
Int32 paletteIndex = (indexRed << 10) + (indexRed << 6) + indexRed + (indexGreen << 5) + indexGreen + indexBlue;
|
||||||
|
destinationFastBitmap.SetColorIndexAt(x, y, (byte)(paletteIndex & 0xff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultBitmap = destinationFastBitmap.UnlockAndReturnBitmap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// See <see cref="IColorQuantizer.Prepare"/> for more details.
|
||||||
|
/// </summary>
|
||||||
|
public Int32 GetColorCount()
|
||||||
|
{
|
||||||
|
return colorCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reindex the 24/32 BPP (A)RGB image to a 8BPP
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Bitmap</returns>
|
||||||
|
public Bitmap SimpleReindex()
|
||||||
|
{
|
||||||
|
List<Color> colors = new List<Color>();
|
||||||
|
Dictionary<Color, byte> lookup = new Dictionary<Color, byte>();
|
||||||
|
using (FastChunkyBitmap bbbDest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap)
|
||||||
|
{
|
||||||
|
bbbDest.Lock();
|
||||||
|
using (IFastBitmap bbbSrc = FastBitmap.Create(sourceBitmap))
|
||||||
|
{
|
||||||
|
IFastBitmapWithBlend bbbSrcBlend = bbbSrc as IFastBitmapWithBlend;
|
||||||
|
|
||||||
|
bbbSrc.Lock();
|
||||||
|
byte index;
|
||||||
|
for (int y = 0; y < bbbSrc.Height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < bbbSrc.Width; x++)
|
||||||
|
{
|
||||||
|
Color color;
|
||||||
|
if (bbbSrcBlend != null)
|
||||||
|
{
|
||||||
|
color = bbbSrcBlend.GetBlendedColorAt(x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = bbbSrc.GetColorAt(x, y);
|
||||||
|
}
|
||||||
|
if (lookup.ContainsKey(color))
|
||||||
|
{
|
||||||
|
index = lookup[color];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colors.Add(color);
|
||||||
|
index = (byte)(colors.Count - 1);
|
||||||
|
lookup.Add(color, index);
|
||||||
|
}
|
||||||
|
bbbDest.SetColorIndexAt(x, y, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generates palette
|
||||||
|
ColorPalette imagePalette = resultBitmap.Palette;
|
||||||
|
Color[] entries = imagePalette.Entries;
|
||||||
|
for (Int32 paletteIndex = 0; paletteIndex < 256; paletteIndex++)
|
||||||
|
{
|
||||||
|
if (paletteIndex < colorCount)
|
||||||
|
{
|
||||||
|
entries[paletteIndex] = colors[paletteIndex];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entries[paletteIndex] = Color.Black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultBitmap.Palette = imagePalette;
|
||||||
|
|
||||||
|
// Make sure the bitmap is not disposed, as we return it.
|
||||||
|
Bitmap tmpBitmap = resultBitmap;
|
||||||
|
resultBitmap = null;
|
||||||
|
return tmpBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the image
|
||||||
|
/// </summary>
|
||||||
|
public Bitmap GetQuantizedImage(int allowedColorCount)
|
||||||
|
{
|
||||||
|
if (allowedColorCount > 256)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("Quantizing muss be done to get less than 256 colors");
|
||||||
|
}
|
||||||
|
if (colorCount < allowedColorCount)
|
||||||
|
{
|
||||||
|
// Simple logic to reduce to 8 bit
|
||||||
|
LOG.Info("Colors in the image are already less as whished for, using simple copy to indexed image, no quantizing needed!");
|
||||||
|
return SimpleReindex();
|
||||||
|
}
|
||||||
|
// preprocess the colors
|
||||||
|
CalculateMoments();
|
||||||
|
LOG.Info("Calculated the moments...");
|
||||||
|
Int32 next = 0;
|
||||||
|
Single[] volumeVariance = new Single[MAXCOLOR];
|
||||||
|
|
||||||
|
// processes the cubes
|
||||||
|
for (Int32 cubeIndex = 1; cubeIndex < allowedColorCount; ++cubeIndex)
|
||||||
|
{
|
||||||
|
// if cut is possible; make it
|
||||||
|
if (Cut(cubes[next], cubes[cubeIndex]))
|
||||||
|
{
|
||||||
|
volumeVariance[next] = cubes[next].Volume > 1 ? CalculateVariance(cubes[next]) : 0.0f;
|
||||||
|
volumeVariance[cubeIndex] = cubes[cubeIndex].Volume > 1 ? CalculateVariance(cubes[cubeIndex]) : 0.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the cut was not possible, revert the index
|
||||||
|
volumeVariance[next] = 0.0f;
|
||||||
|
cubeIndex--;
|
||||||
|
}
|
||||||
|
|
||||||
|
next = 0;
|
||||||
|
Single temp = volumeVariance[0];
|
||||||
|
|
||||||
|
for (Int32 index = 1; index <= cubeIndex; ++index)
|
||||||
|
{
|
||||||
|
if (volumeVariance[index] > temp)
|
||||||
|
{
|
||||||
|
temp = volumeVariance[index];
|
||||||
|
next = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (temp <= 0.0)
|
||||||
|
{
|
||||||
|
allowedColorCount = cubeIndex + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Int32[] lookupRed = new Int32[MAXCOLOR];
|
||||||
|
Int32[] lookupGreen = new Int32[MAXCOLOR];
|
||||||
|
Int32[] lookupBlue = new Int32[MAXCOLOR];
|
||||||
|
|
||||||
|
tag = new byte[MAXVOLUME];
|
||||||
|
|
||||||
|
// precalculates lookup tables
|
||||||
|
for (int k = 0; k < allowedColorCount; ++k)
|
||||||
|
{
|
||||||
|
Mark(cubes[k], k, tag);
|
||||||
|
|
||||||
|
long weight = Volume(cubes[k], weights);
|
||||||
|
|
||||||
|
if (weight > 0)
|
||||||
|
{
|
||||||
|
lookupRed[k] = (int)(Volume(cubes[k], momentsRed) / weight);
|
||||||
|
lookupGreen[k] = (int)(Volume(cubes[k], momentsGreen) / weight);
|
||||||
|
lookupBlue[k] = (int)(Volume(cubes[k], momentsBlue) / weight);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lookupRed[k] = 0;
|
||||||
|
lookupGreen[k] = 0;
|
||||||
|
lookupBlue[k] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reds = new Int32[allowedColorCount + 1];
|
||||||
|
greens = new Int32[allowedColorCount + 1];
|
||||||
|
blues = new Int32[allowedColorCount + 1];
|
||||||
|
sums = new Int32[allowedColorCount + 1];
|
||||||
|
|
||||||
|
LOG.Info("Starting bitmap reconstruction...");
|
||||||
|
|
||||||
|
using (FastChunkyBitmap dest = FastBitmap.Create(resultBitmap) as FastChunkyBitmap)
|
||||||
|
{
|
||||||
|
using (IFastBitmap src = FastBitmap.Create(sourceBitmap))
|
||||||
|
{
|
||||||
|
IFastBitmapWithBlend srcBlend = src as IFastBitmapWithBlend;
|
||||||
|
Dictionary<Color, byte> lookup = new Dictionary<Color, byte>();
|
||||||
|
byte bestMatch;
|
||||||
|
for (int y = 0; y < src.Height; y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < src.Width; x++)
|
||||||
|
{
|
||||||
|
Color color;
|
||||||
|
if (srcBlend != null)
|
||||||
|
{
|
||||||
|
// WithoutAlpha, this makes it possible to ignore the alpha
|
||||||
|
color = srcBlend.GetBlendedColorAt(x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
color = src.GetColorAt(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we already matched the color
|
||||||
|
if (!lookup.ContainsKey(color))
|
||||||
|
{
|
||||||
|
// If not we need to find the best match
|
||||||
|
|
||||||
|
// First get initial match
|
||||||
|
bestMatch = dest.GetColorIndexAt(x, y);
|
||||||
|
bestMatch = tag[bestMatch];
|
||||||
|
|
||||||
|
Int32 bestDistance = 100000000;
|
||||||
|
for (int lookupIndex = 0; lookupIndex < allowedColorCount; lookupIndex++)
|
||||||
|
{
|
||||||
|
Int32 foundRed = lookupRed[lookupIndex];
|
||||||
|
Int32 foundGreen = lookupGreen[lookupIndex];
|
||||||
|
Int32 foundBlue = lookupBlue[lookupIndex];
|
||||||
|
Int32 deltaRed = color.R - foundRed;
|
||||||
|
Int32 deltaGreen = color.G - foundGreen;
|
||||||
|
Int32 deltaBlue = color.B - foundBlue;
|
||||||
|
|
||||||
|
Int32 distance = deltaRed * deltaRed + deltaGreen * deltaGreen + deltaBlue * deltaBlue;
|
||||||
|
|
||||||
|
if (distance < bestDistance)
|
||||||
|
{
|
||||||
|
bestDistance = distance;
|
||||||
|
bestMatch = (byte)lookupIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lookup.Add(color, bestMatch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Already matched, so we just use the lookup
|
||||||
|
bestMatch = lookup[color];
|
||||||
|
}
|
||||||
|
|
||||||
|
reds[bestMatch] += color.R;
|
||||||
|
greens[bestMatch] += color.G;
|
||||||
|
blues[bestMatch] += color.B;
|
||||||
|
sums[bestMatch]++;
|
||||||
|
|
||||||
|
dest.SetColorIndexAt(x, y, bestMatch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generates palette
|
||||||
|
ColorPalette imagePalette = resultBitmap.Palette;
|
||||||
|
Color[] entries = imagePalette.Entries;
|
||||||
|
for (Int32 paletteIndex = 0; paletteIndex < allowedColorCount; paletteIndex++)
|
||||||
|
{
|
||||||
|
if (sums[paletteIndex] > 0)
|
||||||
|
{
|
||||||
|
reds[paletteIndex] /= sums[paletteIndex];
|
||||||
|
greens[paletteIndex] /= sums[paletteIndex];
|
||||||
|
blues[paletteIndex] /= sums[paletteIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
entries[paletteIndex] = Color.FromArgb(255, reds[paletteIndex], greens[paletteIndex], blues[paletteIndex]);
|
||||||
|
}
|
||||||
|
resultBitmap.Palette = imagePalette;
|
||||||
|
|
||||||
|
// Make sure the bitmap is not disposed, as we return it.
|
||||||
|
Bitmap tmpBitmap = resultBitmap;
|
||||||
|
resultBitmap = null;
|
||||||
|
return tmpBitmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the histogram to a series of moments.
|
||||||
|
/// </summary>
|
||||||
|
private void CalculateMoments()
|
||||||
|
{
|
||||||
|
Int64[] area = new Int64[SIDESIZE];
|
||||||
|
Int64[] areaRed = new Int64[SIDESIZE];
|
||||||
|
Int64[] areaGreen = new Int64[SIDESIZE];
|
||||||
|
Int64[] areaBlue = new Int64[SIDESIZE];
|
||||||
|
Single[] area2 = new Single[SIDESIZE];
|
||||||
|
|
||||||
|
for (Int32 redIndex = 1; redIndex <= MAXSIDEINDEX; ++redIndex)
|
||||||
|
{
|
||||||
|
for (Int32 index = 0; index <= MAXSIDEINDEX; ++index)
|
||||||
|
{
|
||||||
|
area[index] = 0;
|
||||||
|
areaRed[index] = 0;
|
||||||
|
areaGreen[index] = 0;
|
||||||
|
areaBlue[index] = 0;
|
||||||
|
area2[index] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Int32 greenIndex = 1; greenIndex <= MAXSIDEINDEX; ++greenIndex)
|
||||||
|
{
|
||||||
|
Int64 line = 0;
|
||||||
|
Int64 lineRed = 0;
|
||||||
|
Int64 lineGreen = 0;
|
||||||
|
Int64 lineBlue = 0;
|
||||||
|
Single line2 = 0.0f;
|
||||||
|
|
||||||
|
for (Int32 blueIndex = 1; blueIndex <= MAXSIDEINDEX; ++blueIndex)
|
||||||
|
{
|
||||||
|
line += weights[redIndex, greenIndex, blueIndex];
|
||||||
|
lineRed += momentsRed[redIndex, greenIndex, blueIndex];
|
||||||
|
lineGreen += momentsGreen[redIndex, greenIndex, blueIndex];
|
||||||
|
lineBlue += momentsBlue[redIndex, greenIndex, blueIndex];
|
||||||
|
line2 += moments[redIndex, greenIndex, blueIndex];
|
||||||
|
|
||||||
|
area[blueIndex] += line;
|
||||||
|
areaRed[blueIndex] += lineRed;
|
||||||
|
areaGreen[blueIndex] += lineGreen;
|
||||||
|
areaBlue[blueIndex] += lineBlue;
|
||||||
|
area2[blueIndex] += line2;
|
||||||
|
|
||||||
|
weights[redIndex, greenIndex, blueIndex] = weights[redIndex - 1, greenIndex, blueIndex] + area[blueIndex];
|
||||||
|
momentsRed[redIndex, greenIndex, blueIndex] = momentsRed[redIndex - 1, greenIndex, blueIndex] + areaRed[blueIndex];
|
||||||
|
momentsGreen[redIndex, greenIndex, blueIndex] = momentsGreen[redIndex - 1, greenIndex, blueIndex] + areaGreen[blueIndex];
|
||||||
|
momentsBlue[redIndex, greenIndex, blueIndex] = momentsBlue[redIndex - 1, greenIndex, blueIndex] + areaBlue[blueIndex];
|
||||||
|
moments[redIndex, greenIndex, blueIndex] = moments[redIndex - 1, greenIndex, blueIndex] + area2[blueIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the volume of the cube in a specific moment.
|
||||||
|
/// </summary>
|
||||||
|
private static Int64 Volume(WuColorCube cube, Int64[, ,] moment)
|
||||||
|
{
|
||||||
|
return moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMaximum] -
|
||||||
|
moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] -
|
||||||
|
moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] +
|
||||||
|
moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the volume of the cube in a specific moment. For the floating-point values.
|
||||||
|
/// </summary>
|
||||||
|
private static Single VolumeFloat(WuColorCube cube, Single[, ,] moment)
|
||||||
|
{
|
||||||
|
return moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMaximum] -
|
||||||
|
moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] -
|
||||||
|
moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] +
|
||||||
|
moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits the cube in given position, and color direction.
|
||||||
|
/// </summary>
|
||||||
|
private static Int64 Top(WuColorCube cube, Int32 direction, Int32 position, Int64[, ,] moment)
|
||||||
|
{
|
||||||
|
switch (direction)
|
||||||
|
{
|
||||||
|
case RED:
|
||||||
|
return (moment[position, cube.GreenMaximum, cube.BlueMaximum] -
|
||||||
|
moment[position, cube.GreenMaximum, cube.BlueMinimum] -
|
||||||
|
moment[position, cube.GreenMinimum, cube.BlueMaximum] +
|
||||||
|
moment[position, cube.GreenMinimum, cube.BlueMinimum]);
|
||||||
|
|
||||||
|
case GREEN:
|
||||||
|
return (moment[cube.RedMaximum, position, cube.BlueMaximum] -
|
||||||
|
moment[cube.RedMaximum, position, cube.BlueMinimum] -
|
||||||
|
moment[cube.RedMinimum, position, cube.BlueMaximum] +
|
||||||
|
moment[cube.RedMinimum, position, cube.BlueMinimum]);
|
||||||
|
|
||||||
|
case BLUE:
|
||||||
|
return (moment[cube.RedMaximum, cube.GreenMaximum, position] -
|
||||||
|
moment[cube.RedMaximum, cube.GreenMinimum, position] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMaximum, position] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, position]);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits the cube in a given color direction at its minimum.
|
||||||
|
/// </summary>
|
||||||
|
private static Int64 Bottom(WuColorCube cube, Int32 direction, Int64[, ,] moment)
|
||||||
|
{
|
||||||
|
switch (direction)
|
||||||
|
{
|
||||||
|
case RED:
|
||||||
|
return (-moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMaximum] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]);
|
||||||
|
|
||||||
|
case GREEN:
|
||||||
|
return (-moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMaximum] +
|
||||||
|
moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMaximum] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]);
|
||||||
|
|
||||||
|
case BLUE:
|
||||||
|
return (-moment[cube.RedMaximum, cube.GreenMaximum, cube.BlueMinimum] +
|
||||||
|
moment[cube.RedMaximum, cube.GreenMinimum, cube.BlueMinimum] +
|
||||||
|
moment[cube.RedMinimum, cube.GreenMaximum, cube.BlueMinimum] -
|
||||||
|
moment[cube.RedMinimum, cube.GreenMinimum, cube.BlueMinimum]);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculates statistical variance for a given cube.
|
||||||
|
/// </summary>
|
||||||
|
private Single CalculateVariance(WuColorCube cube)
|
||||||
|
{
|
||||||
|
Single volumeRed = Volume(cube, momentsRed);
|
||||||
|
Single volumeGreen = Volume(cube, momentsGreen);
|
||||||
|
Single volumeBlue = Volume(cube, momentsBlue);
|
||||||
|
Single volumeMoment = VolumeFloat(cube, moments);
|
||||||
|
Single volumeWeight = Volume(cube, weights);
|
||||||
|
|
||||||
|
Single distance = volumeRed * volumeRed + volumeGreen * volumeGreen + volumeBlue * volumeBlue;
|
||||||
|
|
||||||
|
return volumeMoment - (distance / volumeWeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the optimal (maximal) position for the cut.
|
||||||
|
/// </summary>
|
||||||
|
private Single Maximize(WuColorCube cube, Int32 direction, Int32 first, Int32 last, Int32[] cut, Int64 wholeRed, Int64 wholeGreen, Int64 wholeBlue, Int64 wholeWeight)
|
||||||
|
{
|
||||||
|
Int64 bottomRed = Bottom(cube, direction, momentsRed);
|
||||||
|
Int64 bottomGreen = Bottom(cube, direction, momentsGreen);
|
||||||
|
Int64 bottomBlue = Bottom(cube, direction, momentsBlue);
|
||||||
|
Int64 bottomWeight = Bottom(cube, direction, weights);
|
||||||
|
|
||||||
|
Single result = 0.0f;
|
||||||
|
cut[0] = -1;
|
||||||
|
|
||||||
|
for (Int32 position = first; position < last; ++position)
|
||||||
|
{
|
||||||
|
// determines the cube cut at a certain position
|
||||||
|
Int64 halfRed = bottomRed + Top(cube, direction, position, momentsRed);
|
||||||
|
Int64 halfGreen = bottomGreen + Top(cube, direction, position, momentsGreen);
|
||||||
|
Int64 halfBlue = bottomBlue + Top(cube, direction, position, momentsBlue);
|
||||||
|
Int64 halfWeight = bottomWeight + Top(cube, direction, position, weights);
|
||||||
|
|
||||||
|
// the cube cannot be cut at bottom (this would lead to empty cube)
|
||||||
|
if (halfWeight != 0)
|
||||||
|
{
|
||||||
|
Single halfDistance = halfRed * halfRed + halfGreen * halfGreen + halfBlue * halfBlue;
|
||||||
|
Single temp = halfDistance / halfWeight;
|
||||||
|
|
||||||
|
halfRed = wholeRed - halfRed;
|
||||||
|
halfGreen = wholeGreen - halfGreen;
|
||||||
|
halfBlue = wholeBlue - halfBlue;
|
||||||
|
halfWeight = wholeWeight - halfWeight;
|
||||||
|
|
||||||
|
if (halfWeight != 0)
|
||||||
|
{
|
||||||
|
halfDistance = halfRed * halfRed + halfGreen * halfGreen + halfBlue * halfBlue;
|
||||||
|
temp += halfDistance / halfWeight;
|
||||||
|
|
||||||
|
if (temp > result)
|
||||||
|
{
|
||||||
|
result = temp;
|
||||||
|
cut[0] = position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cuts a cube with another one.
|
||||||
|
/// </summary>
|
||||||
|
private Boolean Cut(WuColorCube first, WuColorCube second)
|
||||||
|
{
|
||||||
|
Int32 direction;
|
||||||
|
|
||||||
|
Int32[] cutRed = { 0 };
|
||||||
|
Int32[] cutGreen = { 0 };
|
||||||
|
Int32[] cutBlue = { 0 };
|
||||||
|
|
||||||
|
Int64 wholeRed = Volume(first, momentsRed);
|
||||||
|
Int64 wholeGreen = Volume(first, momentsGreen);
|
||||||
|
Int64 wholeBlue = Volume(first, momentsBlue);
|
||||||
|
Int64 wholeWeight = Volume(first, weights);
|
||||||
|
|
||||||
|
Single maxRed = Maximize(first, RED, first.RedMinimum + 1, first.RedMaximum, cutRed, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
||||||
|
Single maxGreen = Maximize(first, GREEN, first.GreenMinimum + 1, first.GreenMaximum, cutGreen, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
||||||
|
Single maxBlue = Maximize(first, BLUE, first.BlueMinimum + 1, first.BlueMaximum, cutBlue, wholeRed, wholeGreen, wholeBlue, wholeWeight);
|
||||||
|
|
||||||
|
if ((maxRed >= maxGreen) && (maxRed >= maxBlue))
|
||||||
|
{
|
||||||
|
direction = RED;
|
||||||
|
|
||||||
|
// cannot split empty cube
|
||||||
|
if (cutRed[0] < 0) return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((maxGreen >= maxRed) && (maxGreen >= maxBlue))
|
||||||
|
{
|
||||||
|
direction = GREEN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
direction = BLUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
second.RedMaximum = first.RedMaximum;
|
||||||
|
second.GreenMaximum = first.GreenMaximum;
|
||||||
|
second.BlueMaximum = first.BlueMaximum;
|
||||||
|
|
||||||
|
// cuts in a certain direction
|
||||||
|
switch (direction)
|
||||||
|
{
|
||||||
|
case RED:
|
||||||
|
second.RedMinimum = first.RedMaximum = cutRed[0];
|
||||||
|
second.GreenMinimum = first.GreenMinimum;
|
||||||
|
second.BlueMinimum = first.BlueMinimum;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GREEN:
|
||||||
|
second.GreenMinimum = first.GreenMaximum = cutGreen[0];
|
||||||
|
second.RedMinimum = first.RedMinimum;
|
||||||
|
second.BlueMinimum = first.BlueMinimum;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BLUE:
|
||||||
|
second.BlueMinimum = first.BlueMaximum = cutBlue[0];
|
||||||
|
second.RedMinimum = first.RedMinimum;
|
||||||
|
second.GreenMinimum = first.GreenMinimum;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// determines the volumes after cut
|
||||||
|
first.Volume = (first.RedMaximum - first.RedMinimum) * (first.GreenMaximum - first.GreenMinimum) * (first.BlueMaximum - first.BlueMinimum);
|
||||||
|
second.Volume = (second.RedMaximum - second.RedMinimum) * (second.GreenMaximum - second.GreenMinimum) * (second.BlueMaximum - second.BlueMinimum);
|
||||||
|
|
||||||
|
// the cut was successfull
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Marks all the tags with a given label.
|
||||||
|
/// </summary>
|
||||||
|
private void Mark(WuColorCube cube, Int32 label, byte[] tag)
|
||||||
|
{
|
||||||
|
for (Int32 redIndex = cube.RedMinimum + 1; redIndex <= cube.RedMaximum; ++redIndex)
|
||||||
|
{
|
||||||
|
for (Int32 greenIndex = cube.GreenMinimum + 1; greenIndex <= cube.GreenMaximum; ++greenIndex)
|
||||||
|
{
|
||||||
|
for (Int32 blueIndex = cube.BlueMinimum + 1; blueIndex <= cube.BlueMaximum; ++blueIndex)
|
||||||
|
{
|
||||||
|
tag[(redIndex << 10) + (redIndex << 6) + redIndex + (greenIndex << 5) + greenIndex + blueIndex] = (byte)label;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
906
GreenshotImageEditor/Core/WindowCapture.cs
Normal file
906
GreenshotImageEditor/Core/WindowCapture.cs
Normal file
|
@ -0,0 +1,906 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using Greenshot.Plugin;
|
||||||
|
using GreenshotPlugin.UnmanagedHelpers;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace GreenshotPlugin.Core
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This Class is used to pass details about the capture around.
|
||||||
|
/// The time the Capture was taken and the Title of the window (or a region of) that is captured
|
||||||
|
/// </summary>
|
||||||
|
public class CaptureDetails : ICaptureDetails
|
||||||
|
{
|
||||||
|
private string title;
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get { return title; }
|
||||||
|
set { title = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private string filename;
|
||||||
|
public string Filename
|
||||||
|
{
|
||||||
|
get { return filename; }
|
||||||
|
set { filename = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime dateTime;
|
||||||
|
public DateTime DateTime
|
||||||
|
{
|
||||||
|
get { return dateTime; }
|
||||||
|
set { dateTime = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private float dpiX;
|
||||||
|
public float DpiX
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return dpiX;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
dpiX = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float dpiY;
|
||||||
|
public float DpiY
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return dpiY;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
dpiY = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Dictionary<string, string> metaData = new Dictionary<string, string>();
|
||||||
|
public Dictionary<string, string> MetaData
|
||||||
|
{
|
||||||
|
get { return metaData; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMetaData(string key, string value)
|
||||||
|
{
|
||||||
|
if (metaData.ContainsKey(key))
|
||||||
|
{
|
||||||
|
metaData[key] = value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
metaData.Add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CaptureMode captureMode;
|
||||||
|
public CaptureMode CaptureMode
|
||||||
|
{
|
||||||
|
get { return captureMode; }
|
||||||
|
set { captureMode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<IDestination> captureDestinations = new List<IDestination>();
|
||||||
|
public List<IDestination> CaptureDestinations
|
||||||
|
{
|
||||||
|
get { return captureDestinations; }
|
||||||
|
set { captureDestinations = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearDestinations()
|
||||||
|
{
|
||||||
|
captureDestinations.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveDestination(IDestination destination)
|
||||||
|
{
|
||||||
|
if (captureDestinations.Contains(destination))
|
||||||
|
{
|
||||||
|
captureDestinations.Remove(destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddDestination(IDestination captureDestination)
|
||||||
|
{
|
||||||
|
if (!captureDestinations.Contains(captureDestination))
|
||||||
|
{
|
||||||
|
captureDestinations.Add(captureDestination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasDestination(string designation)
|
||||||
|
{
|
||||||
|
foreach (IDestination destination in captureDestinations)
|
||||||
|
{
|
||||||
|
if (designation.Equals(destination.Designation))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CaptureDetails()
|
||||||
|
{
|
||||||
|
dateTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This class is used to pass an instance of the "Capture" around
|
||||||
|
/// Having the Bitmap, eventually the Windows Title and cursor all together.
|
||||||
|
/// </summary>
|
||||||
|
public class Capture : IDisposable, ICapture
|
||||||
|
{
|
||||||
|
private List<ICaptureElement> elements = new List<ICaptureElement>();
|
||||||
|
|
||||||
|
private Rectangle screenBounds;
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the Screenbounds
|
||||||
|
/// </summary>
|
||||||
|
public Rectangle ScreenBounds
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (screenBounds == null)
|
||||||
|
{
|
||||||
|
screenBounds = WindowCapture.GetScreenBounds();
|
||||||
|
}
|
||||||
|
return screenBounds;
|
||||||
|
}
|
||||||
|
set { screenBounds = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Image image;
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the Image
|
||||||
|
/// </summary>
|
||||||
|
public Image Image
|
||||||
|
{
|
||||||
|
get { return image; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (image != null)
|
||||||
|
{
|
||||||
|
image.Dispose();
|
||||||
|
}
|
||||||
|
image = value;
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
if (value.PixelFormat.Equals(PixelFormat.Format8bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format1bppIndexed) || value.PixelFormat.Equals(PixelFormat.Format4bppIndexed))
|
||||||
|
{
|
||||||
|
LOG.Debug("Converting Bitmap to PixelFormat.Format32bppArgb as we don't support: " + value.PixelFormat);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Default Bitmap PixelFormat is Format32bppArgb
|
||||||
|
image = new Bitmap(value);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Always dispose, even when a exception occured
|
||||||
|
value.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.DebugFormat("Image is set with the following specifications: {0} - {1}", image.Size, image.PixelFormat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.Debug("Image is removed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NullImage()
|
||||||
|
{
|
||||||
|
image = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Icon cursor;
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the image for the Cursor
|
||||||
|
/// </summary>
|
||||||
|
public Icon Cursor
|
||||||
|
{
|
||||||
|
get { return cursor; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (cursor != null)
|
||||||
|
{
|
||||||
|
cursor.Dispose();
|
||||||
|
}
|
||||||
|
cursor = (Icon)value.Clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool cursorVisible = false;
|
||||||
|
/// <summary>
|
||||||
|
/// Set if the cursor is visible
|
||||||
|
/// </summary>
|
||||||
|
public bool CursorVisible
|
||||||
|
{
|
||||||
|
get { return cursorVisible; }
|
||||||
|
set { cursorVisible = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point cursorLocation = Point.Empty;
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the CursorLocation
|
||||||
|
/// </summary>
|
||||||
|
public Point CursorLocation
|
||||||
|
{
|
||||||
|
get { return cursorLocation; }
|
||||||
|
set { cursorLocation = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point location = Point.Empty;
|
||||||
|
/// <summary>
|
||||||
|
/// Get/set the Location
|
||||||
|
/// </summary>
|
||||||
|
public Point Location
|
||||||
|
{
|
||||||
|
get { return location; }
|
||||||
|
set { location = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private CaptureDetails captureDetails;
|
||||||
|
/// <summary>
|
||||||
|
/// Get/set the CaptureDetails
|
||||||
|
/// </summary>
|
||||||
|
public ICaptureDetails CaptureDetails
|
||||||
|
{
|
||||||
|
get { return captureDetails; }
|
||||||
|
set { captureDetails = (CaptureDetails)value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default Constructor
|
||||||
|
/// </summary>
|
||||||
|
public Capture()
|
||||||
|
{
|
||||||
|
screenBounds = WindowCapture.GetScreenBounds();
|
||||||
|
captureDetails = new CaptureDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor with Image
|
||||||
|
/// Note: the supplied bitmap can be disposed immediately or when constructor is called.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newImage">Image</param>
|
||||||
|
public Capture(Image newImage)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
Image = newImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Destructor
|
||||||
|
/// </summary>
|
||||||
|
~Capture()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The public accessible Dispose
|
||||||
|
/// Will call the GarbageCollector to SuppressFinalize, preventing being cleaned twice
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This Dispose is called from the Dispose and the Destructor.
|
||||||
|
/// When disposing==true all non-managed resources should be freed too!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing"></param>
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (image != null)
|
||||||
|
{
|
||||||
|
image.Dispose();
|
||||||
|
}
|
||||||
|
if (cursor != null)
|
||||||
|
{
|
||||||
|
cursor.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
image = null;
|
||||||
|
cursor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Crops the capture to the specified rectangle (with Bitmap coordinates!)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cropRectangle">Rectangle with bitmap coordinates</param>
|
||||||
|
public bool Crop(Rectangle cropRectangle)
|
||||||
|
{
|
||||||
|
LOG.Debug("Cropping to: " + cropRectangle.ToString());
|
||||||
|
if (ImageHelper.Crop(ref image, ref cropRectangle))
|
||||||
|
{
|
||||||
|
location = cropRectangle.Location;
|
||||||
|
// Change mouse location according to the cropRegtangle (including screenbounds) offset
|
||||||
|
MoveMouseLocation(-cropRectangle.Location.X, -cropRectangle.Location.Y);
|
||||||
|
// Move all the elements
|
||||||
|
// TODO: Enable when the elements are usable again.
|
||||||
|
// MoveElements(-cropRectangle.Location.X, -cropRectangle.Location.Y);
|
||||||
|
|
||||||
|
// Remove invisible elements
|
||||||
|
List<ICaptureElement> newElements = new List<ICaptureElement>();
|
||||||
|
foreach (ICaptureElement captureElement in elements)
|
||||||
|
{
|
||||||
|
if (captureElement.Bounds.IntersectsWith(cropRectangle))
|
||||||
|
{
|
||||||
|
newElements.Add(captureElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elements = newElements;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Apply a translate to the mouse location.
|
||||||
|
/// e.g. needed for crop
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">x coordinates to move the mouse</param>
|
||||||
|
/// <param name="y">y coordinates to move the mouse</param>
|
||||||
|
public void MoveMouseLocation(int x, int y)
|
||||||
|
{
|
||||||
|
cursorLocation.Offset(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Enable when the elements are usable again.
|
||||||
|
///// <summary>
|
||||||
|
///// Apply a translate to the elements
|
||||||
|
///// e.g. needed for crop
|
||||||
|
///// </summary>
|
||||||
|
///// <param name="x">x coordinates to move the elements</param>
|
||||||
|
///// <param name="y">y coordinates to move the elements</param>
|
||||||
|
//public void MoveElements(int x, int y) {
|
||||||
|
// MoveElements(elements, x, y);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//private void MoveElements(List<ICaptureElement> listOfElements, int x, int y) {
|
||||||
|
// foreach(ICaptureElement childElement in listOfElements) {
|
||||||
|
// Rectangle bounds = childElement.Bounds;
|
||||||
|
// bounds.Offset(x, y);
|
||||||
|
// childElement.Bounds = bounds;
|
||||||
|
// MoveElements(childElement.Children, x, y);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// Add a new element to the capture
|
||||||
|
///// </summary>
|
||||||
|
///// <param name="element">CaptureElement</param>
|
||||||
|
//public void AddElement(ICaptureElement element) {
|
||||||
|
// int match = elements.IndexOf(element);
|
||||||
|
// if (match >= 0) {
|
||||||
|
// if (elements[match].Children.Count < element.Children.Count) {
|
||||||
|
// elements.RemoveAt(match);
|
||||||
|
// elements.Add(element);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// elements.Add(element);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// Returns a list of rectangles which represent object that are on the capture
|
||||||
|
///// </summary>
|
||||||
|
//public List<ICaptureElement> Elements {
|
||||||
|
// get {
|
||||||
|
// return elements;
|
||||||
|
// }
|
||||||
|
// set {
|
||||||
|
// elements = value;
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A class representing an element in the capture
|
||||||
|
/// </summary>
|
||||||
|
public class CaptureElement : ICaptureElement
|
||||||
|
{
|
||||||
|
public CaptureElement(Rectangle bounds)
|
||||||
|
{
|
||||||
|
Bounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CaptureElement(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CaptureElement(string name, Rectangle bounds)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Bounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ICaptureElement> children = new List<ICaptureElement>();
|
||||||
|
public List<ICaptureElement> Children
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
children = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
public Rectangle Bounds
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CaptureElements are regarded equal if their bounds are equal. this should be sufficient.
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
if (obj != null && GetType().Equals(obj.GetType()))
|
||||||
|
{
|
||||||
|
CaptureElement other = obj as CaptureElement;
|
||||||
|
if (Bounds.Equals(other.Bounds))
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Bounds.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Window Capture code
|
||||||
|
/// </summary>
|
||||||
|
public class WindowCapture
|
||||||
|
{
|
||||||
|
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to cleanup the unmanged resource in the iconInfo for the CaptureCursor method
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hObject"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[DllImport("gdi32", SetLastError = true)]
|
||||||
|
private static extern bool DeleteObject(IntPtr hObject);
|
||||||
|
|
||||||
|
private WindowCapture()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the bounds of all screens combined.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A Rectangle of the bounds of the entire display area.</returns>
|
||||||
|
public static Rectangle GetScreenBounds()
|
||||||
|
{
|
||||||
|
int left = 0, top = 0, bottom = 0, right = 0;
|
||||||
|
foreach (Screen screen in Screen.AllScreens)
|
||||||
|
{
|
||||||
|
left = Math.Min(left, screen.Bounds.X);
|
||||||
|
top = Math.Min(top, screen.Bounds.Y);
|
||||||
|
int screenAbsRight = screen.Bounds.X + screen.Bounds.Width;
|
||||||
|
int screenAbsBottom = screen.Bounds.Y + screen.Bounds.Height;
|
||||||
|
right = Math.Max(right, screenAbsRight);
|
||||||
|
bottom = Math.Max(bottom, screenAbsBottom);
|
||||||
|
}
|
||||||
|
return new Rectangle(left, top, (right + Math.Abs(left)), (bottom + Math.Abs(top)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7.
|
||||||
|
/// <returns>Point with cursor location, relative to the origin of the monitor setup (i.e. negative coordinates are
|
||||||
|
/// possible in multiscreen setups)</returns>
|
||||||
|
public static Point GetCursorLocation()
|
||||||
|
{
|
||||||
|
if (Environment.OSVersion.Version.Major >= 6)
|
||||||
|
{
|
||||||
|
POINT cursorLocation;
|
||||||
|
if (User32.GetPhysicalCursorPos(out cursorLocation))
|
||||||
|
{
|
||||||
|
return new Point(cursorLocation.X, cursorLocation.Y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Win32Error error = Win32.GetLastErrorCode();
|
||||||
|
LOG.ErrorFormat("Error retrieving PhysicalCursorPos : {0}", Win32.GetMessage(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Point(Cursor.Position.X, Cursor.Position.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the cursor location safely, accounting for DPI settings in Vista/Windows 7. This implementation
|
||||||
|
/// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap.
|
||||||
|
/// <returns>Point with cursor location, relative to the top left corner of the monitor setup (which itself might
|
||||||
|
/// actually not be on any screen)</returns>
|
||||||
|
public static Point GetCursorLocationRelativeToScreenBounds()
|
||||||
|
{
|
||||||
|
return GetLocationRelativeToScreenBounds(GetCursorLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts locationRelativeToScreenOrigin to be relative to top left corner of all screen bounds, which might
|
||||||
|
/// be different in multiscreen setups. This implementation
|
||||||
|
/// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="locationRelativeToScreenOrigin"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Point GetLocationRelativeToScreenBounds(Point locationRelativeToScreenOrigin)
|
||||||
|
{
|
||||||
|
Point ret = locationRelativeToScreenOrigin;
|
||||||
|
Rectangle bounds = GetScreenBounds();
|
||||||
|
ret.Offset(-bounds.X, -bounds.Y);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will capture the current Cursor by using User32 Code
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A Capture Object with the Mouse Cursor information in it.</returns>
|
||||||
|
public static ICapture CaptureCursor(ICapture capture)
|
||||||
|
{
|
||||||
|
LOG.Debug("Capturing the mouse cursor.");
|
||||||
|
if (capture == null)
|
||||||
|
{
|
||||||
|
capture = new Capture();
|
||||||
|
}
|
||||||
|
int x, y;
|
||||||
|
CursorInfo cursorInfo = new CursorInfo();
|
||||||
|
IconInfo iconInfo;
|
||||||
|
cursorInfo.cbSize = Marshal.SizeOf(cursorInfo);
|
||||||
|
if (User32.GetCursorInfo(out cursorInfo))
|
||||||
|
{
|
||||||
|
if (cursorInfo.flags == User32.CURSOR_SHOWING)
|
||||||
|
{
|
||||||
|
using (SafeIconHandle safeIcon = User32.CopyIcon(cursorInfo.hCursor))
|
||||||
|
{
|
||||||
|
if (User32.GetIconInfo(safeIcon, out iconInfo))
|
||||||
|
{
|
||||||
|
Point cursorLocation = GetCursorLocation();
|
||||||
|
// Allign cursor location to Bitmap coordinates (instead of Screen coordinates)
|
||||||
|
x = cursorLocation.X - iconInfo.xHotspot - capture.ScreenBounds.X;
|
||||||
|
y = cursorLocation.Y - iconInfo.yHotspot - capture.ScreenBounds.Y;
|
||||||
|
// Set the location
|
||||||
|
capture.CursorLocation = new Point(x, y);
|
||||||
|
|
||||||
|
using (Icon icon = Icon.FromHandle(safeIcon.DangerousGetHandle()))
|
||||||
|
{
|
||||||
|
capture.Cursor = icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iconInfo.hbmMask != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
DeleteObject(iconInfo.hbmMask);
|
||||||
|
}
|
||||||
|
if (iconInfo.hbmColor != IntPtr.Zero)
|
||||||
|
{
|
||||||
|
DeleteObject(iconInfo.hbmColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return capture;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will call the CaptureRectangle with the screenbounds, therefor Capturing the whole screen.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A Capture Object with the Screen as an Image</returns>
|
||||||
|
public static ICapture CaptureScreen(ICapture capture)
|
||||||
|
{
|
||||||
|
if (capture == null)
|
||||||
|
{
|
||||||
|
capture = new Capture();
|
||||||
|
}
|
||||||
|
return CaptureRectangle(capture, capture.ScreenBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to create an exception that might explain what is wrong while capturing
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="method">string with current method</param>
|
||||||
|
/// <param name="capture">ICapture</param>
|
||||||
|
/// <param name="captureBounds">Rectangle of what we want to capture</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static Exception CreateCaptureException(string method, Rectangle captureBounds)
|
||||||
|
{
|
||||||
|
Exception exceptionToThrow = User32.CreateWin32Exception(method);
|
||||||
|
if (!captureBounds.IsEmpty)
|
||||||
|
{
|
||||||
|
exceptionToThrow.Data.Add("Height", captureBounds.Height);
|
||||||
|
exceptionToThrow.Data.Add("Width", captureBounds.Width);
|
||||||
|
}
|
||||||
|
return exceptionToThrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to check if it is allowed to capture the process using DWM
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="process">Process owning the window</param>
|
||||||
|
/// <returns>true if it's allowed</returns>
|
||||||
|
public static bool isDWMAllowed(Process process)
|
||||||
|
{
|
||||||
|
if (process != null)
|
||||||
|
{
|
||||||
|
if (conf.NoDWMCaptureForProduct != null && conf.NoDWMCaptureForProduct.Count > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string productName = process.MainModule.FileVersionInfo.ProductName;
|
||||||
|
if (productName != null && conf.NoDWMCaptureForProduct.Contains(productName.ToLower()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LOG.Warn(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to check if it is allowed to capture the process using GDI
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="processName">Process owning the window</param>
|
||||||
|
/// <returns>true if it's allowed</returns>
|
||||||
|
public static bool isGDIAllowed(Process process)
|
||||||
|
{
|
||||||
|
if (process != null)
|
||||||
|
{
|
||||||
|
if (conf.NoGDICaptureForProduct != null && conf.NoGDICaptureForProduct.Count > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string productName = process.MainModule.FileVersionInfo.ProductName;
|
||||||
|
if (productName != null && conf.NoGDICaptureForProduct.Contains(productName.ToLower()))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LOG.Warn(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will use User32 code to capture the specified captureBounds from the screen
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="capture">ICapture where the captured Bitmap will be stored</param>
|
||||||
|
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
|
||||||
|
/// <returns>A Capture Object with a part of the Screen as an Image</returns>
|
||||||
|
public static ICapture CaptureRectangle(ICapture capture, Rectangle captureBounds)
|
||||||
|
{
|
||||||
|
if (capture == null)
|
||||||
|
{
|
||||||
|
capture = new Capture();
|
||||||
|
}
|
||||||
|
capture.Image = CaptureRectangle(captureBounds);
|
||||||
|
capture.Location = captureBounds.Location;
|
||||||
|
if (capture.CaptureDetails != null)
|
||||||
|
{
|
||||||
|
((Bitmap)capture.Image).SetResolution(capture.CaptureDetails.DpiX, capture.CaptureDetails.DpiY);
|
||||||
|
}
|
||||||
|
if (capture.Image == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return capture;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will use User32 code to capture the specified captureBounds from the screen
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="captureBounds">Rectangle with the bounds to capture</param>
|
||||||
|
/// <returns>Bitmap which is captured from the screen at the location specified by the captureBounds</returns>
|
||||||
|
public static Bitmap CaptureRectangle(Rectangle captureBounds)
|
||||||
|
{
|
||||||
|
Bitmap returnBitmap = null;
|
||||||
|
if (captureBounds.Height <= 0 || captureBounds.Width <= 0)
|
||||||
|
{
|
||||||
|
LOG.Warn("Nothing to capture, ignoring!");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG.Debug("CaptureRectangle Called!");
|
||||||
|
}
|
||||||
|
// .NET GDI+ Solution, according to some post this has a GDI+ leak...
|
||||||
|
// See http://connect.microsoft.com/VisualStudio/feedback/details/344752/gdi-object-leak-when-calling-graphics-copyfromscreen
|
||||||
|
// Bitmap capturedBitmap = new Bitmap(captureBounds.Width, captureBounds.Height);
|
||||||
|
// using (Graphics graphics = Graphics.FromImage(capturedBitmap)) {
|
||||||
|
// graphics.CopyFromScreen(captureBounds.Location, Point.Empty, captureBounds.Size, CopyPixelOperation.CaptureBlt);
|
||||||
|
// }
|
||||||
|
// capture.Image = capturedBitmap;
|
||||||
|
// capture.Location = captureBounds.Location;
|
||||||
|
|
||||||
|
using (SafeWindowDCHandle desktopDCHandle = SafeWindowDCHandle.fromDesktop())
|
||||||
|
{
|
||||||
|
if (desktopDCHandle.IsInvalid)
|
||||||
|
{
|
||||||
|
// Get Exception before the error is lost
|
||||||
|
Exception exceptionToThrow = CreateCaptureException("desktopDCHandle", captureBounds);
|
||||||
|
// throw exception
|
||||||
|
throw exceptionToThrow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a device context we can copy to
|
||||||
|
using (SafeCompatibleDCHandle safeCompatibleDCHandle = GDI32.CreateCompatibleDC(desktopDCHandle))
|
||||||
|
{
|
||||||
|
// Check if the device context is there, if not throw an error with as much info as possible!
|
||||||
|
if (safeCompatibleDCHandle.IsInvalid)
|
||||||
|
{
|
||||||
|
// Get Exception before the error is lost
|
||||||
|
Exception exceptionToThrow = CreateCaptureException("CreateCompatibleDC", captureBounds);
|
||||||
|
// throw exception
|
||||||
|
throw exceptionToThrow;
|
||||||
|
}
|
||||||
|
// Create BitmapInfoHeader for CreateDIBSection
|
||||||
|
BitmapInfoHeader bmi = new BitmapInfoHeader(captureBounds.Width, captureBounds.Height, 24);
|
||||||
|
|
||||||
|
// Make sure the last error is set to 0
|
||||||
|
Win32.SetLastError(0);
|
||||||
|
|
||||||
|
// create a bitmap we can copy it to, using GetDeviceCaps to get the width/height
|
||||||
|
IntPtr bits0; // not used for our purposes. It returns a pointer to the raw bits that make up the bitmap.
|
||||||
|
using (SafeDibSectionHandle safeDibSectionHandle = GDI32.CreateDIBSection(desktopDCHandle, ref bmi, BitmapInfoHeader.DIB_RGB_COLORS, out bits0, IntPtr.Zero, 0))
|
||||||
|
{
|
||||||
|
if (safeDibSectionHandle.IsInvalid)
|
||||||
|
{
|
||||||
|
// Get Exception before the error is lost
|
||||||
|
Exception exceptionToThrow = CreateCaptureException("CreateDIBSection", captureBounds);
|
||||||
|
exceptionToThrow.Data.Add("hdcDest", safeCompatibleDCHandle.DangerousGetHandle().ToInt32());
|
||||||
|
exceptionToThrow.Data.Add("hdcSrc", desktopDCHandle.DangerousGetHandle().ToInt32());
|
||||||
|
|
||||||
|
// Throw so people can report the problem
|
||||||
|
throw exceptionToThrow;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// select the bitmap object and store the old handle
|
||||||
|
using (SafeSelectObjectHandle selectObject = safeCompatibleDCHandle.SelectObject(safeDibSectionHandle))
|
||||||
|
{
|
||||||
|
// bitblt over (make copy)
|
||||||
|
GDI32.BitBlt(safeCompatibleDCHandle, 0, 0, captureBounds.Width, captureBounds.Height, desktopDCHandle, captureBounds.X, captureBounds.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a .NET image object for it
|
||||||
|
// A suggestion for the "A generic error occurred in GDI+." E_FAIL/0×80004005 error is to re-try...
|
||||||
|
bool success = false;
|
||||||
|
ExternalException exception = null;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Collect all screens inside this capture
|
||||||
|
List<Screen> screensInsideCapture = new List<Screen>();
|
||||||
|
foreach (Screen screen in Screen.AllScreens)
|
||||||
|
{
|
||||||
|
if (screen.Bounds.IntersectsWith(captureBounds))
|
||||||
|
{
|
||||||
|
screensInsideCapture.Add(screen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check all all screens are of an equal size
|
||||||
|
bool offscreenContent = false;
|
||||||
|
using (Region captureRegion = new Region(captureBounds))
|
||||||
|
{
|
||||||
|
// Exclude every visible part
|
||||||
|
foreach (Screen screen in screensInsideCapture)
|
||||||
|
{
|
||||||
|
captureRegion.Exclude(screen.Bounds);
|
||||||
|
}
|
||||||
|
// If the region is not empty, we have "offscreenContent"
|
||||||
|
using (Graphics screenGraphics = Graphics.FromHwnd(User32.GetDesktopWindow()))
|
||||||
|
{
|
||||||
|
offscreenContent = !captureRegion.IsEmpty(screenGraphics);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check if we need to have a transparent background, needed for offscreen content
|
||||||
|
if (offscreenContent)
|
||||||
|
{
|
||||||
|
using (Bitmap tmpBitmap = Bitmap.FromHbitmap(safeDibSectionHandle.DangerousGetHandle()))
|
||||||
|
{
|
||||||
|
// Create a new bitmap which has a transparent background
|
||||||
|
returnBitmap = ImageHelper.CreateEmpty(tmpBitmap.Width, tmpBitmap.Height, PixelFormat.Format32bppArgb, Color.Transparent, tmpBitmap.HorizontalResolution, tmpBitmap.VerticalResolution);
|
||||||
|
// Content will be copied here
|
||||||
|
using (Graphics graphics = Graphics.FromImage(returnBitmap))
|
||||||
|
{
|
||||||
|
// For all screens copy the content to the new bitmap
|
||||||
|
foreach (Screen screen in Screen.AllScreens)
|
||||||
|
{
|
||||||
|
Rectangle screenBounds = screen.Bounds;
|
||||||
|
// Make sure the bounds are offsetted to the capture bounds
|
||||||
|
screenBounds.Offset(-captureBounds.X, -captureBounds.Y);
|
||||||
|
graphics.DrawImage(tmpBitmap, screenBounds, screenBounds.X, screenBounds.Y, screenBounds.Width, screenBounds.Height, GraphicsUnit.Pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// All screens, which are inside the capture, are of equal size
|
||||||
|
// assign image to Capture, the image will be disposed there..
|
||||||
|
returnBitmap = Bitmap.FromHbitmap(safeDibSectionHandle.DangerousGetHandle());
|
||||||
|
}
|
||||||
|
// We got through the capture without exception
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (ExternalException ee)
|
||||||
|
{
|
||||||
|
LOG.Warn("Problem getting bitmap at try " + i + " : ", ee);
|
||||||
|
exception = ee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
LOG.Error("Still couldn't create Bitmap!");
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnBitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2074
GreenshotImageEditor/Core/WindowsHelper.cs
Normal file
2074
GreenshotImageEditor/Core/WindowsHelper.cs
Normal file
File diff suppressed because it is too large
Load diff
159
GreenshotImageEditor/Drawing/ArrowContainer.cs
Normal file
159
GreenshotImageEditor/Drawing/ArrowContainer.cs
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Drawing.Fields;
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of LineContainer.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable()]
|
||||||
|
public class ArrowContainer : LineContainer
|
||||||
|
{
|
||||||
|
public enum ArrowHeadCombination { NONE, START_POINT, END_POINT, BOTH };
|
||||||
|
|
||||||
|
private static readonly AdjustableArrowCap ARROW_CAP = new AdjustableArrowCap(4, 6);
|
||||||
|
|
||||||
|
public ArrowContainer(Surface parent)
|
||||||
|
: base(parent)
|
||||||
|
{
|
||||||
|
AddField(GetType(), FieldType.ARROWHEADS, 2);
|
||||||
|
AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
|
||||||
|
//AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
|
||||||
|
AddField(GetType(), FieldType.SHADOW, true);
|
||||||
|
AddField(GetType(), FieldType.ARROWHEADS, ArrowHeadCombination.END_POINT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(Graphics graphics, RenderMode rm)
|
||||||
|
{
|
||||||
|
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||||
|
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||||
|
|
||||||
|
if (lineThickness > 0)
|
||||||
|
{
|
||||||
|
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
|
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||||
|
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||||
|
ArrowHeadCombination heads = (ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS);
|
||||||
|
if (lineThickness > 0)
|
||||||
|
{
|
||||||
|
if (shadow)
|
||||||
|
{
|
||||||
|
//draw shadow first
|
||||||
|
int basealpha = 100;
|
||||||
|
int alpha = basealpha;
|
||||||
|
int steps = 5;
|
||||||
|
int currentStep = 1;
|
||||||
|
while (currentStep <= steps)
|
||||||
|
{
|
||||||
|
using (Pen shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness))
|
||||||
|
{
|
||||||
|
SetArrowHeads(heads, shadowCapPen);
|
||||||
|
|
||||||
|
graphics.DrawLine(shadowCapPen,
|
||||||
|
Left + currentStep,
|
||||||
|
Top + currentStep,
|
||||||
|
Left + currentStep + Width,
|
||||||
|
Top + currentStep + Height);
|
||||||
|
|
||||||
|
currentStep++;
|
||||||
|
alpha = alpha - (basealpha / steps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (Pen pen = new Pen(lineColor, lineThickness))
|
||||||
|
{
|
||||||
|
SetArrowHeads(heads, pen);
|
||||||
|
graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetArrowHeads(ArrowHeadCombination heads, Pen pen)
|
||||||
|
{
|
||||||
|
if (heads == ArrowHeadCombination.BOTH || heads == ArrowHeadCombination.START_POINT)
|
||||||
|
{
|
||||||
|
pen.CustomStartCap = ARROW_CAP;
|
||||||
|
}
|
||||||
|
if (heads == ArrowHeadCombination.BOTH || heads == ArrowHeadCombination.END_POINT)
|
||||||
|
{
|
||||||
|
pen.CustomEndCap = ARROW_CAP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Rectangle DrawingBounds
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||||
|
if (lineThickness > 0)
|
||||||
|
{
|
||||||
|
using (Pen pen = new Pen(Color.White))
|
||||||
|
{
|
||||||
|
pen.Width = lineThickness;
|
||||||
|
SetArrowHeads((ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS), pen);
|
||||||
|
using (GraphicsPath path = new GraphicsPath())
|
||||||
|
{
|
||||||
|
path.AddLine(Left, Top, Left + Width, Top + Height);
|
||||||
|
Rectangle drawingBounds = Rectangle.Round(path.GetBounds(new Matrix(), pen));
|
||||||
|
drawingBounds.Inflate(2, 2);
|
||||||
|
return drawingBounds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Rectangle.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ClickableAt(int x, int y)
|
||||||
|
{
|
||||||
|
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10;
|
||||||
|
if (lineThickness > 0)
|
||||||
|
{
|
||||||
|
using (Pen pen = new Pen(Color.White))
|
||||||
|
{
|
||||||
|
pen.Width = lineThickness;
|
||||||
|
SetArrowHeads((ArrowHeadCombination)GetFieldValue(FieldType.ARROWHEADS), pen);
|
||||||
|
using (GraphicsPath path = new GraphicsPath())
|
||||||
|
{
|
||||||
|
path.AddLine(Left, Top, Left + Width, Top + Height);
|
||||||
|
return path.IsOutlineVisible(x, y, pen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
86
GreenshotImageEditor/Drawing/CropContainer.cs
Normal file
86
GreenshotImageEditor/Drawing/CropContainer.cs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Drawing.Fields;
|
||||||
|
using Greenshot.Helpers;
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of CropContainer.
|
||||||
|
/// </summary>
|
||||||
|
public class CropContainer : DrawableContainer
|
||||||
|
{
|
||||||
|
public CropContainer(Surface parent)
|
||||||
|
: base(parent)
|
||||||
|
{
|
||||||
|
AddField(GetType(), FieldType.FLAGS, FieldType.Flag.CONFIRMABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Invalidate()
|
||||||
|
{
|
||||||
|
parent.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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)
|
||||||
|
/// </summary>
|
||||||
|
public override Rectangle DrawingBounds
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Rectangle(0, 0, parent.Width, parent.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(Graphics g, RenderMode rm)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
DrawSelectionBorder(g, selectionRect);
|
||||||
|
|
||||||
|
// top
|
||||||
|
g.FillRectangle(cropBrush, new Rectangle(0, 0, parent.Width, cropRectangle.Top));
|
||||||
|
// left
|
||||||
|
g.FillRectangle(cropBrush, new Rectangle(0, cropRectangle.Top, cropRectangle.Left, cropRectangle.Height));
|
||||||
|
// right
|
||||||
|
g.FillRectangle(cropBrush, new Rectangle(cropRectangle.Left + cropRectangle.Width, cropRectangle.Top, parent.Width - (cropRectangle.Left + cropRectangle.Width), cropRectangle.Height));
|
||||||
|
// bottom
|
||||||
|
g.FillRectangle(cropBrush, new Rectangle(0, cropRectangle.Top + cropRectangle.Height, parent.Width, parent.Height - (cropRectangle.Top + cropRectangle.Height)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool hasContextMenu
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// No context menu for the CropContainer
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
117
GreenshotImageEditor/Drawing/CursorContainer.cs
Normal file
117
GreenshotImageEditor/Drawing/CursorContainer.cs
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using GreenshotPlugin;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.IO;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of CursorContainer.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable()]
|
||||||
|
public class CursorContainer : DrawableContainer, ICursorContainer
|
||||||
|
{
|
||||||
|
protected Cursor cursor;
|
||||||
|
|
||||||
|
public CursorContainer(Surface parent)
|
||||||
|
: base(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public CursorContainer(Surface parent, string filename)
|
||||||
|
: base(parent)
|
||||||
|
{
|
||||||
|
Load(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cursor Cursor
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (cursor != null)
|
||||||
|
{
|
||||||
|
cursor.Dispose();
|
||||||
|
}
|
||||||
|
// Clone cursor (is this correct??)
|
||||||
|
cursor = new Cursor(value.CopyHandle());
|
||||||
|
Width = value.Size.Width;
|
||||||
|
Height = value.Size.Height;
|
||||||
|
}
|
||||||
|
get { return cursor; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This Dispose is called from the Dispose and the Destructor.
|
||||||
|
/// When disposing==true all non-managed resources should be freed too!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing"></param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (cursor != null)
|
||||||
|
{
|
||||||
|
cursor.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursor = null;
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Load(string filename)
|
||||||
|
{
|
||||||
|
if (File.Exists(filename))
|
||||||
|
{
|
||||||
|
using (Cursor fileCursor = new Cursor(filename))
|
||||||
|
{
|
||||||
|
Cursor = fileCursor;
|
||||||
|
LOG.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(Graphics graphics, RenderMode rm)
|
||||||
|
{
|
||||||
|
if (cursor != null)
|
||||||
|
{
|
||||||
|
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||||
|
graphics.CompositingQuality = CompositingQuality.Default;
|
||||||
|
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||||
|
cursor.DrawStretched(graphics, Bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Size DefaultSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return cursor.Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
856
GreenshotImageEditor/Drawing/DrawableContainer.cs
Normal file
856
GreenshotImageEditor/Drawing/DrawableContainer.cs
Normal file
|
@ -0,0 +1,856 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Configuration;
|
||||||
|
using Greenshot.Drawing.Fields;
|
||||||
|
using Greenshot.Drawing.Filters;
|
||||||
|
using Greenshot.Helpers;
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using Greenshot.Memento;
|
||||||
|
using Greenshot.Plugin;
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using GreenshotPlugin;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// represents a rectangle, ellipse, label or whatever. Can contain filters, too.
|
||||||
|
/// serializable for clipboard support
|
||||||
|
/// Subclasses should fulfill INotifyPropertyChanged contract, i.e. call
|
||||||
|
/// OnPropertyChanged whenever a public property has been changed.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable()]
|
||||||
|
public abstract class DrawableContainer : AbstractFieldHolderWithChildren, INotifyPropertyChanged, IDrawableContainer
|
||||||
|
{
|
||||||
|
protected static readonly EditorConfiguration editorConfig = IniConfig.GetIniSection<EditorConfiguration>();
|
||||||
|
private bool isMadeUndoable = false;
|
||||||
|
|
||||||
|
public virtual void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
if (grippers != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < grippers.Length; i++)
|
||||||
|
{
|
||||||
|
if (grippers[i] != null)
|
||||||
|
{
|
||||||
|
grippers[i].Dispose();
|
||||||
|
grippers[i] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
grippers = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
FieldAggregator aggProps = parent.FieldAggregator;
|
||||||
|
aggProps.UnbindElement(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~DrawableContainer()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NonSerialized]
|
||||||
|
private PropertyChangedEventHandler propertyChanged;
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged
|
||||||
|
{
|
||||||
|
add { propertyChanged += value; }
|
||||||
|
remove { propertyChanged -= value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IFilter> Filters
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
List<IFilter> ret = new List<IFilter>();
|
||||||
|
foreach (IFieldHolder c in Children)
|
||||||
|
{
|
||||||
|
if (c is IFilter)
|
||||||
|
{
|
||||||
|
ret.Add(c as IFilter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NonSerialized]
|
||||||
|
internal Surface parent;
|
||||||
|
public ISurface Parent
|
||||||
|
{
|
||||||
|
get { return parent; }
|
||||||
|
set { SwitchParent((Surface)value); }
|
||||||
|
}
|
||||||
|
[NonSerialized]
|
||||||
|
protected Gripper[] grippers;
|
||||||
|
private bool layoutSuspended = false;
|
||||||
|
|
||||||
|
[NonSerialized]
|
||||||
|
private bool selected = false;
|
||||||
|
public bool Selected
|
||||||
|
{
|
||||||
|
get { return selected; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
selected = value;
|
||||||
|
OnPropertyChanged("Selected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NonSerialized]
|
||||||
|
private EditStatus status = EditStatus.UNDRAWN;
|
||||||
|
public EditStatus Status
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
status = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int left = 0;
|
||||||
|
public int Left
|
||||||
|
{
|
||||||
|
get { return left; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != left)
|
||||||
|
{
|
||||||
|
left = value;
|
||||||
|
DoLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int top = 0;
|
||||||
|
public int Top
|
||||||
|
{
|
||||||
|
get { return top; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != top)
|
||||||
|
{
|
||||||
|
top = value;
|
||||||
|
DoLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int width = 0;
|
||||||
|
public int Width
|
||||||
|
{
|
||||||
|
get { return width; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != width)
|
||||||
|
{
|
||||||
|
width = value;
|
||||||
|
DoLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int height = 0;
|
||||||
|
public int Height
|
||||||
|
{
|
||||||
|
get { return height; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != height)
|
||||||
|
{
|
||||||
|
height = value;
|
||||||
|
DoLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point Location
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Point(left, top);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Size Size
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Size(width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[NonSerialized]
|
||||||
|
/// <summary>
|
||||||
|
/// will store current bounds of this DrawableContainer before starting a resize
|
||||||
|
/// </summary>
|
||||||
|
private Rectangle boundsBeforeResize = Rectangle.Empty;
|
||||||
|
|
||||||
|
[NonSerialized]
|
||||||
|
/// <summary>
|
||||||
|
/// "workbench" rectangle - used for calculatoing bounds during resizing (to be applied to this DrawableContainer afterwards)
|
||||||
|
/// </summary>
|
||||||
|
private RectangleF boundsAfterResize = RectangleF.Empty;
|
||||||
|
|
||||||
|
public Rectangle Bounds
|
||||||
|
{
|
||||||
|
get { return GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Left = round(value.Left);
|
||||||
|
Top = round(value.Top);
|
||||||
|
Width = round(value.Width);
|
||||||
|
Height = round(value.Height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ApplyBounds(RectangleF newBounds)
|
||||||
|
{
|
||||||
|
Left = round(newBounds.Left);
|
||||||
|
Top = round(newBounds.Top);
|
||||||
|
Width = round(newBounds.Width);
|
||||||
|
Height = round(newBounds.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DrawableContainer(Surface parent)
|
||||||
|
{
|
||||||
|
this.parent = parent;
|
||||||
|
InitControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(IFilter filter)
|
||||||
|
{
|
||||||
|
AddChild(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(IFilter filter)
|
||||||
|
{
|
||||||
|
RemoveChild(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int round(float f)
|
||||||
|
{
|
||||||
|
if (float.IsPositiveInfinity(f) || f > int.MaxValue / 2) return int.MaxValue / 2;
|
||||||
|
else if (float.IsNegativeInfinity(f) || f < int.MinValue / 2) return int.MinValue / 2;
|
||||||
|
return (int)Math.Round(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int round(double d)
|
||||||
|
{
|
||||||
|
if (Double.IsPositiveInfinity(d) || d > int.MaxValue / 2) return int.MaxValue / 2;
|
||||||
|
else if (Double.IsNegativeInfinity(d) || d < int.MinValue / 2) return int.MinValue / 2;
|
||||||
|
else return (int)Math.Round(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool accountForShadowChange = false;
|
||||||
|
public virtual Rectangle DrawingBounds
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
foreach (IFilter filter in Filters)
|
||||||
|
{
|
||||||
|
if (filter.Invert)
|
||||||
|
{
|
||||||
|
return new Rectangle(Point.Empty, parent.Image.Size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Take a base safetymargin
|
||||||
|
int lineThickness = 5;
|
||||||
|
if (HasField(FieldType.LINE_THICKNESS))
|
||||||
|
{
|
||||||
|
lineThickness += GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||||
|
}
|
||||||
|
int offset = lineThickness / 2;
|
||||||
|
|
||||||
|
int shadow = 0;
|
||||||
|
if (accountForShadowChange || (HasField(FieldType.SHADOW) && GetFieldValueAsBool(FieldType.SHADOW)))
|
||||||
|
{
|
||||||
|
accountForShadowChange = false;
|
||||||
|
shadow += 10;
|
||||||
|
}
|
||||||
|
return new Rectangle(Bounds.Left - offset, Bounds.Top - offset, Bounds.Width + lineThickness + shadow, Bounds.Height + lineThickness + shadow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Invalidate()
|
||||||
|
{
|
||||||
|
parent.Invalidate(DrawingBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AlignToParent(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment)
|
||||||
|
{
|
||||||
|
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||||
|
if (horizontalAlignment == HorizontalAlignment.Left)
|
||||||
|
{
|
||||||
|
Left = lineThickness / 2;
|
||||||
|
}
|
||||||
|
if (horizontalAlignment == HorizontalAlignment.Right)
|
||||||
|
{
|
||||||
|
Left = parent.Width - Width - lineThickness / 2;
|
||||||
|
}
|
||||||
|
if (horizontalAlignment == HorizontalAlignment.Center)
|
||||||
|
{
|
||||||
|
Left = (parent.Width / 2) - (Width / 2) - lineThickness / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verticalAlignment == VerticalAlignment.TOP)
|
||||||
|
{
|
||||||
|
Top = lineThickness / 2;
|
||||||
|
}
|
||||||
|
if (verticalAlignment == VerticalAlignment.BOTTOM)
|
||||||
|
{
|
||||||
|
Top = parent.Height - Height - lineThickness / 2;
|
||||||
|
}
|
||||||
|
if (verticalAlignment == VerticalAlignment.CENTER)
|
||||||
|
{
|
||||||
|
Top = (parent.Height / 2) - (Height / 2) - lineThickness / 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool InitContent()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void OnDoubleClick()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitControls()
|
||||||
|
{
|
||||||
|
InitGrippers();
|
||||||
|
|
||||||
|
DoLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 center = (Gripper.GripperSize - 1) / 2;
|
||||||
|
int[] xChoords = new int[] { Left - center, Left + Width / 2 - center, Left + Width - center };
|
||||||
|
int[] yChoords = new int[] { Top - center, Top + Height / 2 - center, Top + Height - center };
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int mx;
|
||||||
|
private int my;
|
||||||
|
|
||||||
|
private void gripperMouseDown(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
mx = e.X;
|
||||||
|
my = e.Y;
|
||||||
|
Status = EditStatus.RESIZING;
|
||||||
|
boundsBeforeResize = new Rectangle(left, top, width, height);
|
||||||
|
boundsAfterResize = new RectangleF(boundsBeforeResize.Left, boundsBeforeResize.Top, boundsBeforeResize.Width, boundsBeforeResize.Height);
|
||||||
|
isMadeUndoable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void gripperMouseUp(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
Status = EditStatus.IDLE;
|
||||||
|
boundsBeforeResize = Rectangle.Empty;
|
||||||
|
boundsAfterResize = RectangleF.Empty;
|
||||||
|
isMadeUndoable = false;
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void gripperMouseMove(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
Invalidate();
|
||||||
|
SuspendLayout();
|
||||||
|
|
||||||
|
Gripper gr = (Gripper)sender;
|
||||||
|
int absX = gr.Left + e.X;
|
||||||
|
int absY = gr.Top + e.Y;
|
||||||
|
|
||||||
|
// 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, gr.Position, new PointF(absX, absY), ScaleHelper.GetScaleOptions());
|
||||||
|
|
||||||
|
// apply scaled bounds to this DrawableContainer
|
||||||
|
ApplyBounds(boundsAfterResize);
|
||||||
|
|
||||||
|
ResumeLayout();
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void childLabelMouseMove(object sender, MouseEventArgs e)
|
||||||
|
{
|
||||||
|
if (Status.Equals(EditStatus.RESIZING))
|
||||||
|
{
|
||||||
|
Invalidate();
|
||||||
|
SuspendLayout();
|
||||||
|
Left += e.X - mx;
|
||||||
|
Top += e.Y - my;
|
||||||
|
ResumeLayout();
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool hasFilters
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Filters.Count > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void Draw(Graphics graphics, RenderMode renderMode);
|
||||||
|
|
||||||
|
public virtual void DrawContent(Graphics graphics, Bitmap bmp, RenderMode renderMode, Rectangle clipRectangle)
|
||||||
|
{
|
||||||
|
if (Children.Count > 0)
|
||||||
|
{
|
||||||
|
if (Status != EditStatus.IDLE)
|
||||||
|
{
|
||||||
|
DrawSelectionBorder(graphics, Bounds);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (clipRectangle.Width != 0 && clipRectangle.Height != 0)
|
||||||
|
{
|
||||||
|
foreach (IFilter filter in Filters)
|
||||||
|
{
|
||||||
|
if (filter.Invert)
|
||||||
|
{
|
||||||
|
filter.Apply(graphics, bmp, Bounds, renderMode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Rectangle drawingRect = new Rectangle(Bounds.Location, Bounds.Size);
|
||||||
|
drawingRect.Intersect(clipRectangle);
|
||||||
|
filter.Apply(graphics, bmp, drawingRect, renderMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Draw(graphics, renderMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool Contains(int x, int y)
|
||||||
|
{
|
||||||
|
return Bounds.Contains(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool ClickableAt(int x, int y)
|
||||||
|
{
|
||||||
|
Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||||
|
r.Inflate(5, 5);
|
||||||
|
return r.Contains(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void DrawSelectionBorder(Graphics g, Rectangle rect)
|
||||||
|
{
|
||||||
|
using (Pen pen = new Pen(Color.MediumSeaGreen))
|
||||||
|
{
|
||||||
|
pen.DashPattern = new float[] { 1, 2 };
|
||||||
|
pen.Width = 1;
|
||||||
|
g.DrawRectangle(pen, rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResumeLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void HideGrippers()
|
||||||
|
{
|
||||||
|
SuspendLayout();
|
||||||
|
if (grippers != null)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < grippers.Length; i++)
|
||||||
|
{
|
||||||
|
grippers[i].Hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResizeTo(int width, int height, int anchorPosition)
|
||||||
|
{
|
||||||
|
SuspendLayout();
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
ResumeLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Make a following bounds change on this drawablecontainer undoable!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="allowMerge">true means allow the moves to be merged</param>
|
||||||
|
public void MakeBoundsChangeUndoable(bool allowMerge)
|
||||||
|
{
|
||||||
|
parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(this), allowMerge);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MoveBy(int dx, int dy)
|
||||||
|
{
|
||||||
|
SuspendLayout();
|
||||||
|
Left += dx;
|
||||||
|
Top += dy;
|
||||||
|
ResumeLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A handler for the MouseDown, used if you don't want the surface to handle this for you
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">current mouse x</param>
|
||||||
|
/// <param name="y">current mouse y</param>
|
||||||
|
/// <returns>true if the event is handled, false if the surface needs to handle it</returns>
|
||||||
|
public virtual bool HandleMouseDown(int x, int y)
|
||||||
|
{
|
||||||
|
Left = boundsBeforeResize.X = x;
|
||||||
|
Top = boundsBeforeResize.Y = y;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A handler for the MouseMove, used if you don't want the surface to handle this for you
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">current mouse x</param>
|
||||||
|
/// <param name="y">current mouse y</param>
|
||||||
|
/// <returns>true if the event is handled, false if the surface needs to handle it</returns>
|
||||||
|
public virtual bool HandleMouseMove(int x, int y)
|
||||||
|
{
|
||||||
|
Invalidate();
|
||||||
|
SuspendLayout();
|
||||||
|
|
||||||
|
// reset "workrbench" rectangle to current bounds
|
||||||
|
boundsAfterResize.X = boundsBeforeResize.Left;
|
||||||
|
boundsAfterResize.Y = boundsBeforeResize.Top;
|
||||||
|
boundsAfterResize.Width = x - boundsAfterResize.Left;
|
||||||
|
boundsAfterResize.Height = y - boundsAfterResize.Top;
|
||||||
|
|
||||||
|
ScaleHelper.Scale(boundsBeforeResize, x, y, ref boundsAfterResize, GetAngleRoundProcessor());
|
||||||
|
|
||||||
|
// apply scaled bounds to this DrawableContainer
|
||||||
|
ApplyBounds(boundsAfterResize);
|
||||||
|
|
||||||
|
ResumeLayout();
|
||||||
|
Invalidate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A handler for the MouseUp
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">current mouse x</param>
|
||||||
|
/// <param name="y">current mouse y</param>
|
||||||
|
public virtual void HandleMouseUp(int x, int y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SwitchParent(Surface newParent)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
parent.Controls.AddRange(grippers);
|
||||||
|
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().Equals(obj.GetType()))
|
||||||
|
{
|
||||||
|
DrawableContainer other = obj as DrawableContainer;
|
||||||
|
if (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));
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This method will be called before a field is changes.
|
||||||
|
/// Using this makes it possible to invalidate the object as is before changing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fieldToBeChanged">The field to be changed</param>
|
||||||
|
/// <param name="newValue">The new value</param>
|
||||||
|
public virtual void BeforeFieldChange(Field fieldToBeChanged, object newValue)
|
||||||
|
{
|
||||||
|
parent.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true);
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle the field changed event, this should invalidate the correct bounds (e.g. when shadow comes or goes more pixels!)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
public void HandleFieldChanged(object sender, FieldChangedEventArgs e)
|
||||||
|
{
|
||||||
|
LOG.DebugFormat("Field {0} changed", e.Field.FieldType);
|
||||||
|
if (e.Field.FieldType == FieldType.SHADOW)
|
||||||
|
{
|
||||||
|
accountForShadowChange = true;
|
||||||
|
}
|
||||||
|
Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool CanRotate
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Rotate(RotateFlipType rotateFlipType)
|
||||||
|
{
|
||||||
|
// somehow the rotation is the wrong way?
|
||||||
|
int angle = 90;
|
||||||
|
if (RotateFlipType.Rotate90FlipNone == rotateFlipType)
|
||||||
|
{
|
||||||
|
angle = 270;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle beforeBounds = new Rectangle(Left, Top, Width, Height);
|
||||||
|
LOG.DebugFormat("Bounds before: {0}", beforeBounds);
|
||||||
|
GraphicsPath translatePath = new GraphicsPath();
|
||||||
|
translatePath.AddRectangle(beforeBounds);
|
||||||
|
Matrix rotateMatrix = new Matrix();
|
||||||
|
rotateMatrix.RotateAt(angle, new PointF(parent.Width >> 1, parent.Height >> 1));
|
||||||
|
translatePath.Transform(rotateMatrix);
|
||||||
|
RectangleF newBounds = translatePath.GetBounds();
|
||||||
|
LOG.DebugFormat("New bounds by using graphics path: {0}", newBounds);
|
||||||
|
|
||||||
|
int ox = 0;
|
||||||
|
int oy = 0;
|
||||||
|
int centerX = parent.Width >> 1;
|
||||||
|
int centerY = parent.Height >> 1;
|
||||||
|
// Transform from screen to normal coordinates
|
||||||
|
int px = Left - centerX;
|
||||||
|
int py = centerY - Top;
|
||||||
|
double theta = Math.PI * angle / 180.0;
|
||||||
|
double x1 = Math.Cos(theta) * (px - ox) - Math.Sin(theta) * (py - oy) + ox;
|
||||||
|
double y1 = Math.Sin(theta) * (px - ox) + Math.Cos(theta) * (py - oy) + oy;
|
||||||
|
|
||||||
|
// Transform from screen to normal coordinates
|
||||||
|
px = (Left + Width) - centerX;
|
||||||
|
py = centerY - (Top + Height);
|
||||||
|
|
||||||
|
double x2 = Math.Cos(theta) * (px - ox) - Math.Sin(theta) * (py - oy) + ox;
|
||||||
|
double y2 = Math.Sin(theta) * (px - ox) + Math.Cos(theta) * (py - oy) + oy;
|
||||||
|
|
||||||
|
// Transform back to screen coordinates, as we rotate the bitmap we need to switch the center X&Y
|
||||||
|
x1 += centerY;
|
||||||
|
y1 = centerX - y1;
|
||||||
|
x2 += centerY;
|
||||||
|
y2 = centerX - y2;
|
||||||
|
|
||||||
|
// Calculate to rectangle
|
||||||
|
double newWidth = x2 - x1;
|
||||||
|
double newHeight = y2 - y1;
|
||||||
|
|
||||||
|
RectangleF newRectangle = new RectangleF(
|
||||||
|
(float)x1,
|
||||||
|
(float)y1,
|
||||||
|
(float)newWidth,
|
||||||
|
(float)newHeight
|
||||||
|
);
|
||||||
|
ApplyBounds(newRectangle);
|
||||||
|
LOG.DebugFormat("New bounds by using old method: {0}", newRectangle);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual ScaleHelper.IDoubleProcessor GetAngleRoundProcessor()
|
||||||
|
{
|
||||||
|
return ScaleHelper.ShapeAngleRoundBehavior.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool hasContextMenu
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool hasDefaultSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual Size DefaultSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Object doesn't have a default size");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
621
GreenshotImageEditor/Drawing/DrawableContainerList.cs
Normal file
621
GreenshotImageEditor/Drawing/DrawableContainerList.cs
Normal file
|
@ -0,0 +1,621 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Threading;
|
||||||
|
using Greenshot.Drawing.Fields;
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using Greenshot.Memento;
|
||||||
|
using Greenshot.Plugin;
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches most of a DrawableContainer's public properties and methods to a list of DrawableContainers.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable()]
|
||||||
|
public class DrawableContainerList : List<IDrawableContainer>
|
||||||
|
{
|
||||||
|
private static CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
||||||
|
private static ComponentResourceManager editorFormResources = new ComponentResourceManager(typeof(ImageEditorForm));
|
||||||
|
|
||||||
|
public DrawableContainerList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public EditStatus Status
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this[Count - 1].Status;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
dc.Status = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IDrawableContainer> AsIDrawableContainerList()
|
||||||
|
{
|
||||||
|
List<IDrawableContainer> interfaceList = new List<IDrawableContainer>();
|
||||||
|
foreach (IDrawableContainer container in this)
|
||||||
|
{
|
||||||
|
interfaceList.Add(container);
|
||||||
|
}
|
||||||
|
return interfaceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the selection status of the elements.
|
||||||
|
/// If several elements are in the list, true is only returned when all elements are selected.
|
||||||
|
/// </summary>
|
||||||
|
public bool Selected
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
bool ret = true;
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
ret &= dc.Selected;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
dc.Selected = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the parent control of the elements in the list.
|
||||||
|
/// If there are several elements, the parent control of the last added is returned.
|
||||||
|
/// </summary>
|
||||||
|
public ISurface Parent
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (Count > 0)
|
||||||
|
{
|
||||||
|
return this[Count - 1].Parent;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
dc.Parent = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Make a following bounds change on this containerlist undoable!
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="allowMerge">true means allow the moves to be merged</param>
|
||||||
|
public void MakeBoundsChangeUndoable(bool allowMerge)
|
||||||
|
{
|
||||||
|
List<IDrawableContainer> movingList = new List<IDrawableContainer>();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moves all elements in the list by the given amount of pixels.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dx">pixels to move horizontally</param>
|
||||||
|
/// <param name="dy">pixels to move vertically</param>
|
||||||
|
public void MoveBy(int dx, int dy)
|
||||||
|
{
|
||||||
|
// Track modifications
|
||||||
|
bool modified = false;
|
||||||
|
|
||||||
|
// Invalidate before moving, otherwise the old locations aren't refreshed
|
||||||
|
Invalidate();
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
dc.Left += dx;
|
||||||
|
dc.Top += dy;
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
// Invalidate after
|
||||||
|
Invalidate();
|
||||||
|
|
||||||
|
// If we moved something, tell the surface it's modified!
|
||||||
|
if (modified)
|
||||||
|
{
|
||||||
|
Parent.Modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Hides the grippers of all elements in the list.
|
||||||
|
/// </summary>
|
||||||
|
public void HideGrippers()
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
dc.HideGrippers();
|
||||||
|
dc.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shows the grippers of all elements in the list.
|
||||||
|
/// </summary>
|
||||||
|
public void ShowGrippers()
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
dc.ShowGrippers();
|
||||||
|
dc.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether on of the elements is clickable at the given location
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">x coordinate to be checked</param>
|
||||||
|
/// <param name="y">y coordinate to be checked</param>
|
||||||
|
/// <returns>true if one of the elements in the list is clickable at the given location, false otherwise</returns>
|
||||||
|
public bool ClickableAt(int x, int y)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
ret |= dc.ClickableAt(x, y);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// retrieves the topmost element being clickable at the given location
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">x coordinate to be checked</param>
|
||||||
|
/// <param name="y">y coordinate to be checked</param>
|
||||||
|
/// <returns>the topmost element from the list being clickable at the given location, null if there is no clickable element</returns>
|
||||||
|
public IDrawableContainer ClickableElementAt(int x, int y)
|
||||||
|
{
|
||||||
|
for (int i = Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (this[i].ClickableAt(x, y))
|
||||||
|
{
|
||||||
|
return this[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispatches OnDoubleClick to all elements in the list.
|
||||||
|
/// </summary>
|
||||||
|
public void OnDoubleClick()
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
dc.OnDoubleClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if there are any intersecting filters, if so we need to redraw more
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clipRectangle"></param>
|
||||||
|
/// <returns>true if an filter intersects</returns>
|
||||||
|
public bool hasIntersectingFilters(Rectangle clipRectangle)
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
if (dc.DrawingBounds.IntersectsWith(clipRectangle) && dc.hasFilters && dc.Status == EditStatus.IDLE)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if any of the drawableContainers are inside the rectangle
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clipRectangle"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool IntersectsWith(Rectangle clipRectangle)
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
if (dc.DrawingBounds.IntersectsWith(clipRectangle))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Triggers all elements in the list ot be redrawn.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="g">the related Graphics object</param>
|
||||||
|
/// <param name="renderMode">the rendermode in which the element is to be drawn</param>
|
||||||
|
public void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle)
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
if (dc.DrawingBounds.IntersectsWith(clipRectangle))
|
||||||
|
{
|
||||||
|
dc.DrawContent(g, bitmap, renderMode, clipRectangle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pass the field changed event to all elements in the list
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
public void HandleFieldChangedEvent(object sender, FieldChangedEventArgs e)
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
dc.HandleFieldChanged(sender, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Invalidate the bounds of all the DC's in this list
|
||||||
|
/// </summary>
|
||||||
|
public void Invalidate()
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in this)
|
||||||
|
{
|
||||||
|
dc.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the given list of elements can be pulled up,
|
||||||
|
/// i.e. whether there is at least one unselected element higher in hierarchy
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="elements">list of elements to pull up</param>
|
||||||
|
/// <returns>true if the elements could be pulled up</returns>
|
||||||
|
public bool CanPullUp(DrawableContainerList elements)
|
||||||
|
{
|
||||||
|
if (elements.Count == 0 || elements.Count == Count)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach (DrawableContainer element in elements)
|
||||||
|
{
|
||||||
|
if (IndexOf(element) < Count - elements.Count)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pulls one or several elements up one level in hierarchy (z-index).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="elements">list of elements to pull up</param>
|
||||||
|
public void PullElementsUp(DrawableContainerList elements)
|
||||||
|
{
|
||||||
|
for (int i = Count - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
IDrawableContainer dc = this[i];
|
||||||
|
if (elements.Contains(dc))
|
||||||
|
{
|
||||||
|
if (Count > (i + 1) && !elements.Contains(this[i + 1]))
|
||||||
|
{
|
||||||
|
SwapElements(i, i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pulls one or several elements up to the topmost level(s) in hierarchy (z-index).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="elements">of elements to pull to top</param>
|
||||||
|
public void PullElementsToTop(DrawableContainerList elements)
|
||||||
|
{
|
||||||
|
IDrawableContainer[] dcs = ToArray();
|
||||||
|
for (int i = 0; i < dcs.Length; i++)
|
||||||
|
{
|
||||||
|
IDrawableContainer dc = dcs[i];
|
||||||
|
if (elements.Contains(dc))
|
||||||
|
{
|
||||||
|
Remove(dc);
|
||||||
|
Add(dc);
|
||||||
|
Parent.Modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether the given list of elements can be pushed down,
|
||||||
|
/// i.e. whether there is at least one unselected element lower in hierarchy
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="elements">list of elements to push down</param>
|
||||||
|
/// <returns>true if the elements could be pushed down</returns>
|
||||||
|
public bool CanPushDown(DrawableContainerList elements)
|
||||||
|
{
|
||||||
|
if (elements.Count == 0 || elements.Count == Count)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach (DrawableContainer element in elements)
|
||||||
|
{
|
||||||
|
if (IndexOf(element) >= elements.Count)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushes one or several elements down one level in hierarchy (z-index).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="elements">list of elements to push down</param>
|
||||||
|
public void PushElementsDown(DrawableContainerList elements)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < Count; i++)
|
||||||
|
{
|
||||||
|
IDrawableContainer dc = this[i];
|
||||||
|
if (elements.Contains(dc))
|
||||||
|
{
|
||||||
|
if ((i > 0) && !elements.Contains(this[i - 1]))
|
||||||
|
{
|
||||||
|
SwapElements(i, i - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pushes one or several elements down to the bottommost level(s) in hierarchy (z-index).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="elements">of elements to push to bottom</param>
|
||||||
|
public void PushElementsToBottom(DrawableContainerList elements)
|
||||||
|
{
|
||||||
|
IDrawableContainer[] dcs = ToArray();
|
||||||
|
for (int i = dcs.Length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
IDrawableContainer dc = dcs[i];
|
||||||
|
if (elements.Contains(dc))
|
||||||
|
{
|
||||||
|
Remove(dc);
|
||||||
|
Insert(0, dc);
|
||||||
|
Parent.Modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// swaps two elements in hierarchy (z-index),
|
||||||
|
/// checks both indices to be in range
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="index1">index of the 1st element</param>
|
||||||
|
/// <param name="index2">index of the 2nd element</param>
|
||||||
|
private void SwapElements(int index1, int index2)
|
||||||
|
{
|
||||||
|
if (index1 >= 0 && index1 < Count && index2 >= 0 && index2 < Count && index1 != index2)
|
||||||
|
{
|
||||||
|
IDrawableContainer dc = this[index1];
|
||||||
|
this[index1] = this[index2];
|
||||||
|
this[index2] = dc;
|
||||||
|
Parent.Modified = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add items to a context menu for the selected item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="menu"></param>
|
||||||
|
public virtual void AddContextMenuItems(ContextMenuStrip menu, Surface surface)
|
||||||
|
{
|
||||||
|
bool push = surface.Elements.CanPushDown(this);
|
||||||
|
bool pull = surface.Elements.CanPullUp(this);
|
||||||
|
|
||||||
|
ToolStripMenuItem item;
|
||||||
|
|
||||||
|
// Pull "up"
|
||||||
|
if (pull)
|
||||||
|
{
|
||||||
|
item = new ToolStripMenuItem("Up to top");
|
||||||
|
item.Click += delegate
|
||||||
|
{
|
||||||
|
surface.Elements.PullElementsToTop(this);
|
||||||
|
surface.Elements.Invalidate();
|
||||||
|
};
|
||||||
|
menu.Items.Add(item);
|
||||||
|
item = new ToolStripMenuItem("Up one level");
|
||||||
|
item.Click += delegate
|
||||||
|
{
|
||||||
|
surface.Elements.PullElementsUp(this);
|
||||||
|
surface.Elements.Invalidate();
|
||||||
|
};
|
||||||
|
menu.Items.Add(item);
|
||||||
|
}
|
||||||
|
// Push "down"
|
||||||
|
if (push)
|
||||||
|
{
|
||||||
|
item = new ToolStripMenuItem("Down to bottom");
|
||||||
|
item.Click += delegate
|
||||||
|
{
|
||||||
|
surface.Elements.PushElementsToBottom(this);
|
||||||
|
surface.Elements.Invalidate();
|
||||||
|
};
|
||||||
|
menu.Items.Add(item);
|
||||||
|
item = new ToolStripMenuItem("Down one level");
|
||||||
|
item.Click += delegate
|
||||||
|
{
|
||||||
|
surface.Elements.PushElementsDown(this);
|
||||||
|
surface.Elements.Invalidate();
|
||||||
|
};
|
||||||
|
menu.Items.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Duplicate
|
||||||
|
item = new ToolStripMenuItem("Duplicate selected element");
|
||||||
|
item.Click += delegate
|
||||||
|
{
|
||||||
|
DrawableContainerList dcs = this.Clone();
|
||||||
|
dcs.Parent = surface;
|
||||||
|
dcs.MoveBy(10, 10);
|
||||||
|
surface.AddElements(dcs);
|
||||||
|
surface.DeselectAllElements();
|
||||||
|
surface.SelectElements(dcs);
|
||||||
|
};
|
||||||
|
menu.Items.Add(item);
|
||||||
|
|
||||||
|
// Copy
|
||||||
|
item = new ToolStripMenuItem("Copy");
|
||||||
|
item.Image = ((Image)(editorFormResources.GetObject("copyToolStripMenuItem.Image")));
|
||||||
|
item.Click += delegate
|
||||||
|
{
|
||||||
|
ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), this);
|
||||||
|
};
|
||||||
|
menu.Items.Add(item);
|
||||||
|
|
||||||
|
// Cut
|
||||||
|
item = new ToolStripMenuItem("Cut");
|
||||||
|
item.Image = ((Image)(editorFormResources.GetObject("btnCut.Image")));
|
||||||
|
item.Click += delegate
|
||||||
|
{
|
||||||
|
ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), this);
|
||||||
|
List<DrawableContainer> containersToDelete = new List<DrawableContainer>();
|
||||||
|
foreach (DrawableContainer container in this)
|
||||||
|
{
|
||||||
|
containersToDelete.Add(container);
|
||||||
|
}
|
||||||
|
foreach (DrawableContainer container in containersToDelete)
|
||||||
|
{
|
||||||
|
surface.RemoveElement(container, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
menu.Items.Add(item);
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
item = new ToolStripMenuItem("Delete");
|
||||||
|
item.Image = ((Image)(editorFormResources.GetObject("removeObjectToolStripMenuItem.Image")));
|
||||||
|
item.Click += delegate
|
||||||
|
{
|
||||||
|
List<DrawableContainer> containersToDelete = new List<DrawableContainer>();
|
||||||
|
foreach (DrawableContainer container in this)
|
||||||
|
{
|
||||||
|
containersToDelete.Add(container);
|
||||||
|
}
|
||||||
|
foreach (DrawableContainer container in containersToDelete)
|
||||||
|
{
|
||||||
|
surface.RemoveElement(container, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
menu.Items.Add(item);
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
bool canReset = false;
|
||||||
|
foreach (DrawableContainer container in this)
|
||||||
|
{
|
||||||
|
if (container.hasDefaultSize)
|
||||||
|
{
|
||||||
|
canReset = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (canReset)
|
||||||
|
{
|
||||||
|
item = new ToolStripMenuItem("Reset size");
|
||||||
|
//item.Image = ((System.Drawing.Image)(editorFormResources.GetObject("removeObjectToolStripMenuItem.Image")));
|
||||||
|
item.Click += delegate
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer container in this)
|
||||||
|
{
|
||||||
|
if (container.hasDefaultSize)
|
||||||
|
{
|
||||||
|
Size defaultSize = container.DefaultSize;
|
||||||
|
container.Invalidate();
|
||||||
|
container.MakeBoundsChangeUndoable(false);
|
||||||
|
container.Width = defaultSize.Width;
|
||||||
|
container.Height = defaultSize.Height;
|
||||||
|
container.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
menu.Items.Add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void ShowContextMenu(MouseEventArgs e, Surface surface)
|
||||||
|
{
|
||||||
|
bool hasMenu = false;
|
||||||
|
foreach (DrawableContainer container in this)
|
||||||
|
{
|
||||||
|
if (container.hasContextMenu)
|
||||||
|
{
|
||||||
|
hasMenu = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasMenu)
|
||||||
|
{
|
||||||
|
ContextMenuStrip menu = new ContextMenuStrip();
|
||||||
|
AddContextMenuItems(menu, surface);
|
||||||
|
if (menu.Items.Count > 0)
|
||||||
|
{
|
||||||
|
menu.Show(surface, e.Location);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (menu.Visible)
|
||||||
|
{
|
||||||
|
Application.DoEvents();
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
menu.Dispose();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
136
GreenshotImageEditor/Drawing/EllipseContainer.cs
Normal file
136
GreenshotImageEditor/Drawing/EllipseContainer.cs
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Drawing.Fields;
|
||||||
|
using Greenshot.Helpers;
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Description of EllipseContainer.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable()]
|
||||||
|
public class EllipseContainer : DrawableContainer
|
||||||
|
{
|
||||||
|
public EllipseContainer(Surface parent)
|
||||||
|
: base(parent)
|
||||||
|
{
|
||||||
|
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
|
||||||
|
AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
|
||||||
|
AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
|
||||||
|
AddField(GetType(), FieldType.SHADOW, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(Graphics graphics, RenderMode renderMode)
|
||||||
|
{
|
||||||
|
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||||
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
|
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||||
|
|
||||||
|
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||||
|
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||||
|
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||||
|
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||||
|
bool lineVisible = (lineThickness > 0 && Colors.IsVisible(lineColor));
|
||||||
|
// draw shadow before anything else
|
||||||
|
if (shadow && (lineVisible || Colors.IsVisible(fillColor)))
|
||||||
|
{
|
||||||
|
int basealpha = 100;
|
||||||
|
int alpha = basealpha;
|
||||||
|
int steps = 5;
|
||||||
|
int currentStep = lineVisible ? 1 : 0;
|
||||||
|
while (currentStep <= steps)
|
||||||
|
{
|
||||||
|
using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100)))
|
||||||
|
{
|
||||||
|
shadowPen.Width = lineVisible ? lineThickness : 1;
|
||||||
|
Rectangle shadowRect = GuiRectangle.GetGuiRectangle(Left + currentStep, Top + currentStep, Width, Height);
|
||||||
|
graphics.DrawEllipse(shadowPen, shadowRect);
|
||||||
|
currentStep++;
|
||||||
|
alpha = alpha - basealpha / steps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//draw the original shape
|
||||||
|
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||||
|
if (Colors.IsVisible(fillColor))
|
||||||
|
{
|
||||||
|
using (Brush brush = new SolidBrush(fillColor))
|
||||||
|
{
|
||||||
|
graphics.FillEllipse(brush, rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lineVisible)
|
||||||
|
{
|
||||||
|
using (Pen pen = new Pen(lineColor, lineThickness))
|
||||||
|
{
|
||||||
|
graphics.DrawEllipse(pen, rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Contains(int x, int y)
|
||||||
|
{
|
||||||
|
double xDistanceFromCenter = x - (Left + Width / 2);
|
||||||
|
double yDistanceFromCenter = y - (Top + Height / 2);
|
||||||
|
// ellipse: x^2/a^2 + y^2/b^2 = 1
|
||||||
|
return Math.Pow(xDistanceFromCenter, 2) / Math.Pow(Width / 2, 2) + Math.Pow(yDistanceFromCenter, 2) / Math.Pow(Height / 2, 2) < 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool ClickableAt(int x, int y)
|
||||||
|
{
|
||||||
|
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||||
|
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10;
|
||||||
|
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||||
|
|
||||||
|
// If we clicked inside the rectangle and it's visible we are clickable at.
|
||||||
|
if (!Color.Transparent.Equals(fillColor))
|
||||||
|
{
|
||||||
|
if (Contains(x, y))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the rest of the lines
|
||||||
|
if (lineThickness > 0)
|
||||||
|
{
|
||||||
|
using (Pen pen = new Pen(Color.White, lineThickness))
|
||||||
|
{
|
||||||
|
using (GraphicsPath path = new GraphicsPath())
|
||||||
|
{
|
||||||
|
path.AddEllipse(rect);
|
||||||
|
return path.IsOutlineVisible(x, y, pen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
203
GreenshotImageEditor/Drawing/Fields/AbstractFieldHolder.cs
Normal file
203
GreenshotImageEditor/Drawing/Fields/AbstractFieldHolder.cs
Normal file
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Configuration;
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using GreenshotPlugin;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Basic IFieldHolder implementation, providing access to a set of fields
|
||||||
|
/// </summary>
|
||||||
|
[Serializable()]
|
||||||
|
public abstract class AbstractFieldHolder : IFieldHolder
|
||||||
|
{
|
||||||
|
private static EditorConfiguration editorConfiguration = IniConfig.GetIniSection<EditorConfiguration>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// called when a field's value has changed
|
||||||
|
/// </summary>
|
||||||
|
[NonSerialized]
|
||||||
|
private FieldChangedEventHandler fieldChanged;
|
||||||
|
public event FieldChangedEventHandler FieldChanged
|
||||||
|
{
|
||||||
|
add { fieldChanged += value; }
|
||||||
|
remove { fieldChanged -= value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// we keep to Coolections of our fields, dictionary for quick access, list for serialization
|
||||||
|
// this allows us to use default serialization
|
||||||
|
[NonSerialized]
|
||||||
|
private Dictionary<FieldType, Field> fieldsByType = new Dictionary<FieldType, Field>();
|
||||||
|
private List<Field> fields = new List<Field>();
|
||||||
|
|
||||||
|
public AbstractFieldHolder()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[OnDeserialized()]
|
||||||
|
private void OnDeserialized(StreamingContext context)
|
||||||
|
{
|
||||||
|
fieldsByType = new Dictionary<FieldType, Field>();
|
||||||
|
// listen to changing properties
|
||||||
|
foreach (Field field in fields)
|
||||||
|
{
|
||||||
|
field.PropertyChanged += delegate
|
||||||
|
{
|
||||||
|
if (fieldChanged != null)
|
||||||
|
{
|
||||||
|
fieldChanged(this, new FieldChangedEventArgs(field));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fieldsByType[field.FieldType] = field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddField(Type requestingType, FieldType fieldType, object fieldValue)
|
||||||
|
{
|
||||||
|
AddField(editorConfiguration.CreateField(requestingType, fieldType, fieldValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void AddField(Field field)
|
||||||
|
{
|
||||||
|
if (fieldsByType != null && 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));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Field> GetFields()
|
||||||
|
{
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field GetField(FieldType fieldType)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return fieldsByType[fieldType];
|
||||||
|
}
|
||||||
|
catch (KeyNotFoundException e)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GetFieldValue(FieldType fieldType)
|
||||||
|
{
|
||||||
|
return GetField(fieldType).Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region convenience methods to save us some casts outside
|
||||||
|
|
||||||
|
public string GetFieldValueAsString(FieldType fieldType)
|
||||||
|
{
|
||||||
|
return Convert.ToString(GetFieldValue(fieldType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetFieldValueAsInt(FieldType fieldType)
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(GetFieldValue(fieldType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public decimal GetFieldValueAsDecimal(FieldType fieldType)
|
||||||
|
{
|
||||||
|
return Convert.ToDecimal(GetFieldValue(fieldType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public double GetFieldValueAsDouble(FieldType fieldType)
|
||||||
|
{
|
||||||
|
return Convert.ToDouble(GetFieldValue(fieldType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public float GetFieldValueAsFloat(FieldType fieldType)
|
||||||
|
{
|
||||||
|
return Convert.ToSingle(GetFieldValue(fieldType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetFieldValueAsBool(FieldType fieldType)
|
||||||
|
{
|
||||||
|
return Convert.ToBoolean(GetFieldValue(fieldType));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color GetFieldValueAsColor(FieldType fieldType)
|
||||||
|
{
|
||||||
|
return (Color)GetFieldValue(fieldType);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion convenience methods to save us some casts outside
|
||||||
|
|
||||||
|
public bool HasField(FieldType fieldType)
|
||||||
|
{
|
||||||
|
return fieldsByType.ContainsKey(fieldType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasFieldValue(FieldType 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnFieldChanged(object sender, FieldChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (fieldChanged != null)
|
||||||
|
{
|
||||||
|
fieldChanged(sender, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,143 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Basic IFieldHolderWithChildren implementation. Similar to IFieldHolder,
|
||||||
|
/// but has a List<IFieldHolder> of children.
|
||||||
|
/// Field values are passed to and from children as well.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable()]
|
||||||
|
public abstract class AbstractFieldHolderWithChildren : AbstractFieldHolder
|
||||||
|
{
|
||||||
|
private FieldChangedEventHandler fieldChangedEventHandler;
|
||||||
|
|
||||||
|
[NonSerialized]
|
||||||
|
private EventHandler childrenChanged;
|
||||||
|
public event EventHandler ChildrenChanged
|
||||||
|
{
|
||||||
|
add { childrenChanged += value; }
|
||||||
|
remove { childrenChanged -= value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<IFieldHolder> Children = new List<IFieldHolder>();
|
||||||
|
|
||||||
|
public AbstractFieldHolderWithChildren()
|
||||||
|
{
|
||||||
|
fieldChangedEventHandler = OnFieldChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
[OnDeserialized()]
|
||||||
|
private void OnDeserialized(StreamingContext context)
|
||||||
|
{
|
||||||
|
// listen to changing properties
|
||||||
|
foreach (IFieldHolder fieldHolder in Children)
|
||||||
|
{
|
||||||
|
fieldHolder.FieldChanged += fieldChangedEventHandler;
|
||||||
|
}
|
||||||
|
if (childrenChanged != null) childrenChanged(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddChild(IFieldHolder fieldHolder)
|
||||||
|
{
|
||||||
|
Children.Add(fieldHolder);
|
||||||
|
fieldHolder.FieldChanged += fieldChangedEventHandler;
|
||||||
|
if (childrenChanged != null) childrenChanged(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveChild(IFieldHolder fieldHolder)
|
||||||
|
{
|
||||||
|
Children.Remove(fieldHolder);
|
||||||
|
fieldHolder.FieldChanged -= fieldChangedEventHandler;
|
||||||
|
if (childrenChanged != null) childrenChanged(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public new List<Field> GetFields()
|
||||||
|
{
|
||||||
|
List<Field> ret = new List<Field>();
|
||||||
|
ret.AddRange(base.GetFields());
|
||||||
|
foreach (IFieldHolder fh in Children)
|
||||||
|
{
|
||||||
|
ret.AddRange(fh.GetFields());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public new Field GetField(FieldType fieldType)
|
||||||
|
{
|
||||||
|
Field ret = null;
|
||||||
|
if (base.HasField(fieldType))
|
||||||
|
{
|
||||||
|
ret = base.GetField(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());
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public new bool HasField(FieldType fieldType)
|
||||||
|
{
|
||||||
|
bool ret = base.HasField(fieldType);
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
foreach (IFieldHolder fh in Children)
|
||||||
|
{
|
||||||
|
if (fh.HasField(fieldType))
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public new bool HasFieldValue(FieldType fieldType)
|
||||||
|
{
|
||||||
|
Field 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields.Binding
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Basic IBindingConverter implementation
|
||||||
|
/// </summary>
|
||||||
|
public abstract class AbstractBindingConverter<T1, T2> : IBindingConverter
|
||||||
|
{
|
||||||
|
public AbstractBindingConverter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public object convert(object o)
|
||||||
|
{
|
||||||
|
if (o == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else if (o is T1)
|
||||||
|
{
|
||||||
|
return convert((T1)o);
|
||||||
|
}
|
||||||
|
else if (o is T2)
|
||||||
|
{
|
||||||
|
return convert((T2)o);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Cannot handle argument of type " + o.GetType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract T2 convert(T1 o);
|
||||||
|
|
||||||
|
protected abstract T1 convert(T2 o);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Plugin;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields.Binding
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converting horizontal alignment to its StringAlignment representation and vice versa.
|
||||||
|
/// Beware: there's currently no RTL support.
|
||||||
|
/// </summary>
|
||||||
|
public class HorizontalAlignmentConverter : AbstractBindingConverter<HorizontalAlignment, StringAlignment>
|
||||||
|
{
|
||||||
|
private static HorizontalAlignmentConverter uniqueInstance;
|
||||||
|
|
||||||
|
protected override HorizontalAlignment convert(StringAlignment stringAlignment)
|
||||||
|
{
|
||||||
|
switch (stringAlignment)
|
||||||
|
{
|
||||||
|
case StringAlignment.Near: return HorizontalAlignment.Left;
|
||||||
|
case StringAlignment.Center: return HorizontalAlignment.Center;
|
||||||
|
case StringAlignment.Far: return HorizontalAlignment.Right;
|
||||||
|
default: throw new NotImplementedException("Cannot handle: " + stringAlignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override StringAlignment convert(HorizontalAlignment horizontalAligment)
|
||||||
|
{
|
||||||
|
switch (horizontalAligment)
|
||||||
|
{
|
||||||
|
case HorizontalAlignment.Left: return StringAlignment.Near;
|
||||||
|
case HorizontalAlignment.Center: return StringAlignment.Center;
|
||||||
|
case HorizontalAlignment.Right: return StringAlignment.Far;
|
||||||
|
default: throw new NotImplementedException("Cannot handle: " + horizontalAligment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HorizontalAlignmentConverter GetInstance()
|
||||||
|
{
|
||||||
|
if (uniqueInstance == null) uniqueInstance = new HorizontalAlignmentConverter();
|
||||||
|
return uniqueInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converting vertical alignment to its StringAlignment representation and vice versa.
|
||||||
|
/// </summary>
|
||||||
|
public class VerticalAlignmentConverter : AbstractBindingConverter<VerticalAlignment, StringAlignment>
|
||||||
|
{
|
||||||
|
private static VerticalAlignmentConverter uniqueInstance;
|
||||||
|
|
||||||
|
protected override VerticalAlignment convert(StringAlignment stringAlignment)
|
||||||
|
{
|
||||||
|
switch (stringAlignment)
|
||||||
|
{
|
||||||
|
case StringAlignment.Near: return VerticalAlignment.TOP;
|
||||||
|
case StringAlignment.Center: return VerticalAlignment.CENTER;
|
||||||
|
case StringAlignment.Far: return VerticalAlignment.BOTTOM;
|
||||||
|
default: throw new NotImplementedException("Cannot handle: " + stringAlignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override StringAlignment convert(VerticalAlignment verticalAligment)
|
||||||
|
{
|
||||||
|
switch (verticalAligment)
|
||||||
|
{
|
||||||
|
case VerticalAlignment.TOP: return StringAlignment.Near;
|
||||||
|
case VerticalAlignment.CENTER: return StringAlignment.Center;
|
||||||
|
case VerticalAlignment.BOTTOM: return StringAlignment.Far;
|
||||||
|
default: throw new NotImplementedException("Cannot handle: " + verticalAligment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VerticalAlignmentConverter GetInstance()
|
||||||
|
{
|
||||||
|
if (uniqueInstance == null) uniqueInstance = new VerticalAlignmentConverter();
|
||||||
|
return uniqueInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,180 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields.Binding
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Bidirectional binding of properties of two INotifyPropertyChanged instances.
|
||||||
|
/// This implementation synchronizes null values, too. If you do not want this
|
||||||
|
/// behavior (e.g. when binding to a
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not null values are passed on to the other object.
|
||||||
|
/// </summary>
|
||||||
|
protected bool AllowSynchronizeNull = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bind properties of two objects bidirectionally
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="object1">Object containing 1st property to bind</param>
|
||||||
|
/// <param name="property1">Property of 1st object to bind</param>
|
||||||
|
/// <param name="object2">Object containing 2nd property to bind</param>
|
||||||
|
/// <param name="property2">Property of 2nd object to bind</param>
|
||||||
|
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName)
|
||||||
|
{
|
||||||
|
this.controlObject = controlObject;
|
||||||
|
this.fieldObject = fieldObject;
|
||||||
|
this.controlPropertyName = controlPropertyName;
|
||||||
|
this.fieldPropertyName = fieldPropertyName;
|
||||||
|
|
||||||
|
this.controlObject.PropertyChanged += ControlPropertyChanged;
|
||||||
|
this.fieldObject.PropertyChanged += FieldPropertyChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bind properties of two objects bidirectionally, converting the values using a converter
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="controlObject">Object containing 1st property to bind</param>
|
||||||
|
/// <param name="controlPropertyName">Property of 1st object to bind</param>
|
||||||
|
/// <param name="fieldObject">Object containing 2nd property to bind</param>
|
||||||
|
/// <param name="fieldPropertyName">Property of 2nd object to bind</param>
|
||||||
|
/// <param name="converter">taking care of converting the synchronzied value to the correct target format and back</param>
|
||||||
|
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter)
|
||||||
|
: this(controlObject, controlPropertyName, fieldObject, fieldPropertyName)
|
||||||
|
{
|
||||||
|
this.converter = converter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bind properties of two objects bidirectionally, converting the values using a converter.
|
||||||
|
/// Synchronization can be intercepted by adding a validator.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="controlObject">Object containing 1st property to bind</param>
|
||||||
|
/// <param name="controlPropertyName">Property of 1st object to bind</param>
|
||||||
|
/// <param name="fieldObject">Object containing 2nd property to bind</param>
|
||||||
|
/// <param name="fieldPropertyName">Property of 2nd object to bind</param>
|
||||||
|
/// <param name="validator">validator to intercept synchronisation if the value does not match certain criteria</param>
|
||||||
|
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingValidator validator)
|
||||||
|
: this(controlObject, controlPropertyName, fieldObject, fieldPropertyName)
|
||||||
|
{
|
||||||
|
this.validator = validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Bind properties of two objects bidirectionally, converting the values using a converter.
|
||||||
|
/// Synchronization can be intercepted by adding a validator.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="controlObject">Object containing 1st property to bind</param>
|
||||||
|
/// <param name="controlPropertyName">Property of 1st object to bind</param>
|
||||||
|
/// <param name="fieldObject">Object containing 2nd property to bind</param>
|
||||||
|
/// <param name="fieldPropertyName">Property of 2nd object to bind</param>
|
||||||
|
/// <param name="converter">taking care of converting the synchronzied value to the correct target format and back</param>
|
||||||
|
/// <param name="validator">validator to intercept synchronisation if the value does not match certain criteria</param>
|
||||||
|
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName, IBindingConverter converter, IBindingValidator validator)
|
||||||
|
: this(controlObject, controlPropertyName, fieldObject, fieldPropertyName, converter)
|
||||||
|
{
|
||||||
|
this.validator = validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ControlPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PropertyInfo resolvePropertyInfo(object obj, string property)
|
||||||
|
{
|
||||||
|
PropertyInfo ret = null;
|
||||||
|
string[] properties = property.Split(".".ToCharArray());
|
||||||
|
for (int i = 0; i < properties.Length; i++)
|
||||||
|
{
|
||||||
|
string prop = properties[i];
|
||||||
|
ret = obj.GetType().GetProperty(prop);
|
||||||
|
if (ret != null && ret.CanRead && i < prop.Length - 1)
|
||||||
|
{
|
||||||
|
obj = ret.GetValue(obj, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBindingConverter Converter
|
||||||
|
{
|
||||||
|
get { return converter; }
|
||||||
|
set { converter = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields.Binding
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converts decimal to double (%) and vice versa, e.g. 95f <---> 0.95d
|
||||||
|
/// </summary>
|
||||||
|
public class DecimalDoublePercentageConverter : AbstractBindingConverter<double, decimal>
|
||||||
|
{
|
||||||
|
private static DecimalDoublePercentageConverter uniqueInstance;
|
||||||
|
|
||||||
|
private DecimalDoublePercentageConverter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override decimal convert(double o)
|
||||||
|
{
|
||||||
|
return Convert.ToDecimal(o) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override double convert(decimal o)
|
||||||
|
{
|
||||||
|
return Convert.ToDouble(o) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DecimalDoublePercentageConverter GetInstance()
|
||||||
|
{
|
||||||
|
if (uniqueInstance == null) uniqueInstance = new DecimalDoublePercentageConverter();
|
||||||
|
return uniqueInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields.Binding
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converts decimal to float and vice versa.
|
||||||
|
/// </summary>
|
||||||
|
public class DecimalFloatConverter : AbstractBindingConverter<float, decimal>
|
||||||
|
{
|
||||||
|
private static DecimalFloatConverter uniqueInstance;
|
||||||
|
|
||||||
|
private DecimalFloatConverter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override decimal convert(float o)
|
||||||
|
{
|
||||||
|
return Convert.ToDecimal(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override float convert(decimal o)
|
||||||
|
{
|
||||||
|
return Convert.ToInt16(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DecimalFloatConverter GetInstance()
|
||||||
|
{
|
||||||
|
if (uniqueInstance == null) uniqueInstance = new DecimalFloatConverter();
|
||||||
|
return uniqueInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields.Binding
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Converts decimal to int and vice versa.
|
||||||
|
/// </summary>
|
||||||
|
public class DecimalIntConverter : AbstractBindingConverter<int, decimal>
|
||||||
|
{
|
||||||
|
private static DecimalIntConverter uniqueInstance;
|
||||||
|
|
||||||
|
private DecimalIntConverter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override decimal convert(int o)
|
||||||
|
{
|
||||||
|
return Convert.ToDecimal(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override int convert(decimal o)
|
||||||
|
{
|
||||||
|
return Convert.ToInt16(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DecimalIntConverter GetInstance()
|
||||||
|
{
|
||||||
|
if (uniqueInstance == null) uniqueInstance = new DecimalIntConverter();
|
||||||
|
return uniqueInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields.Binding
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for a bidirectional converter, for use with BidirectionalBinding.
|
||||||
|
/// convert(object) implementation must deal with both directions.
|
||||||
|
/// see DecimalIntConverter
|
||||||
|
/// </summary>
|
||||||
|
public interface IBindingConverter
|
||||||
|
{
|
||||||
|
object convert(object o);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields.Binding
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for a bidirectional validator, for use with BidirectionalBinding.
|
||||||
|
/// Useful if you do not want to synchronize values which would be illegal on
|
||||||
|
/// one of the bound objects (e.g. null value on some form components)
|
||||||
|
/// see NotNullValidator
|
||||||
|
/// </summary>
|
||||||
|
public interface IBindingValidator
|
||||||
|
{
|
||||||
|
bool validate(object o);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields.Binding
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Validates a value not to be null.
|
||||||
|
/// </summary>
|
||||||
|
public class NotNullValidator : IBindingValidator
|
||||||
|
{
|
||||||
|
private static NotNullValidator uniqueInstance;
|
||||||
|
|
||||||
|
private NotNullValidator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool validate(object o)
|
||||||
|
{
|
||||||
|
return o != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NotNullValidator GetInstance()
|
||||||
|
{
|
||||||
|
if (uniqueInstance == null) uniqueInstance = new NotNullValidator();
|
||||||
|
return uniqueInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
151
GreenshotImageEditor/Drawing/Fields/Field.cs
Normal file
151
GreenshotImageEditor/Drawing/Fields/Field.cs
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a single field of a drawable element, i.e.
|
||||||
|
/// line thickness of a rectangle.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class Field : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
[field: NonSerialized]
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
public object myValue;
|
||||||
|
public object Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return myValue;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!Equals(myValue, value))
|
||||||
|
{
|
||||||
|
myValue = value;
|
||||||
|
if (PropertyChanged != null)
|
||||||
|
{
|
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs("Value"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public FieldType FieldType;
|
||||||
|
public string Scope;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs a new Field instance, usually you should be using FieldFactory
|
||||||
|
/// to create Fields.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fieldType">FieldType of the Field to be created</param>
|
||||||
|
/// <param name="scope">The scope to which the value of this Field is relevant.
|
||||||
|
/// Depending on the scope the Field's value may be shared for other elements
|
||||||
|
/// containing the same FieldType for defaulting to the last used value.
|
||||||
|
/// 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))
|
||||||
|
/// </param>
|
||||||
|
public Field(FieldType fieldType, Type scope)
|
||||||
|
{
|
||||||
|
FieldType = fieldType;
|
||||||
|
Scope = scope.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field(FieldType fieldType, string scope)
|
||||||
|
{
|
||||||
|
FieldType = fieldType;
|
||||||
|
Scope = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Field(FieldType fieldType)
|
||||||
|
{
|
||||||
|
FieldType = fieldType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this field holds a value other than null.
|
||||||
|
/// </summary>
|
||||||
|
public bool HasValue
|
||||||
|
{
|
||||||
|
get { return Value != null; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a flat clone of this Field. The fields value itself is not cloned.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Field Clone()
|
||||||
|
{
|
||||||
|
Field ret = new Field(FieldType, Scope);
|
||||||
|
ret.Value = Value;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
int hashCode = 0;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EventHandler to be used when a field value changes
|
||||||
|
/// </summary>
|
||||||
|
public delegate void FieldChangedEventHandler(object sender, FieldChangedEventArgs e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// EventArgs to be used with FieldChangedEventHandler
|
||||||
|
/// </summary>
|
||||||
|
public class FieldChangedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public readonly Field Field;
|
||||||
|
|
||||||
|
public FieldChangedEventArgs(Field field)
|
||||||
|
{
|
||||||
|
Field = field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
218
GreenshotImageEditor/Drawing/Fields/FieldAggregator.cs
Normal file
218
GreenshotImageEditor/Drawing/Fields/FieldAggregator.cs
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Configuration;
|
||||||
|
using Greenshot.IniFile;
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the current set of properties for the editor.
|
||||||
|
/// When one of EditorProperties' properties is updated, the change will be promoted
|
||||||
|
/// to all bound elements.
|
||||||
|
/// * If an element is selected:
|
||||||
|
/// This class represents the element's properties
|
||||||
|
/// * I n>1 elements are selected:
|
||||||
|
/// This class represents the properties of all elements.
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
public class FieldAggregator : AbstractFieldHolder
|
||||||
|
{
|
||||||
|
private List<IDrawableContainer> boundContainers;
|
||||||
|
private bool internalUpdateRunning = false;
|
||||||
|
|
||||||
|
private enum Status { IDLE, BINDING, UPDATING };
|
||||||
|
|
||||||
|
private static EditorConfiguration editorConfiguration = IniConfig.GetIniSection<EditorConfiguration>();
|
||||||
|
|
||||||
|
public FieldAggregator()
|
||||||
|
{
|
||||||
|
foreach (FieldType fieldType in FieldType.Values)
|
||||||
|
{
|
||||||
|
Field field = new Field(fieldType, GetType());
|
||||||
|
AddField(field);
|
||||||
|
}
|
||||||
|
boundContainers = new List<IDrawableContainer>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddField(Field field)
|
||||||
|
{
|
||||||
|
base.AddField(field);
|
||||||
|
field.PropertyChanged += OwnPropertyChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BindElements(DrawableContainerList dcs)
|
||||||
|
{
|
||||||
|
foreach (DrawableContainer dc in dcs)
|
||||||
|
{
|
||||||
|
BindElement(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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BindAndUpdateElement(IDrawableContainer dc)
|
||||||
|
{
|
||||||
|
UpdateElement(dc);
|
||||||
|
BindElement(dc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateElement(IDrawableContainer dc)
|
||||||
|
{
|
||||||
|
DrawableContainer container = dc as DrawableContainer;
|
||||||
|
if (container == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
internalUpdateRunning = true;
|
||||||
|
foreach (Field 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnbindElement(IDrawableContainer dc)
|
||||||
|
{
|
||||||
|
if (boundContainers.Contains(dc))
|
||||||
|
{
|
||||||
|
boundContainers.Remove(dc);
|
||||||
|
UpdateFromBoundElements();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
ClearFields();
|
||||||
|
boundContainers.Clear();
|
||||||
|
UpdateFromBoundElements();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// sets all field values to null, however does not remove fields
|
||||||
|
/// </summary>
|
||||||
|
private void ClearFields()
|
||||||
|
{
|
||||||
|
internalUpdateRunning = true;
|
||||||
|
foreach (Field field in GetFields())
|
||||||
|
{
|
||||||
|
field.Value = null;
|
||||||
|
}
|
||||||
|
internalUpdateRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateFromBoundElements()
|
||||||
|
{
|
||||||
|
ClearFields();
|
||||||
|
internalUpdateRunning = true;
|
||||||
|
foreach (Field field in FindCommonFields())
|
||||||
|
{
|
||||||
|
SetFieldValue(field.FieldType, field.Value);
|
||||||
|
}
|
||||||
|
internalUpdateRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Field> FindCommonFields()
|
||||||
|
{
|
||||||
|
List<Field> 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)
|
||||||
|
{
|
||||||
|
returnFields = leastSelectedContainer.GetFields();
|
||||||
|
for (int i = 0; i < boundContainers.Count - 1; i++)
|
||||||
|
{
|
||||||
|
DrawableContainer dc = boundContainers[i] as DrawableContainer;
|
||||||
|
if (dc != null)
|
||||||
|
{
|
||||||
|
List<Field> fieldsToRemove = new List<Field>();
|
||||||
|
foreach (Field f in returnFields)
|
||||||
|
{
|
||||||
|
// ... throw out those that do not apply to one of the other containers
|
||||||
|
if (!dc.HasField(f.FieldType))
|
||||||
|
{
|
||||||
|
fieldsToRemove.Add(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (Field f in fieldsToRemove)
|
||||||
|
{
|
||||||
|
returnFields.Remove(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (returnFields == null)
|
||||||
|
{
|
||||||
|
returnFields = new List<Field>();
|
||||||
|
}
|
||||||
|
return returnFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
125
GreenshotImageEditor/Drawing/Fields/FieldType.cs
Normal file
125
GreenshotImageEditor/Drawing/Fields/FieldType.cs
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines all FieldTypes + their default value.
|
||||||
|
/// (The additional value is why this is not an enum)
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class FieldType
|
||||||
|
{
|
||||||
|
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[]{
|
||||||
|
ARROWHEADS,
|
||||||
|
BLUR_RADIUS,
|
||||||
|
BRIGHTNESS,
|
||||||
|
FILL_COLOR,
|
||||||
|
FONT_BOLD,
|
||||||
|
FONT_FAMILY,
|
||||||
|
FONT_ITALIC,
|
||||||
|
FONT_SIZE,
|
||||||
|
TEXT_HORIZONTAL_ALIGNMENT,
|
||||||
|
TEXT_VERTICAL_ALIGNMENT,
|
||||||
|
HIGHLIGHT_COLOR,
|
||||||
|
LINE_COLOR,
|
||||||
|
LINE_THICKNESS,
|
||||||
|
MAGNIFICATION_FACTOR,
|
||||||
|
PIXEL_SIZE,
|
||||||
|
PREVIEW_QUALITY,
|
||||||
|
SHADOW,
|
||||||
|
PREPARED_FILTER_OBFUSCATE,
|
||||||
|
PREPARED_FILTER_HIGHLIGHT,
|
||||||
|
FLAGS
|
||||||
|
};
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum Flag
|
||||||
|
{
|
||||||
|
NONE = 0,
|
||||||
|
CONFIRMABLE = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name;
|
||||||
|
|
||||||
|
private FieldType(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
int hashCode = 0;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(FieldType a, FieldType b)
|
||||||
|
{
|
||||||
|
return Equals(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(FieldType a, FieldType b)
|
||||||
|
{
|
||||||
|
return !Equals(a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
GreenshotImageEditor/Drawing/Fields/IFieldHolder.cs
Normal file
61
GreenshotImageEditor/Drawing/Fields/IFieldHolder.cs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Fields
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Any element holding Fields must provide access to it.
|
||||||
|
/// AbstractFieldHolder is the basic implementation.
|
||||||
|
/// If you need the fieldHolder to have child fieldHolders,
|
||||||
|
/// you should consider using IFieldHolderWithChildren.
|
||||||
|
/// </summary>
|
||||||
|
public interface IFieldHolder
|
||||||
|
{
|
||||||
|
event FieldChangedEventHandler FieldChanged;
|
||||||
|
|
||||||
|
void AddField(Field field);
|
||||||
|
|
||||||
|
void RemoveField(Field field);
|
||||||
|
|
||||||
|
List<Field> GetFields();
|
||||||
|
|
||||||
|
Field GetField(FieldType fieldType);
|
||||||
|
|
||||||
|
bool HasField(FieldType fieldType);
|
||||||
|
|
||||||
|
void SetFieldValue(FieldType fieldType, object value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extended fieldHolder which has fieldHolder children.
|
||||||
|
/// Implementations should pass field values to and from
|
||||||
|
/// their children.
|
||||||
|
/// AbstractFieldHolderWithChildren is the basic implementation.
|
||||||
|
/// </summary>
|
||||||
|
public interface IFieldHolderWithChildren : IFieldHolder
|
||||||
|
{
|
||||||
|
void AddChild(IFieldHolder fieldHolder);
|
||||||
|
|
||||||
|
void RemoveChild(IFieldHolder fieldHolder);
|
||||||
|
}
|
||||||
|
}
|
94
GreenshotImageEditor/Drawing/FilterContainer.cs
Normal file
94
GreenshotImageEditor/Drawing/FilterContainer.cs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Drawing.Fields;
|
||||||
|
using Greenshot.Helpers;
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// empty container for filter-only elements
|
||||||
|
/// </summary>
|
||||||
|
[Serializable()]
|
||||||
|
public abstract class FilterContainer : DrawableContainer
|
||||||
|
{
|
||||||
|
public enum PreparedFilterMode { OBFUSCATE, HIGHLIGHT };
|
||||||
|
public enum PreparedFilter { BLUR, PIXELIZE, TEXT_HIGHTLIGHT, AREA_HIGHLIGHT, GRAYSCALE, MAGNIFICATION };
|
||||||
|
|
||||||
|
public PreparedFilter Filter
|
||||||
|
{
|
||||||
|
get { return (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public FilterContainer(Surface parent)
|
||||||
|
: base(parent)
|
||||||
|
{
|
||||||
|
AddField(GetType(), FieldType.LINE_THICKNESS, 0);
|
||||||
|
AddField(GetType(), FieldType.LINE_COLOR, Color.Red);
|
||||||
|
AddField(GetType(), FieldType.SHADOW, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(Graphics graphics, RenderMode rm)
|
||||||
|
{
|
||||||
|
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||||
|
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||||
|
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||||
|
bool lineVisible = (lineThickness > 0 && Colors.IsVisible(lineColor));
|
||||||
|
if (lineVisible)
|
||||||
|
{
|
||||||
|
graphics.SmoothingMode = SmoothingMode.HighSpeed;
|
||||||
|
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||||
|
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||||
|
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||||
|
//draw shadow first
|
||||||
|
if (shadow)
|
||||||
|
{
|
||||||
|
int basealpha = 100;
|
||||||
|
int alpha = basealpha;
|
||||||
|
int steps = 5;
|
||||||
|
int currentStep = lineVisible ? 1 : 0;
|
||||||
|
while (currentStep <= steps)
|
||||||
|
{
|
||||||
|
using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness))
|
||||||
|
{
|
||||||
|
Rectangle shadowRect = GuiRectangle.GetGuiRectangle(Left + currentStep, Top + currentStep, Width, Height);
|
||||||
|
graphics.DrawRectangle(shadowPen, shadowRect);
|
||||||
|
currentStep++;
|
||||||
|
alpha = alpha - (basealpha / steps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||||
|
if (lineThickness > 0)
|
||||||
|
{
|
||||||
|
using (Pen pen = new Pen(lineColor, lineThickness))
|
||||||
|
{
|
||||||
|
graphics.DrawRectangle(pen, rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
93
GreenshotImageEditor/Drawing/Filters/AbstractFilter.cs
Normal file
93
GreenshotImageEditor/Drawing/Filters/AbstractFilter.cs
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Drawing.Fields;
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Graphical filter which can be added to DrawableContainer.
|
||||||
|
/// Subclasses should fulfill INotifyPropertyChanged contract, i.e. call
|
||||||
|
/// OnPropertyChanged whenever a public property has been changed.
|
||||||
|
/// </summary>
|
||||||
|
namespace Greenshot.Drawing.Filters
|
||||||
|
{
|
||||||
|
[Serializable()]
|
||||||
|
public abstract class AbstractFilter : AbstractFieldHolder, IFilter
|
||||||
|
{
|
||||||
|
[NonSerialized]
|
||||||
|
private PropertyChangedEventHandler propertyChanged;
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged
|
||||||
|
{
|
||||||
|
add { propertyChanged += value; }
|
||||||
|
remove { propertyChanged -= value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool invert = false;
|
||||||
|
public bool Invert
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return invert;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
invert = value;
|
||||||
|
OnPropertyChanged("Invert");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DrawableContainer parent;
|
||||||
|
public DrawableContainer Parent
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
parent = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractFilter(DrawableContainer parent)
|
||||||
|
{
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DrawableContainer GetParent()
|
||||||
|
{
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
80
GreenshotImageEditor/Drawing/Filters/BlurFilter.cs
Normal file
80
GreenshotImageEditor/Drawing/Filters/BlurFilter.cs
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Drawing.Fields;
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
using GreenshotPlugin.UnmanagedHelpers;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Filters
|
||||||
|
{
|
||||||
|
[Serializable()]
|
||||||
|
public class BlurFilter : AbstractFilter
|
||||||
|
{
|
||||||
|
public double previewQuality;
|
||||||
|
public double PreviewQuality
|
||||||
|
{
|
||||||
|
get { return previewQuality; }
|
||||||
|
set { previewQuality = value; OnPropertyChanged("PreviewQuality"); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlurFilter(DrawableContainer parent)
|
||||||
|
: base(parent)
|
||||||
|
{
|
||||||
|
AddField(GetType(), FieldType.BLUR_RADIUS, 3);
|
||||||
|
AddField(GetType(), FieldType.PREVIEW_QUALITY, 1.0d);
|
||||||
|
}
|
||||||
|
|
||||||
|
public unsafe override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode)
|
||||||
|
{
|
||||||
|
int blurRadius = GetFieldValueAsInt(FieldType.BLUR_RADIUS);
|
||||||
|
double previewQuality = GetFieldValueAsDouble(FieldType.PREVIEW_QUALITY);
|
||||||
|
Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
|
||||||
|
if (applyRect.Width == 0 || applyRect.Height == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
GraphicsState state = graphics.Save();
|
||||||
|
if (Invert)
|
||||||
|
{
|
||||||
|
graphics.SetClip(applyRect);
|
||||||
|
graphics.ExcludeClip(rect);
|
||||||
|
}
|
||||||
|
if (GDIplus.IsBlurPossible(blurRadius))
|
||||||
|
{
|
||||||
|
GDIplus.DrawWithBlur(graphics, applyBitmap, applyRect, null, null, blurRadius, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect))
|
||||||
|
{
|
||||||
|
ImageHelper.ApplyBoxBlur(fastBitmap, blurRadius);
|
||||||
|
fastBitmap.DrawTo(graphics, applyRect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
graphics.Restore(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
70
GreenshotImageEditor/Drawing/Filters/BrightnessFilter.cs
Normal file
70
GreenshotImageEditor/Drawing/Filters/BrightnessFilter.cs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Greenshot - a free and open source screenshot tool
|
||||||
|
* Copyright (C) 2007-2013 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Greenshot.Drawing.Fields;
|
||||||
|
using Greenshot.Plugin.Drawing;
|
||||||
|
using GreenshotPlugin.Core;
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Drawing2D;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
|
||||||
|
namespace Greenshot.Drawing.Filters
|
||||||
|
{
|
||||||
|
[Serializable()]
|
||||||
|
public class BrightnessFilter : AbstractFilter
|
||||||
|
{
|
||||||
|
public BrightnessFilter(DrawableContainer parent)
|
||||||
|
: base(parent)
|
||||||
|
{
|
||||||
|
AddField(GetType(), FieldType.BRIGHTNESS, 0.9d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implements the Apply code for the Brightness Filet
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="graphics"></param>
|
||||||
|
/// <param name="applyBitmap"></param>
|
||||||
|
/// <param name="rect"></param>
|
||||||
|
/// <param name="renderMode"></param>
|
||||||
|
public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode)
|
||||||
|
{
|
||||||
|
Rectangle applyRect = ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
|
||||||
|
|
||||||
|
if (applyRect.Width == 0 || applyRect.Height == 0)
|
||||||
|
{
|
||||||
|
// nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsState state = graphics.Save();
|
||||||
|
if (Invert)
|
||||||
|
{
|
||||||
|
graphics.SetClip(applyRect);
|
||||||
|
graphics.ExcludeClip(rect);
|
||||||
|
}
|
||||||
|
float brightness = GetFieldValueAsFloat(FieldType.BRIGHTNESS);
|
||||||
|
ImageAttributes ia = ImageHelper.CreateAdjustAttributes(brightness, 1f, 1f);
|
||||||
|
graphics.DrawImage(applyBitmap, applyRect, applyRect.X, applyRect.Y, applyRect.Width, applyRect.Height, GraphicsUnit.Pixel, ia);
|
||||||
|
graphics.Restore(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue