mirror of
https://github.com/ShareX/ShareX.git
synced 2024-06-23 08:40:39 +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
|
||||
|
||||
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
|
||||
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
|
||||
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.}
|
||||
Copyright (C) {year} {name of author}
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
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 is free software, and you are welcome to redistribute it
|
||||
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,
|
||||
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
|
||||
{http://www.gnu.org/licenses/}.
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
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
|
||||
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