mirror of
https://github.com/ShareX/ShareX.git
synced 2024-06-28 11:10:23 +12:00
Removed Greenshot image editor
This commit is contained in:
parent
88d362383a
commit
b2e46f617c
|
@ -1,597 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.IniFile;
|
||||
using Greenshot.Plugin;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
public enum ClipboardFormat
|
||||
{
|
||||
PNG, DIB, HTML, HTMLDATAURL, BITMAP, DIBV5
|
||||
}
|
||||
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, INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
[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 = "false")]
|
||||
public bool OutputFileAutoReduceColors;
|
||||
[IniProperty("OutputFileReduceColorsTo", Description = "Amount of colors to reduce to, when reducing", DefaultValue = "256")]
|
||||
public int OutputFileReduceColorsTo;
|
||||
|
||||
[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.")]
|
||||
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 productnames for which GDI capturing is skipped (using fallback).", DefaultValue = "IntelliJ IDEA")]
|
||||
public List<string> NoGDICaptureForProduct;
|
||||
[IniProperty("NoDWMCaptureForProduct", Description = "List of productnames for which DWM capturing is skipped (using fallback).", 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("DisableRDPOptimizing", Description = "Disable all optimizations for usage with remote desktop", DefaultValue = "False")]
|
||||
public bool DisableRDPOptimizing;
|
||||
|
||||
[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("ZoomerOpacity", Description = "Specify the transparency for the zoomer, from 0-1 (where 1 is no transparency and 0 is complete transparent. An usefull setting would be 0.7)", DefaultValue = "1")]
|
||||
public float ZoomerOpacity;
|
||||
|
||||
[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;
|
||||
|
||||
[IniProperty("OptimizePNGCommand", Description = "Optional command to execute on a temporary PNG file, the command should overwrite the file and Greenshot will read it back. Note: this command is also executed when uploading PNG's!", DefaultValue = "")]
|
||||
public string OptimizePNGCommand;
|
||||
[IniProperty("OptimizePNGCommandArguments", Description = "Arguments for the optional command to execute on a PNG, {0} is replaced by the temp-filename from Greenshot. Note: Temp-file is deleted afterwards by Greenshot.", DefaultValue = "\"{0}\"")]
|
||||
public string OptimizePNGCommandArguments;
|
||||
|
||||
[IniProperty("LastSaveWithVersion", Description = "Version of Greenshot which created this .ini")]
|
||||
public string LastSaveWithVersion;
|
||||
|
||||
[IniProperty("ProcessEXIFOrientation", Description = "When reading images from files or clipboard, use the EXIF information to correct the orientation", DefaultValue = "True")]
|
||||
public bool ProcessEXIFOrientation;
|
||||
|
||||
[IniProperty("LastCapturedRegion", Description = "The last used region, for reuse in the capture last region")]
|
||||
public Rectangle LastCapturedRegion;
|
||||
|
||||
private Size _iconSize;
|
||||
[IniProperty("IconSize", Description = "Defines the size of the icons (e.g. for the buttons in the editor), default value 16,16 anything bigger will cause scaling", DefaultValue = "16,16")]
|
||||
public Size IconSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return _iconSize;
|
||||
}
|
||||
set
|
||||
{
|
||||
Size newSize = value;
|
||||
if (newSize != Size.Empty)
|
||||
{
|
||||
if (newSize.Width < 16)
|
||||
{
|
||||
newSize.Width = 16;
|
||||
}
|
||||
else if (newSize.Width > 256)
|
||||
{
|
||||
newSize.Width = 256;
|
||||
}
|
||||
newSize.Width = (newSize.Width / 8) * 8;
|
||||
if (newSize.Height < 16)
|
||||
{
|
||||
newSize.Height = 16;
|
||||
}
|
||||
else if (IconSize.Height > 256)
|
||||
{
|
||||
newSize.Height = 256;
|
||||
}
|
||||
newSize.Height = (newSize.Height / 8) * 8;
|
||||
}
|
||||
if (_iconSize != newSize)
|
||||
{
|
||||
_iconSize = value;
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("IconSize"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[IniProperty("WebRequestTimeout", Description = "The connect timeout value for webrequets, these are seconds", DefaultValue = "100")]
|
||||
public int WebRequestTimeout;
|
||||
[IniProperty("WebRequestReadWriteTimeout", Description = "The read/write timeout value for webrequets, these are seconds", DefaultValue = "100")]
|
||||
public int WebRequestReadWriteTimeout;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies what THIS build is
|
||||
/// </summary>
|
||||
public BuildStates BuildState
|
||||
{
|
||||
get
|
||||
{
|
||||
string informationalVersion = Application.ProductVersion;
|
||||
if (informationalVersion != null)
|
||||
{
|
||||
if (informationalVersion.ToLowerInvariant().Contains("-rc"))
|
||||
{
|
||||
return BuildStates.RELEASE_CANDIDATE;
|
||||
}
|
||||
if (informationalVersion.ToLowerInvariant().Contains("-unstable"))
|
||||
{
|
||||
return BuildStates.UNSTABLE;
|
||||
}
|
||||
}
|
||||
return BuildStates.RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseLargeIcons
|
||||
{
|
||||
get
|
||||
{
|
||||
return IconSize.Width >= 32 || IconSize.Height >= 32;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 before writing the configuration
|
||||
/// </summary>
|
||||
public override void BeforeSave()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Store version, this can be used later to fix settings after an update
|
||||
LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 (string.IsNullOrEmpty(LastSaveWithVersion))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Store version, this can be used later to fix settings after an update
|
||||
LastSaveWithVersion = Assembly.GetEntryAssembly().GetName().Version.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
// Disable the AutoReduceColors as it causes issues with Mozzila applications and some others
|
||||
OutputFileAutoReduceColors = false;
|
||||
}
|
||||
|
||||
// Enable OneNote if upgrading from 1.1
|
||||
if (ExcludeDestinations != null && ExcludeDestinations.Contains("OneNote"))
|
||||
{
|
||||
if (LastSaveWithVersion != null && LastSaveWithVersion.StartsWith("1.1"))
|
||||
{
|
||||
ExcludeDestinations.Remove("OneNote");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove with the release
|
||||
ExcludeDestinations.Remove("OneNote");
|
||||
}
|
||||
}
|
||||
|
||||
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 >= 2)
|
||||
{
|
||||
if ("intellij".Equals(NoGDICaptureForProduct[0]) && "idea".Equals(NoGDICaptureForProduct[1]))
|
||||
{
|
||||
NoGDICaptureForProduct.RemoveRange(0, 2);
|
||||
NoGDICaptureForProduct.Add("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 >= 3)
|
||||
{
|
||||
if ("citrix".Equals(NoDWMCaptureForProduct[0]) && "ica".Equals(NoDWMCaptureForProduct[1]) && "client".Equals(NoDWMCaptureForProduct[2]))
|
||||
{
|
||||
NoDWMCaptureForProduct.RemoveRange(0, 3);
|
||||
NoDWMCaptureForProduct.Add("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;
|
||||
}
|
||||
if (OutputFileReduceColorsTo < 2)
|
||||
{
|
||||
OutputFileReduceColorsTo = 2;
|
||||
}
|
||||
if (OutputFileReduceColorsTo > 256)
|
||||
{
|
||||
OutputFileReduceColorsTo = 256;
|
||||
}
|
||||
|
||||
if (WebRequestTimeout <= 10)
|
||||
{
|
||||
WebRequestTimeout = 100;
|
||||
}
|
||||
if (WebRequestReadWriteTimeout < 1)
|
||||
{
|
||||
WebRequestReadWriteTimeout = 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,166 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Core;
|
||||
using Greenshot.Drawing.Fields;
|
||||
using Greenshot.IniFile;
|
||||
using Greenshot.Plugin;
|
||||
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("DefaultDrawingMode", Separator = "|", Description = "Default drawing mode:None,Rect,Ellipse,Line,Arrow,Path,Text,SpeechBubble,StepLabel,Highlight,Obfuscate,Crop", DefaultValue = "Rect", FixedValue = true)]
|
||||
public DrawingModes DefaultDrawingMode;
|
||||
[IniProperty("RememberLastDrawingMode", Description = "Remember last drawing mode used and select it next time", DefaultValue = "False")]
|
||||
public bool RememberLastDrawingMode;
|
||||
[IniProperty("LastDrawingMode", Separator = "|", Description = "Last drawing mode used", DefaultValue = "Rect")]
|
||||
public DrawingModes LastDrawingMode;
|
||||
|
||||
[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("MaximizeWhenLargeImage", Description = "Maximize the editor window when image is larger than the working area", DefaultValue = "False")]
|
||||
public bool MaximizeWhenLargeImage;
|
||||
[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,400,400")]
|
||||
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;
|
||||
|
||||
[IniProperty("DropShadowEffectSettings", Description = "Settings for the drop shadow effect.")]
|
||||
public DropShadowEffect DropShadowEffectSettings;
|
||||
|
||||
[IniProperty("TornEdgeEffectSettings", Description = "Settings for the torn edge effect.")]
|
||||
public TornEdgeEffect TornEdgeEffectSettings;
|
||||
|
||||
public override void AfterLoad()
|
||||
{
|
||||
base.AfterLoad();
|
||||
if (RecentColors == null)
|
||||
{
|
||||
RecentColors = new List<Color>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <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="preferredDefaultValue">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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using GreenshotPlugin.Core;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PleaseWaitForm.
|
||||
/// </summary>
|
||||
internal partial class BackgroundForm : Form
|
||||
{
|
||||
private volatile bool _shouldClose;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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>
|
||||
internal 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()
|
||||
{
|
||||
CheckedChanged += BindableToolStripButton_CheckedChanged;
|
||||
}
|
||||
|
||||
private void BindableToolStripButton_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("Checked"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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>
|
||||
internal 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()
|
||||
{
|
||||
SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged;
|
||||
}
|
||||
|
||||
private void BindableToolStripComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("SelectedItem"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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 adopts its Tag and Image.
|
||||
/// The selected tag can be accessed via SelectedTag property.
|
||||
/// </summary>
|
||||
internal 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 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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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>
|
||||
internal 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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Greenshot.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Prevent having a gradient background in the toolstrip, and the overflow button
|
||||
/// See: http://stackoverflow.com/a/16926979
|
||||
/// </summary>
|
||||
internal class CustomProfessionalColorTable : ProfessionalColorTable
|
||||
{
|
||||
public override Color ToolStripGradientBegin
|
||||
{
|
||||
get { return SystemColors.Control; }
|
||||
}
|
||||
public override Color ToolStripGradientMiddle
|
||||
{
|
||||
get { return SystemColors.Control; }
|
||||
}
|
||||
public override Color ToolStripGradientEnd
|
||||
{
|
||||
get { return SystemColors.Control; }
|
||||
}
|
||||
public override Color OverflowButtonGradientBegin
|
||||
{
|
||||
get { return SystemColors.Control; }
|
||||
}
|
||||
public override Color OverflowButtonGradientMiddle
|
||||
{
|
||||
get { return SystemColors.Control; }
|
||||
}
|
||||
public override Color OverflowButtonGradientEnd
|
||||
{
|
||||
get { return SystemColors.Control; }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ToolStripProfessionalRenderer without having a visual artifact
|
||||
/// See: http://stackoverflow.com/a/16926979 and http://stackoverflow.com/a/13418840
|
||||
/// </summary>
|
||||
internal class CustomToolStripProfessionalRenderer : ToolStripProfessionalRenderer
|
||||
{
|
||||
public CustomToolStripProfessionalRenderer() : base(new CustomProfessionalColorTable())
|
||||
{
|
||||
RoundedEdges = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// By overriding the OnRenderToolStripBorder we can make the ToolStrip without border
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
|
||||
{
|
||||
// Don't draw a border
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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>
|
||||
internal 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()
|
||||
{
|
||||
if (ComboBox != null)
|
||||
{
|
||||
ComboBox.DataSource = FontFamily.Families;
|
||||
ComboBox.DisplayMember = "Name";
|
||||
SelectedIndexChanged += BindableToolStripComboBox_SelectedIndexChanged;
|
||||
ComboBox.DrawMode = DrawMode.OwnerDrawFixed;
|
||||
ComboBox.DrawItem += ComboBox_DrawItem;
|
||||
}
|
||||
}
|
||||
|
||||
private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
|
||||
{
|
||||
// DrawBackground handles drawing the background (i.e,. hot-tracked v. not)
|
||||
// It uses the system colors (Bluish, and and white, by default)
|
||||
// same as calling e.Graphics.FillRectangle ( SystemBrushes.Highlight, e.Bounds );
|
||||
e.DrawBackground();
|
||||
|
||||
if (e.Index > -1)
|
||||
{
|
||||
FontFamily fontFamily = Items[e.Index] as FontFamily;
|
||||
FontStyle fontStyle = FontStyle.Regular;
|
||||
if (fontFamily != null && !fontFamily.IsStyleAvailable(FontStyle.Regular))
|
||||
{
|
||||
if (fontFamily.IsStyleAvailable(FontStyle.Bold))
|
||||
{
|
||||
fontStyle = FontStyle.Bold;
|
||||
}
|
||||
else if (fontFamily.IsStyleAvailable(FontStyle.Italic))
|
||||
{
|
||||
fontStyle = FontStyle.Italic;
|
||||
}
|
||||
else if (fontFamily.IsStyleAvailable(FontStyle.Strikeout))
|
||||
{
|
||||
fontStyle = FontStyle.Strikeout;
|
||||
}
|
||||
else if (fontFamily.IsStyleAvailable(FontStyle.Underline))
|
||||
{
|
||||
fontStyle = FontStyle.Underline;
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
if (fontFamily != null)
|
||||
{
|
||||
DrawText(e.Graphics, fontFamily, fontStyle, e.Bounds, fontFamily.Name);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (fontFamily != null)
|
||||
{
|
||||
// If the drawing failed, BUG-1770 seems to have a weird case that causes: Font 'Lucida Sans Typewriter' does not support style 'Regular'
|
||||
DrawText(e.Graphics, FontFamily.GenericSansSerif, FontStyle.Regular, e.Bounds, fontFamily.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Uncomment this if you actually like the way the focus rectangle looks
|
||||
//e.DrawFocusRectangle ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to draw the string
|
||||
/// </summary>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="fontFamily"></param>
|
||||
/// <param name="fontStyle"></param>
|
||||
/// <param name="bounds"></param>
|
||||
/// <param name="text"></param>
|
||||
private void DrawText(Graphics graphics, FontFamily fontFamily, FontStyle fontStyle, Rectangle bounds, string text)
|
||||
{
|
||||
using (Font font = new Font(fontFamily, Font.Size + 5, fontStyle, GraphicsUnit.Pixel))
|
||||
{
|
||||
// Make sure the text is visible by centering it in the line
|
||||
using (StringFormat stringFormat = new StringFormat())
|
||||
{
|
||||
stringFormat.LineAlignment = StringAlignment.Center;
|
||||
graphics.DrawString(text, font, Brushes.Black, bounds, stringFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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>
|
||||
internal class FormWithoutActivation : Form
|
||||
{
|
||||
protected override bool ShowWithoutActivation
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of GreenshotCheckbox.
|
||||
/// </summary>
|
||||
internal 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;
|
||||
}
|
||||
|
||||
[Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
|
||||
public string SectionName { get; set; } = "Core";
|
||||
|
||||
[Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")]
|
||||
public string PropertyName
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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>
|
||||
internal 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 readonly 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)
|
||||
{
|
||||
if (x == null && y == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (x == null)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (y == null)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
// Cast the objects to be compared to ListViewItem objects
|
||||
var listviewX = (ListViewItem)x;
|
||||
var listviewY = (ListViewItem)y;
|
||||
|
||||
// Compare the two items
|
||||
var 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;
|
||||
}
|
||||
if (_orderOfSort == SortOrder.Descending)
|
||||
{
|
||||
// Descending sort is selected, return negative result of compare operation
|
||||
return (-compareResult);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal class GreenshotComboBox : ComboBox, IGreenshotConfigBindable
|
||||
{
|
||||
private Type _enumType = null;
|
||||
private Enum _selectedEnum = null;
|
||||
|
||||
[Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
|
||||
public string SectionName { get; set; } = "Core";
|
||||
|
||||
[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 = 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
|
||||
_enumType = enumType;
|
||||
|
||||
var availableValues = Enum.GetValues(enumType);
|
||||
Items.Clear();
|
||||
foreach (var enumValue in availableValues)
|
||||
{
|
||||
Items.Add(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)
|
||||
{
|
||||
}
|
||||
|
||||
_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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,376 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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.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 readonly IDictionary<Type, FieldInfo[]> reflectionCache = new Dictionary<Type, FieldInfo[]>();
|
||||
private IComponentChangeService m_changeService;
|
||||
private bool _storeFieldsManually;
|
||||
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 ManualStoreFields
|
||||
{
|
||||
get
|
||||
{
|
||||
return _storeFieldsManually;
|
||||
}
|
||||
set
|
||||
{
|
||||
_storeFieldsManually = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When this is set, the form will be brought to the foreground as soon as it is shown.
|
||||
/// </summary>
|
||||
protected bool ToFront
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <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>();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLoad(EventArgs e)
|
||||
{
|
||||
// Every GreenshotForm should have it's default icon
|
||||
// And it might not ne needed for a Tool Window, but still for the task manager / switcher it's important
|
||||
Icon = GreenshotResources.getGreenshotIcon();
|
||||
if (!DesignMode)
|
||||
{
|
||||
FillFields();
|
||||
base.OnLoad(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.Info("OnLoad called from designer.");
|
||||
InitializeForDesigner();
|
||||
base.OnLoad(e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the form is visible, if this is wanted
|
||||
/// </summary>
|
||||
/// <param name="e">EventArgs</param>
|
||||
protected override void OnShown(EventArgs e)
|
||||
{
|
||||
base.OnShown(e);
|
||||
if (ToFront)
|
||||
{
|
||||
WindowDetails.ToForeground(Handle);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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.ComponentAdded -= OnComponentAdded;
|
||||
}
|
||||
}
|
||||
|
||||
private void RegisterChangeNotifications()
|
||||
{
|
||||
// Register the event handlers for the IComponentChangeService events
|
||||
if (m_changeService != null)
|
||||
{
|
||||
m_changeService.ComponentAdded += OnComponentAdded;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// 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.DebugFormat("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;
|
||||
}
|
||||
GreenshotComboBox comboxBox = controlObject as GreenshotComboBox;
|
||||
if (comboxBox != null)
|
||||
{
|
||||
comboxBox.Populate(iniValue.ValueType);
|
||||
comboxBox.SetValue((Enum)iniValue.Value);
|
||||
comboxBox.Enabled = !iniValue.IsFixed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
GreenshotComboBox comboxBox = controlObject as GreenshotComboBox;
|
||||
if (comboxBox != null)
|
||||
{
|
||||
iniValue.Value = comboxBox.GetSelectedEnum();
|
||||
iniDirty = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iniDirty)
|
||||
{
|
||||
//IniConfig.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of GreenshotCheckbox.
|
||||
/// </summary>
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal class GreenshotTextBox : TextBox, IGreenshotConfigBindable
|
||||
{
|
||||
[Category("Greenshot"), DefaultValue("Core"), Description("Specifies the Ini-Section to map this control with.")]
|
||||
public string SectionName { get; set; } = "Core";
|
||||
|
||||
[Category("Greenshot"), DefaultValue(null), Description("Specifies the property name to map the configuration.")]
|
||||
public string PropertyName
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
internal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// This interface describes the designer fields that need to be implemented for Greenshot controls
|
||||
/// </summary>
|
||||
internal interface IGreenshotLanguageBindable
|
||||
{
|
||||
/// <summary>
|
||||
/// Language key to use to fill the Text value with
|
||||
/// </summary>
|
||||
string LanguageKey
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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>
|
||||
internal class MenuStripEx : MenuStrip
|
||||
{
|
||||
private const int WM_MOUSEACTIVATE = 0x21;
|
||||
|
||||
private enum NativeConstants : uint
|
||||
{
|
||||
MA_ACTIVATE = 1,
|
||||
MA_ACTIVATEANDEAT = 2,
|
||||
}
|
||||
|
||||
private bool _clickThrough;
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// See: http://nickstips.wordpress.com/2010/03/03/c-panel-resets-scroll-position-after-focus-is-lost-and-regained/
|
||||
/// </summary>
|
||||
internal 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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add horizontal scrolling to the panel, when using the wheel and the shift key is pressed
|
||||
/// </summary>
|
||||
/// <param name="e">MouseEventArgs</param>
|
||||
protected override void OnMouseWheel(MouseEventArgs e)
|
||||
{
|
||||
if (VScroll && (ModifierKeys & Keys.Shift) == Keys.Shift)
|
||||
{
|
||||
VScroll = false;
|
||||
base.OnMouseWheel(e);
|
||||
VScroll = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.OnMouseWheel(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,209 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Forms;
|
||||
using GreenshotPlugin.UnmanagedHelpers;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
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>
|
||||
internal class Pipette : Label, IMessageFilter, IDisposable
|
||||
{
|
||||
private MovableShowColorForm movableShowColorForm;
|
||||
private bool dragging;
|
||||
private Cursor _cursor;
|
||||
private readonly 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();
|
||||
if (PipetteUsed != null)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,136 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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>
|
||||
internal partial class PleaseWaitForm : Form
|
||||
{
|
||||
private Thread waitFor;
|
||||
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 = "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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.IniFile;
|
||||
using Greenshot.Plugin;
|
||||
using GreenshotPlugin.Core;
|
||||
using System;
|
||||
|
||||
namespace GreenshotPlugin.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of JpegQualityDialog.
|
||||
/// </summary>
|
||||
internal partial class QualityDialog : GreenshotForm
|
||||
{
|
||||
private static readonly 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();
|
||||
|
||||
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();
|
||||
ToFront = true;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
152
Greenshot.ImageEditor/Controls/QualityDialog.designer.cs
generated
152
Greenshot.ImageEditor/Controls/QualityDialog.designer.cs
generated
|
@ -1,152 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
}
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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>
|
||||
internal class SaveImageFileDialog : IDisposable
|
||||
{
|
||||
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
protected SaveFileDialog SaveFileDialog;
|
||||
private FilterOption[] _filterOptions;
|
||||
private DirectoryInfo _eagerlyCreatedDirectory;
|
||||
private readonly 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)
|
||||
{
|
||||
_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;
|
||||
var outputFileFormatAsString = Enum.GetName(typeof(OutputFormat), conf.OutputFileFormat);
|
||||
for (int i = 0; i < _filterOptions.Length; i++)
|
||||
{
|
||||
FilterOption fo = _filterOptions[i];
|
||||
fdf += fo.Label + "|*." + fo.Extension + "|";
|
||||
if (outputFileFormatAsString == fo.Extension)
|
||||
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
|
||||
{
|
||||
Label = ifo.ToUpper(),
|
||||
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>
|
||||
private void ApplySuggestedValues()
|
||||
{
|
||||
// build the full path and set dialog properties
|
||||
FileName = FilenameHelper.GetFilenameWithoutExtensionFromPattern(conf.OutputFileFilenamePattern, _captureDetails);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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
|
||||
{
|
||||
internal 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"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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,
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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)]
|
||||
internal 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"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,250 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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 readonly IDictionary<TK, TV> internalCache = new Dictionary<TK, TV>();
|
||||
private readonly object lockObject = new object();
|
||||
private readonly int secondsToExpire = 10;
|
||||
private readonly 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>();
|
||||
|
||||
lock (lockObject)
|
||||
{
|
||||
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)
|
||||
{
|
||||
lock (lockObject)
|
||||
{
|
||||
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 readonly 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the method signature which is used to capture a rectangle from the screen.
|
||||
/// </summary>
|
||||
/// <param name="captureBounds"></param>
|
||||
/// <returns>Captured Bitmap</returns>
|
||||
public delegate Bitmap CaptureScreenRectangleHandler(Rectangle captureBounds);
|
||||
|
||||
/// <summary>
|
||||
/// This is a hack to experiment with different screen capture routines
|
||||
/// </summary>
|
||||
public static class CaptureHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// By changing this value, null is default
|
||||
/// </summary>
|
||||
public static CaptureScreenRectangleHandler CaptureScreenRectangle
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,669 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using GreenshotPlugin;
|
||||
using GreenshotPlugin.Core;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
namespace Greenshot.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface to describe an effect
|
||||
/// </summary>
|
||||
public interface IEffect
|
||||
{
|
||||
/// <summary>
|
||||
/// Apply this IEffect to the supplied sourceImage.
|
||||
/// In the process of applying the supplied matrix will be modified to represent the changes.
|
||||
/// </summary>
|
||||
/// <param name="sourceImage">Image to apply the effect to</param>
|
||||
/// <param name="matrix">Matrix with the modifications like rotate, translate etc. this can be used to calculate the new location of elements on a canvas</param>
|
||||
/// <returns>new image with applied effect</returns>
|
||||
Image Apply(Image sourceImage, Matrix matrix);
|
||||
|
||||
/// <summary>
|
||||
/// Reset all values to their defaults
|
||||
/// </summary>
|
||||
void Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DropShadowEffect
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(EffectConverter))]
|
||||
public class DropShadowEffect : IEffect
|
||||
{
|
||||
public DropShadowEffect()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public float Darkness
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public int ShadowSize
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public Point ShadowOffset
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
Darkness = 0.6f;
|
||||
ShadowSize = 7;
|
||||
ShadowOffset = new Point(-1, -1);
|
||||
}
|
||||
|
||||
public virtual Image Apply(Image sourceImage, Matrix matrix)
|
||||
{
|
||||
return ImageHelper.CreateShadow(sourceImage, Darkness, ShadowSize, ShadowOffset, matrix, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TornEdgeEffect extends on DropShadowEffect
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(EffectConverter))]
|
||||
public class TornEdgeEffect : DropShadowEffect
|
||||
{
|
||||
public TornEdgeEffect()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public int ToothHeight
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public int HorizontalToothRange
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public int VerticalToothRange
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public bool[] Edges
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public bool GenerateShadow
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
base.Reset();
|
||||
ShadowSize = 7;
|
||||
ToothHeight = 12;
|
||||
HorizontalToothRange = 20;
|
||||
VerticalToothRange = 20;
|
||||
Edges = new[] { true, true, true, true };
|
||||
GenerateShadow = true;
|
||||
}
|
||||
|
||||
public override Image Apply(Image sourceImage, Matrix matrix)
|
||||
{
|
||||
Image tmpTornImage = ImageHelper.CreateTornEdge(sourceImage, ToothHeight, HorizontalToothRange, VerticalToothRange, Edges);
|
||||
if (GenerateShadow)
|
||||
{
|
||||
using (tmpTornImage)
|
||||
{
|
||||
return ImageHelper.CreateShadow(tmpTornImage, Darkness, ShadowSize, ShadowOffset, matrix, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
}
|
||||
return tmpTornImage;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GrayscaleEffect
|
||||
/// </summary>
|
||||
public class GrayscaleEffect : IEffect
|
||||
{
|
||||
public Image Apply(Image sourceImage, Matrix matrix)
|
||||
{
|
||||
return ImageHelper.CreateGrayscale(sourceImage);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
// No settings to reset
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MonochromeEffect
|
||||
/// </summary>
|
||||
public class MonochromeEffect : IEffect
|
||||
{
|
||||
private readonly byte _threshold;
|
||||
|
||||
/// <param name="threshold">Threshold for monochrome filter (0 - 255), lower value means less black</param>
|
||||
public MonochromeEffect(byte threshold)
|
||||
{
|
||||
_threshold = threshold;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
// Modify the threshold to have a default, which is reset here
|
||||
}
|
||||
|
||||
public Image Apply(Image sourceImage, Matrix matrix)
|
||||
{
|
||||
return ImageHelper.CreateMonochrome(sourceImage, _threshold);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AdjustEffect
|
||||
/// </summary>
|
||||
public class AdjustEffect : IEffect
|
||||
{
|
||||
public AdjustEffect()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public float Contrast
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public float Brightness
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public float Gamma
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Contrast = 1f;
|
||||
Brightness = 1f;
|
||||
Gamma = 1f;
|
||||
}
|
||||
|
||||
public Image Apply(Image sourceImage, Matrix matrix)
|
||||
{
|
||||
return ImageHelper.Adjust(sourceImage, Brightness, Contrast, Gamma);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ReduceColorsEffect
|
||||
/// </summary>
|
||||
public class ReduceColorsEffect : IEffect
|
||||
{
|
||||
public ReduceColorsEffect()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public int Colors
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Colors = 256;
|
||||
}
|
||||
|
||||
public Image Apply(Image sourceImage, Matrix matrix)
|
||||
{
|
||||
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, Matrix matrix)
|
||||
{
|
||||
return ImageHelper.CreateNegative(sourceImage);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
// No settings to reset
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BorderEffect
|
||||
/// </summary>
|
||||
public class BorderEffect : IEffect
|
||||
{
|
||||
public BorderEffect()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
public Color Color
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
public int Width
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
Width = 2;
|
||||
Color = Color.Black;
|
||||
}
|
||||
|
||||
public Image Apply(Image sourceImage, Matrix matrix)
|
||||
{
|
||||
return ImageHelper.CreateBorder(sourceImage, Width, Color, sourceImage.PixelFormat, matrix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// RotateEffect
|
||||
/// </summary>
|
||||
public class RotateEffect : IEffect
|
||||
{
|
||||
public RotateEffect(int angle)
|
||||
{
|
||||
Angle = angle;
|
||||
}
|
||||
|
||||
public int Angle
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
// Angle doesn't have a default value
|
||||
}
|
||||
|
||||
public Image Apply(Image sourceImage, Matrix matrix)
|
||||
{
|
||||
RotateFlipType flipType;
|
||||
if (Angle == 90)
|
||||
{
|
||||
matrix.Rotate(90, MatrixOrder.Append);
|
||||
matrix.Translate(sourceImage.Height, 0, MatrixOrder.Append);
|
||||
flipType = RotateFlipType.Rotate90FlipNone;
|
||||
}
|
||||
else if (Angle == -90 || Angle == 270)
|
||||
{
|
||||
flipType = RotateFlipType.Rotate270FlipNone;
|
||||
matrix.Rotate(-90, MatrixOrder.Append);
|
||||
matrix.Translate(0, sourceImage.Width, MatrixOrder.Append);
|
||||
}
|
||||
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 void Reset()
|
||||
{
|
||||
// values don't have a default value
|
||||
}
|
||||
|
||||
public Image Apply(Image sourceImage, Matrix matrix)
|
||||
{
|
||||
return ImageHelper.ResizeImage(sourceImage, MaintainAspectRatio, Width, Height, matrix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 void Reset()
|
||||
{
|
||||
// values don't have a default value
|
||||
}
|
||||
|
||||
public Image Apply(Image sourceImage, Matrix matrix)
|
||||
{
|
||||
return ImageHelper.ResizeCanvas(sourceImage, BackgroundColor, Left, Right, Top, Bottom, matrix);
|
||||
}
|
||||
}
|
||||
|
||||
public class EffectConverter : TypeConverter
|
||||
{
|
||||
// Fix to prevent BUG-1753
|
||||
private readonly NumberFormatInfo numberFormatInfo = new NumberFormatInfo();
|
||||
|
||||
public EffectConverter()
|
||||
{
|
||||
numberFormatInfo.NumberDecimalSeparator = ".";
|
||||
numberFormatInfo.NumberGroupSeparator = ",";
|
||||
}
|
||||
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
if (sourceType == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (destinationType == typeof(DropShadowEffect))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (destinationType == typeof(TornEdgeEffect))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return base.CanConvertTo(context, destinationType);
|
||||
}
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
||||
{
|
||||
// to string
|
||||
if (destinationType == typeof(string))
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (value.GetType() == typeof(DropShadowEffect))
|
||||
{
|
||||
DropShadowEffect effect = value as DropShadowEffect;
|
||||
RetrieveDropShadowEffectValues(effect, sb);
|
||||
return sb.ToString();
|
||||
}
|
||||
if (value.GetType() == typeof(TornEdgeEffect))
|
||||
{
|
||||
TornEdgeEffect effect = value as TornEdgeEffect;
|
||||
RetrieveDropShadowEffectValues(effect, sb);
|
||||
sb.Append("|");
|
||||
RetrieveTornEdgeEffectValues(effect, sb);
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
// from string
|
||||
if (value is string)
|
||||
{
|
||||
string settings = value as string;
|
||||
if (destinationType == typeof(DropShadowEffect))
|
||||
{
|
||||
DropShadowEffect effect = new DropShadowEffect();
|
||||
ApplyDropShadowEffectValues(settings, effect);
|
||||
return effect;
|
||||
}
|
||||
if (destinationType == typeof(TornEdgeEffect))
|
||||
{
|
||||
TornEdgeEffect effect = new TornEdgeEffect();
|
||||
ApplyDropShadowEffectValues(settings, effect);
|
||||
ApplyTornEdgeEffectValues(settings, effect);
|
||||
return effect;
|
||||
}
|
||||
}
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value != null && value is string)
|
||||
{
|
||||
string settings = value as string;
|
||||
if (settings.Contains("ToothHeight"))
|
||||
{
|
||||
return ConvertTo(context, culture, value, typeof(TornEdgeEffect));
|
||||
}
|
||||
return ConvertTo(context, culture, value, typeof(DropShadowEffect));
|
||||
}
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
|
||||
private void ApplyDropShadowEffectValues(string valuesString, DropShadowEffect effect)
|
||||
{
|
||||
string[] values = valuesString.Split('|');
|
||||
foreach (string nameValuePair in values)
|
||||
{
|
||||
string[] pair = nameValuePair.Split(':');
|
||||
switch (pair[0])
|
||||
{
|
||||
case "Darkness":
|
||||
float darkness;
|
||||
// Fix to prevent BUG-1753
|
||||
if (pair[1] != null && float.TryParse(pair[1], NumberStyles.Float, numberFormatInfo, out darkness))
|
||||
{
|
||||
if (darkness <= 1.0)
|
||||
{
|
||||
effect.Darkness = darkness;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "ShadowSize":
|
||||
int shadowSize;
|
||||
if (int.TryParse(pair[1], out shadowSize))
|
||||
{
|
||||
effect.ShadowSize = shadowSize;
|
||||
}
|
||||
break;
|
||||
case "ShadowOffset":
|
||||
Point shadowOffset = new Point();
|
||||
int shadowOffsetX;
|
||||
int shadowOffsetY;
|
||||
string[] coordinates = pair[1].Split(',');
|
||||
if (int.TryParse(coordinates[0], out shadowOffsetX))
|
||||
{
|
||||
shadowOffset.X = shadowOffsetX;
|
||||
}
|
||||
if (int.TryParse(coordinates[1], out shadowOffsetY))
|
||||
{
|
||||
shadowOffset.Y = shadowOffsetY;
|
||||
}
|
||||
effect.ShadowOffset = shadowOffset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyTornEdgeEffectValues(string valuesString, TornEdgeEffect effect)
|
||||
{
|
||||
string[] values = valuesString.Split('|');
|
||||
foreach (string nameValuePair in values)
|
||||
{
|
||||
string[] pair = nameValuePair.Split(':');
|
||||
switch (pair[0])
|
||||
{
|
||||
case "GenerateShadow":
|
||||
bool generateShadow;
|
||||
if (bool.TryParse(pair[1], out generateShadow))
|
||||
{
|
||||
effect.GenerateShadow = generateShadow;
|
||||
}
|
||||
break;
|
||||
case "ToothHeight":
|
||||
int toothHeight;
|
||||
if (int.TryParse(pair[1], out toothHeight))
|
||||
{
|
||||
effect.ToothHeight = toothHeight;
|
||||
}
|
||||
break;
|
||||
case "HorizontalToothRange":
|
||||
int horizontalToothRange;
|
||||
if (int.TryParse(pair[1], out horizontalToothRange))
|
||||
{
|
||||
effect.HorizontalToothRange = horizontalToothRange;
|
||||
}
|
||||
break;
|
||||
case "VerticalToothRange":
|
||||
int verticalToothRange;
|
||||
if (int.TryParse(pair[1], out verticalToothRange))
|
||||
{
|
||||
effect.VerticalToothRange = verticalToothRange;
|
||||
}
|
||||
break;
|
||||
case "Edges":
|
||||
string[] edges = pair[1].Split(',');
|
||||
bool edge;
|
||||
if (bool.TryParse(edges[0], out edge))
|
||||
{
|
||||
effect.Edges[0] = edge;
|
||||
}
|
||||
if (bool.TryParse(edges[1], out edge))
|
||||
{
|
||||
effect.Edges[1] = edge;
|
||||
}
|
||||
if (bool.TryParse(edges[2], out edge))
|
||||
{
|
||||
effect.Edges[2] = edge;
|
||||
}
|
||||
if (bool.TryParse(edges[3], out edge))
|
||||
{
|
||||
effect.Edges[3] = edge;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void RetrieveDropShadowEffectValues(DropShadowEffect effect, StringBuilder sb)
|
||||
{
|
||||
// Fix to prevent BUG-1753 is to use the numberFormatInfo
|
||||
sb.AppendFormat("Darkness:{0}|ShadowSize:{1}|ShadowOffset:{2},{3}", effect.Darkness.ToString("F2", numberFormatInfo), effect.ShadowSize, effect.ShadowOffset.X, effect.ShadowOffset.Y);
|
||||
}
|
||||
|
||||
private void RetrieveTornEdgeEffectValues(TornEdgeEffect effect, StringBuilder sb)
|
||||
{
|
||||
sb.AppendFormat("GenerateShadow:{0}|ToothHeight:{1}|HorizontalToothRange:{2}|VerticalToothRange:{3}|Edges:{4},{5},{6},{7}", effect.GenerateShadow, effect.ToothHeight, effect.HorizontalToothRange, effect.VerticalToothRange, effect.Edges[0], effect.Edges[1], effect.Edges[2], effect.Edges[3]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
public class EventDelay
|
||||
{
|
||||
private long lastCheck;
|
||||
private readonly long waitTime;
|
||||
|
||||
public EventDelay(long ticks)
|
||||
{
|
||||
waitTime = ticks;
|
||||
}
|
||||
|
||||
public bool Check()
|
||||
{
|
||||
lock (this)
|
||||
{
|
||||
long now = DateTime.Now.Ticks;
|
||||
bool isPassed = now - lastCheck > waitTime;
|
||||
lastCheck = now;
|
||||
return isPassed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,661 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.IniFile;
|
||||
using Greenshot.Plugin;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
public static class FilenameHelper
|
||||
{
|
||||
// Specify the regular expression for the filename formatting:
|
||||
// Starting with ${
|
||||
// than the varname, which ends with a : or }
|
||||
// If a parameters needs to be supplied, than a ":" should follow the name... everything from the : until the } is considered to be part of the parameters.
|
||||
// The parameter format is a single alpha followed by the value belonging to the parameter, e.g. :
|
||||
// ${capturetime:d"yyyy-MM-dd HH_mm_ss"}
|
||||
private static readonly Regex VAR_REGEXP = new Regex(@"\${(?<variable>[^:}]+)[:]?(?<parameters>[^}]*)}", RegexOptions.Compiled);
|
||||
private static readonly Regex CMD_VAR_REGEXP = new Regex(@"%(?<variable>[^%]+)%", RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex SPLIT_REGEXP = new Regex(";(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)", RegexOptions.Compiled);
|
||||
private const int MAX_TITLE_LENGTH = 80;
|
||||
private static readonly 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="path">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";
|
||||
IDictionary<string, string> replacements = new Dictionary<string, string>();
|
||||
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))
|
||||
{
|
||||
// Padding p<width>[,pad-character]
|
||||
case "p":
|
||||
string[] padParams = parameter.Substring(1).Split(new[] { ',' });
|
||||
try
|
||||
{
|
||||
padWidth = int.Parse(padParams[0]);
|
||||
}
|
||||
catch
|
||||
{
|
||||
};
|
||||
if (padParams.Length > 1)
|
||||
{
|
||||
padChar = padParams[1][0];
|
||||
}
|
||||
break;
|
||||
// replace
|
||||
// r<old string>,<new string>
|
||||
case "r":
|
||||
string[] replaceParameters = parameter.Substring(1).Split(new[] { ',' });
|
||||
if (replaceParameters != null && replaceParameters.Length == 2)
|
||||
{
|
||||
replacements.Add(replaceParameters[0], replaceParameters[1]);
|
||||
}
|
||||
break;
|
||||
// Dateformat d<format>
|
||||
// Format can be anything that is used in C# date formatting
|
||||
case "d":
|
||||
dateFormat = parameter.Substring(1);
|
||||
if (dateFormat.StartsWith("\""))
|
||||
{
|
||||
dateFormat = dateFormat.Substring(1);
|
||||
}
|
||||
if (dateFormat.EndsWith("\""))
|
||||
{
|
||||
dateFormat = dateFormat.Substring(0, dateFormat.Length - 1);
|
||||
}
|
||||
break;
|
||||
// Substring:
|
||||
// s<start>[,length]
|
||||
case "s":
|
||||
string range = parameter.Substring(1);
|
||||
string[] rangelist = range.Split(new[] { ',' });
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// new for feature #697
|
||||
if (replacements.Count > 0)
|
||||
{
|
||||
foreach (string oldValue in replacements.Keys)
|
||||
{
|
||||
replaceValue = replaceValue.Replace(oldValue, replacements[oldValue]);
|
||||
}
|
||||
}
|
||||
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 FillCmdVariables(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 CMD_VAR_REGEXP.Replace(pattern,
|
||||
delegate (Match m)
|
||||
{
|
||||
return MatchVarEvaluator(m, null, processVars, userVars, machineVars, filenameSafeMode);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/// <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, can be null</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
|
||||
if (captureDetails != null)
|
||||
{
|
||||
e.Data.Add("title", captureDetails.Title);
|
||||
}
|
||||
e.Data.Add("pattern", pattern);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a directory name is valid in the current file system
|
||||
/// </summary>
|
||||
/// <param name="directoryName">directory name (not path!)</param>
|
||||
/// <returns>true if directory name is valid</returns>
|
||||
public static bool IsDirectoryNameValid(string directoryName)
|
||||
{
|
||||
var forbiddenChars = Path.GetInvalidPathChars();
|
||||
foreach (var forbiddenChar in forbiddenChars)
|
||||
{
|
||||
if (directoryName == null || directoryName.Contains(forbiddenChar.ToString()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a filename is valid in the current file system
|
||||
/// </summary>
|
||||
/// <param name="filename">name of the file</param>
|
||||
/// <returns>true if filename is valid</returns>
|
||||
public static bool IsFilenameValid(string filename)
|
||||
{
|
||||
var forbiddenChars = Path.GetInvalidFileNameChars();
|
||||
foreach (var forbiddenChar in forbiddenChars)
|
||||
{
|
||||
if (filename == null || filename.Contains(forbiddenChar.ToString()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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 readonly 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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,471 +0,0 @@
|
|||
<?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>
|
File diff suppressed because it is too large
Load diff
|
@ -1,728 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.IniFile;
|
||||
using Greenshot.Plugin;
|
||||
using GreenshotPlugin.Controls;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
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 readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
private static readonly int PROPERTY_TAG_SOFTWARE_USED = 0x0131;
|
||||
private static readonly 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 = Encoding.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;
|
||||
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;
|
||||
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;
|
||||
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 (Equals(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
|
||||
{
|
||||
bool needsDispose = false;
|
||||
// Removing transparency if it's not supported in the output
|
||||
if (!Equals(imageFormat, ImageFormat.Png) && Image.IsAlphaPixelFormat(imageToSave.PixelFormat))
|
||||
{
|
||||
imageToSave = ImageHelper.Clone(imageToSave, PixelFormat.Format24bppRgb);
|
||||
needsDispose = true;
|
||||
}
|
||||
AddTag(imageToSave);
|
||||
// Added for OptiPNG
|
||||
bool processed = false;
|
||||
if (Equals(imageFormat, ImageFormat.Png) && !string.IsNullOrEmpty(conf.OptimizePNGCommand))
|
||||
{
|
||||
processed = ProcessPNGImageExternally(imageToSave, targetStream);
|
||||
}
|
||||
if (!processed)
|
||||
{
|
||||
imageToSave.Save(targetStream, imageFormat);
|
||||
}
|
||||
if (needsDispose)
|
||||
{
|
||||
imageToSave.Dispose();
|
||||
imageToSave = null;
|
||||
}
|
||||
}
|
||||
|
||||
// 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>
|
||||
/// Write the passed Image to a tmp-file and call an external process, than read the file back and write it to the targetStream
|
||||
/// </summary>
|
||||
/// <param name="imageToProcess">Image to pass to the external process</param>
|
||||
/// <param name="targetStream">stream to write the processed image to</param>
|
||||
/// <returns></returns>
|
||||
private static bool ProcessPNGImageExternally(Image imageToProcess, Stream targetStream)
|
||||
{
|
||||
if (string.IsNullOrEmpty(conf.OptimizePNGCommand))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!File.Exists(conf.OptimizePNGCommand))
|
||||
{
|
||||
LOG.WarnFormat("Can't find 'OptimizePNGCommand' {0}", conf.OptimizePNGCommand);
|
||||
return false;
|
||||
}
|
||||
string tmpFileName = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName() + ".png");
|
||||
try
|
||||
{
|
||||
using (FileStream tmpStream = File.Create(tmpFileName))
|
||||
{
|
||||
LOG.DebugFormat("Writing png to tmp file: {0}", tmpFileName);
|
||||
imageToProcess.Save(tmpStream, ImageFormat.Png);
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.DebugFormat("File size before processing {0}", new FileInfo(tmpFileName).Length);
|
||||
}
|
||||
}
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.DebugFormat("Starting : {0}", conf.OptimizePNGCommand);
|
||||
}
|
||||
|
||||
ProcessStartInfo processStartInfo = new ProcessStartInfo(conf.OptimizePNGCommand);
|
||||
processStartInfo.Arguments = string.Format(conf.OptimizePNGCommandArguments, tmpFileName);
|
||||
processStartInfo.CreateNoWindow = true;
|
||||
processStartInfo.RedirectStandardOutput = true;
|
||||
processStartInfo.RedirectStandardError = true;
|
||||
processStartInfo.UseShellExecute = false;
|
||||
using (Process process = Process.Start(processStartInfo))
|
||||
{
|
||||
if (process != null)
|
||||
{
|
||||
process.WaitForExit();
|
||||
if (process.ExitCode == 0)
|
||||
{
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
LOG.DebugFormat("File size after processing {0}", new FileInfo(tmpFileName).Length);
|
||||
LOG.DebugFormat("Reading back tmp file: {0}", tmpFileName);
|
||||
}
|
||||
byte[] processedImage = File.ReadAllBytes(tmpFileName);
|
||||
targetStream.Write(processedImage, 0, processedImage.Length);
|
||||
return true;
|
||||
}
|
||||
LOG.ErrorFormat("Error while processing PNG image: {0}", process.ExitCode);
|
||||
LOG.ErrorFormat("Output: {0}", process.StandardOutput.ReadToEnd());
|
||||
LOG.ErrorFormat("Error: {0}", process.StandardError.ReadToEnd());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.Error("Error while processing PNG image: ", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (File.Exists(tmpFileName))
|
||||
{
|
||||
LOG.DebugFormat("Cleaning up tmp file: {0}", tmpFileName);
|
||||
File.Delete(tmpFileName);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <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;
|
||||
|
||||
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)
|
||||
{
|
||||
return disposeImage;
|
||||
}
|
||||
Image tmpImage;
|
||||
if (outputSettings.Effects != null && outputSettings.Effects.Count > 0)
|
||||
{
|
||||
// apply effects, if there are any
|
||||
using (Matrix matrix = new Matrix())
|
||||
{
|
||||
tmpImage = ImageHelper.ApplyEffects(imageToSave, outputSettings.Effects, matrix);
|
||||
}
|
||||
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))
|
||||
{
|
||||
return disposeImage;
|
||||
}
|
||||
bool isAlpha = Image.IsAlphaPixelFormat(imageToSave.PixelFormat);
|
||||
if (outputSettings.ReduceColors || (!isAlpha && conf.OutputFileAutoReduceColors))
|
||||
{
|
||||
using (var 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)
|
||||
{
|
||||
return disposeImage;
|
||||
}
|
||||
try
|
||||
{
|
||||
LOG.Info("Reducing colors on bitmap to 256.");
|
||||
tmpImage = quantizer.GetQuantizedImage(conf.OutputFileReduceColorsTo);
|
||||
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>
|
||||
/// <param name="returnSurface"></param>
|
||||
/// <returns></returns>
|
||||
public static ISurface LoadGreenshotSurface(string fullPath, ISurface returnSurface)
|
||||
{
|
||||
if (string.IsNullOrEmpty(fullPath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Image fileImage;
|
||||
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.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);
|
||||
using (BinaryReader reader = new BinaryReader(surfaceFileStream))
|
||||
{
|
||||
long 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
|
||||
if (path != null)
|
||||
{
|
||||
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
|
||||
{
|
||||
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();
|
||||
}
|
||||
// For now we always overwrite, should be changed
|
||||
Save(surface, fileNameWithExtension, true, outputSettings, conf.OutputFileCopyPathToClipboard);
|
||||
returnValue = fileNameWithExtension;
|
||||
IniConfig.Save();
|
||||
}
|
||||
catch (ExternalException)
|
||||
{
|
||||
MessageBox.Show(string.Format("Cannot save file to {0}.\r\nPlease check write accessibility of the selected storage location.",
|
||||
saveImageFileDialog.FileName).Replace(@"\\", @"\"), "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>
|
||||
/// Remove a tmpfile which was created by SaveNamedTmpFile
|
||||
/// Used e.g. by the email export
|
||||
/// </summary>
|
||||
/// <param name="tmpfile"></param>
|
||||
/// <returns>true if it worked</returns>
|
||||
public static bool DeleteNamedTmpFile(string tmpfile)
|
||||
{
|
||||
LOG.Debug("Deleting TMP File: " + tmpfile);
|
||||
try
|
||||
{
|
||||
if (File.Exists(tmpfile))
|
||||
{
|
||||
File.Delete(tmpfile);
|
||||
tmpFileCache.Remove(tmpfile);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Warn("Error deleting tmp file: ", ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a temp image file
|
||||
/// </summary>
|
||||
/// <param name="surface"></param>
|
||||
/// <param name="outputSettings"></param>
|
||||
/// <param name="destinationPath"></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="filekey"></param>
|
||||
/// <param name="filename"></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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,907 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.IniFile;
|
||||
using Greenshot.Plugin;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// HTTP Method to make sure we have the correct method
|
||||
/// </summary>
|
||||
public enum HTTPMethod
|
||||
{
|
||||
GET,
|
||||
POST,
|
||||
PUT,
|
||||
DELETE,
|
||||
HEAD
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Description of NetworkHelper.
|
||||
/// </summary>
|
||||
public static class NetworkHelper
|
||||
{
|
||||
private static readonly CoreConfiguration Config = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
|
||||
static NetworkHelper()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Disable certificate checking
|
||||
ServicePointManager.ServerCertificateValidationCallback += delegate
|
||||
{
|
||||
return true;
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.Warn("An error has occured while allowing self-signed certificates:", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download a uri response as string
|
||||
/// </summary>
|
||||
/// <param name="uri">An Uri to specify the download location</param>
|
||||
/// <returns>string with the file content</returns>
|
||||
public static string GetAsString(Uri uri)
|
||||
{
|
||||
return GetResponseAsString(CreateWebRequest(uri));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the FavIcon as a Bitmap
|
||||
/// </summary>
|
||||
/// <param name="baseUri"></param>
|
||||
/// <returns>Bitmap with the FavIcon</returns>
|
||||
public static Bitmap DownloadFavIcon(Uri baseUri)
|
||||
{
|
||||
Uri url = new Uri(baseUri, new Uri("favicon.ico"));
|
||||
try
|
||||
{
|
||||
HttpWebRequest request = CreateWebRequest(url);
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
if (request.HaveResponse)
|
||||
{
|
||||
using (Stream responseStream = response.GetResponseStream())
|
||||
{
|
||||
if (responseStream != null)
|
||||
{
|
||||
using (Image image = Image.FromStream(responseStream))
|
||||
{
|
||||
return (image.Height > 16 && image.Width > 16) ? new Bitmap(image, 16, 16) : new Bitmap(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.Error("Problem downloading the FavIcon from: " + baseUri, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the uri into a memorystream, without catching exceptions
|
||||
/// </summary>
|
||||
/// <param name="url">Of an image</param>
|
||||
/// <returns>MemoryStream which is already seeked to 0</returns>
|
||||
public static MemoryStream GetAsMemoryStream(string url)
|
||||
{
|
||||
HttpWebRequest request = CreateWebRequest(url);
|
||||
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
using (Stream responseStream = response.GetResponseStream())
|
||||
{
|
||||
if (responseStream != null)
|
||||
{
|
||||
responseStream.CopyTo(memoryStream);
|
||||
}
|
||||
// Make sure it can be used directly
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
return memoryStream;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download the uri to Bitmap
|
||||
/// </summary>
|
||||
/// <param name="url">Of an image</param>
|
||||
/// <returns>Bitmap</returns>
|
||||
public static Image DownloadImage(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
string content;
|
||||
using (MemoryStream memoryStream = GetAsMemoryStream(url))
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Image image = Image.FromStream(memoryStream))
|
||||
{
|
||||
return ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// If we arrive here, the image loading didn't work, try to see if the response has a http(s) URL to an image and just take this instead.
|
||||
using (StreamReader streamReader = new StreamReader(memoryStream, Encoding.UTF8, true))
|
||||
{
|
||||
content = streamReader.ReadLine();
|
||||
}
|
||||
if (!string.IsNullOrEmpty(content))
|
||||
{
|
||||
Regex imageUrlRegex = new Regex(@"(http|https)://.*(\.png|\.gif|\.jpg|\.tiff|\.jpeg|\.bmp)");
|
||||
Match match = imageUrlRegex.Match(content);
|
||||
if (match.Success)
|
||||
{
|
||||
using (MemoryStream memoryStream2 = GetAsMemoryStream(match.Value))
|
||||
{
|
||||
using (Image image = Image.FromStream(memoryStream2))
|
||||
{
|
||||
return ImageHelper.Clone(image, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.Error("Problem downloading the image from: " + url, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a web request with a lot of default settings
|
||||
/// </summary>
|
||||
/// <param name="uri">string with uri to connect to</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static HttpWebRequest CreateWebRequest(string uri)
|
||||
{
|
||||
return CreateWebRequest(new Uri(uri));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a web request with a lot of default settings
|
||||
/// </summary>
|
||||
/// <param name="uri">string with uri to connect to</param>
|
||||
/// /// <param name="method">Method to use</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static HttpWebRequest CreateWebRequest(string uri, HTTPMethod method)
|
||||
{
|
||||
return CreateWebRequest(new Uri(uri), method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a web request with a lot of default settings
|
||||
/// </summary>
|
||||
/// <param name="uri">Uri with uri to connect to</param>
|
||||
/// <param name="method">Method to use</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static HttpWebRequest CreateWebRequest(Uri uri, HTTPMethod method)
|
||||
{
|
||||
HttpWebRequest webRequest = CreateWebRequest(uri);
|
||||
webRequest.Method = method.ToString();
|
||||
return webRequest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create a web request, eventually with proxy
|
||||
/// </summary>
|
||||
/// <param name="uri">Uri with uri to connect to</param>
|
||||
/// <returns>WebRequest</returns>
|
||||
public static HttpWebRequest CreateWebRequest(Uri uri)
|
||||
{
|
||||
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uri);
|
||||
webRequest.Proxy = Config.UseProxy ? CreateProxy(uri) : null;
|
||||
// Make sure the default credentials are available
|
||||
webRequest.Credentials = CredentialCache.DefaultCredentials;
|
||||
|
||||
// Allow redirect, this is usually needed so that we don't get a problem when a service moves
|
||||
webRequest.AllowAutoRedirect = true;
|
||||
// Set default timeouts
|
||||
webRequest.Timeout = Config.WebRequestTimeout * 1000;
|
||||
webRequest.ReadWriteTimeout = Config.WebRequestReadWriteTimeout * 1000;
|
||||
return webRequest;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a IWebProxy Object which can be used to access the Internet
|
||||
/// This method will check the configuration if the proxy is allowed to be used.
|
||||
/// Usages can be found in the DownloadFavIcon or Jira and Confluence plugins
|
||||
/// </summary>
|
||||
/// <param name="uri"></param>
|
||||
/// <returns>IWebProxy filled with all the proxy details or null if none is set/wanted</returns>
|
||||
public static IWebProxy CreateProxy(Uri uri)
|
||||
{
|
||||
IWebProxy proxyToUse = null;
|
||||
if (Config.UseProxy)
|
||||
{
|
||||
proxyToUse = WebRequest.DefaultWebProxy;
|
||||
if (proxyToUse != null)
|
||||
{
|
||||
proxyToUse.Credentials = CredentialCache.DefaultCredentials;
|
||||
if (LOG.IsDebugEnabled)
|
||||
{
|
||||
// check the proxy for the Uri
|
||||
if (!proxyToUse.IsBypassed(uri))
|
||||
{
|
||||
Uri proxyUri = proxyToUse.GetProxy(uri);
|
||||
if (proxyUri != null)
|
||||
{
|
||||
LOG.Debug("Using proxy: " + proxyUri + " for " + uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.Debug("No proxy found!");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.Debug("Proxy bypass for: " + uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.Debug("No proxy found!");
|
||||
}
|
||||
}
|
||||
return proxyToUse;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UrlEncodes a string without the requirement for System.Web
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <returns></returns>
|
||||
// [Obsolete("Use System.Uri.EscapeDataString instead")]
|
||||
public static string UrlEncode(string text)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
// Sytem.Uri provides reliable parsing, but doesn't encode spaces.
|
||||
return Uri.EscapeDataString(text).Replace("%20", "+");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper around the EscapeDataString, as the limit is 32766 characters
|
||||
/// See: http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring%28v=vs.110%29.aspx
|
||||
/// </summary>
|
||||
/// <param name="text"></param>
|
||||
/// <returns>escaped data string</returns>
|
||||
public static string EscapeDataString(string text)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(text))
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
int currentLocation = 0;
|
||||
while (currentLocation < text.Length)
|
||||
{
|
||||
string process = text.Substring(currentLocation, Math.Min(16384, text.Length - currentLocation));
|
||||
result.Append(Uri.EscapeDataString(process));
|
||||
currentLocation = currentLocation + 16384;
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UrlDecodes a string without requiring System.Web
|
||||
/// </summary>
|
||||
/// <param name="text">String to decode.</param>
|
||||
/// <returns>decoded string</returns>
|
||||
public static string UrlDecode(string text)
|
||||
{
|
||||
// pre-process for + sign space formatting since System.Uri doesn't handle it
|
||||
// plus literals are encoded as %2b normally so this should be safe
|
||||
text = text.Replace("+", " ");
|
||||
return Uri.UnescapeDataString(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ParseQueryString without the requirement for System.Web
|
||||
/// </summary>
|
||||
/// <param name="queryString"></param>
|
||||
/// <returns>IDictionary string, string</returns>
|
||||
public static IDictionary<string, string> ParseQueryString(string queryString)
|
||||
{
|
||||
IDictionary<string, string> parameters = new SortedDictionary<string, string>();
|
||||
// remove anything other than query string from uri
|
||||
if (queryString.Contains("?"))
|
||||
{
|
||||
queryString = queryString.Substring(queryString.IndexOf('?') + 1);
|
||||
}
|
||||
foreach (string vp in Regex.Split(queryString, "&"))
|
||||
{
|
||||
if (string.IsNullOrEmpty(vp))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
string[] singlePair = Regex.Split(vp, "=");
|
||||
if (parameters.ContainsKey(singlePair[0]))
|
||||
{
|
||||
parameters.Remove(singlePair[0]);
|
||||
}
|
||||
parameters.Add(singlePair[0], singlePair.Length == 2 ? singlePair[1] : string.Empty);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the query paramters
|
||||
/// </summary>
|
||||
/// <param name="queryParameters">the list of query parameters</param>
|
||||
/// <returns>a string with the query parameters</returns>
|
||||
public static string GenerateQueryParameters(IDictionary<string, object> queryParameters)
|
||||
{
|
||||
if (queryParameters == null || queryParameters.Count == 0)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
queryParameters = new SortedDictionary<string, object>(queryParameters);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (string key in queryParameters.Keys)
|
||||
{
|
||||
sb.AppendFormat(CultureInfo.InvariantCulture, "{0}={1}&", key, UrlEncode(string.Format("{0}", queryParameters[key])));
|
||||
}
|
||||
sb.Remove(sb.Length - 1, 1);
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data directly to the HttpWebRequest
|
||||
/// </summary>
|
||||
/// <param name="webRequest">HttpWebRequest to write the multipart form data to</param>
|
||||
/// <param name="postParameters">Parameters to include in the multipart form data</param>
|
||||
public static void WriteMultipartFormData(HttpWebRequest webRequest, IDictionary<string, object> postParameters)
|
||||
{
|
||||
string boundary = String.Format("----------{0:N}", Guid.NewGuid());
|
||||
webRequest.ContentType = "multipart/form-data; boundary=" + boundary;
|
||||
using (Stream formDataStream = webRequest.GetRequestStream())
|
||||
{
|
||||
WriteMultipartFormData(formDataStream, boundary, postParameters);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data to the HttpListenerResponse
|
||||
/// </summary>
|
||||
/// <param name="response">HttpListenerResponse</param>
|
||||
/// <param name="postParameters">Parameters to include in the multipart form data</param>
|
||||
public static void WriteMultipartFormData(HttpListenerResponse response, IDictionary<string, object> postParameters)
|
||||
{
|
||||
string boundary = String.Format("----------{0:N}", Guid.NewGuid());
|
||||
response.ContentType = "multipart/form-data; boundary=" + boundary;
|
||||
WriteMultipartFormData(response.OutputStream, boundary, postParameters);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data to a Stream, content-type should be set before this!
|
||||
/// </summary>
|
||||
/// <param name="formDataStream">Stream to write the multipart form data to</param>
|
||||
/// <param name="boundary">String boundary for the multipart/form-data</param>
|
||||
/// <param name="postParameters">Parameters to include in the multipart form data</param>
|
||||
public static void WriteMultipartFormData(Stream formDataStream, string boundary, IDictionary<string, object> postParameters)
|
||||
{
|
||||
bool needsClrf = false;
|
||||
foreach (var param in postParameters)
|
||||
{
|
||||
// Add a CRLF to allow multiple parameters to be added.
|
||||
// Skip it on the first parameter, add it to subsequent parameters.
|
||||
if (needsClrf)
|
||||
{
|
||||
formDataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, Encoding.UTF8.GetByteCount("\r\n"));
|
||||
}
|
||||
|
||||
needsClrf = true;
|
||||
|
||||
if (param.Value is IBinaryContainer)
|
||||
{
|
||||
IBinaryContainer binaryParameter = (IBinaryContainer)param.Value;
|
||||
binaryParameter.WriteFormDataToStream(boundary, param.Key, formDataStream);
|
||||
}
|
||||
else
|
||||
{
|
||||
string postData = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}",
|
||||
boundary,
|
||||
param.Key,
|
||||
param.Value);
|
||||
formDataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData));
|
||||
}
|
||||
}
|
||||
|
||||
// Add the end of the request. Start with a newline
|
||||
string footer = "\r\n--" + boundary + "--\r\n";
|
||||
formDataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Post the parameters "x-www-form-urlencoded"
|
||||
/// </summary>
|
||||
/// <param name="webRequest"></param>
|
||||
/// <param name="parameters"></param>
|
||||
public static void UploadFormUrlEncoded(HttpWebRequest webRequest, IDictionary<string, object> parameters)
|
||||
{
|
||||
webRequest.ContentType = "application/x-www-form-urlencoded";
|
||||
string urlEncoded = GenerateQueryParameters(parameters);
|
||||
|
||||
byte[] data = Encoding.UTF8.GetBytes(urlEncoded);
|
||||
using (var requestStream = webRequest.GetRequestStream())
|
||||
{
|
||||
requestStream.Write(data, 0, data.Length);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Log the headers of the WebResponse, if IsDebugEnabled
|
||||
/// </summary>
|
||||
/// <param name="response">WebResponse</param>
|
||||
private static void DebugHeaders(WebResponse response)
|
||||
{
|
||||
if (!LOG.IsDebugEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
LOG.DebugFormat("Debug information on the response from {0} :", response.ResponseUri);
|
||||
foreach (string key in response.Headers.AllKeys)
|
||||
{
|
||||
LOG.DebugFormat("Reponse-header: {0}={1}", key, response.Headers[key]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the web response.
|
||||
/// </summary>
|
||||
/// <param name="webRequest">The request object.</param>
|
||||
/// <returns>The response data.</returns>
|
||||
/// This method should handle the StatusCode better!
|
||||
public static string GetResponseAsString(HttpWebRequest webRequest)
|
||||
{
|
||||
return GetResponseAsString(webRequest, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read the response as string
|
||||
/// </summary>
|
||||
/// <param name="response"></param>
|
||||
/// <returns>string or null</returns>
|
||||
private static string GetResponseAsString(HttpWebResponse response)
|
||||
{
|
||||
string responseData = null;
|
||||
if (response == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
using (response)
|
||||
{
|
||||
Stream responseStream = response.GetResponseStream();
|
||||
if (responseStream != null)
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(responseStream, true))
|
||||
{
|
||||
responseData = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
return responseData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="webRequest"></param>
|
||||
/// <param name="alsoReturnContentOnError"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetResponseAsString(HttpWebRequest webRequest, bool alsoReturnContentOnError)
|
||||
{
|
||||
string responseData = null;
|
||||
HttpWebResponse response = null;
|
||||
bool isHttpError = false;
|
||||
try
|
||||
{
|
||||
response = (HttpWebResponse)webRequest.GetResponse();
|
||||
LOG.InfoFormat("Response status: {0}", response.StatusCode);
|
||||
isHttpError = (int)response.StatusCode >= 300;
|
||||
if (isHttpError)
|
||||
{
|
||||
LOG.ErrorFormat("HTTP error {0}", response.StatusCode);
|
||||
}
|
||||
DebugHeaders(response);
|
||||
responseData = GetResponseAsString(response);
|
||||
if (isHttpError)
|
||||
{
|
||||
LOG.ErrorFormat("HTTP response {0}", responseData);
|
||||
}
|
||||
}
|
||||
catch (WebException e)
|
||||
{
|
||||
response = (HttpWebResponse)e.Response;
|
||||
HttpStatusCode statusCode = HttpStatusCode.Unused;
|
||||
if (response != null)
|
||||
{
|
||||
statusCode = response.StatusCode;
|
||||
LOG.ErrorFormat("HTTP error {0}", statusCode);
|
||||
string errorContent = GetResponseAsString(response);
|
||||
if (alsoReturnContentOnError)
|
||||
{
|
||||
return errorContent;
|
||||
}
|
||||
LOG.ErrorFormat("Content: {0}", errorContent);
|
||||
}
|
||||
LOG.Error("WebException: ", e);
|
||||
if (statusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
throw new UnauthorizedAccessException(e.Message);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (response != null)
|
||||
{
|
||||
if (isHttpError)
|
||||
{
|
||||
LOG.ErrorFormat("HTTP error {0} with content: {1}", response.StatusCode, responseData);
|
||||
}
|
||||
response.Close();
|
||||
}
|
||||
}
|
||||
return responseData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get LastModified for a URI
|
||||
/// </summary>
|
||||
/// <param name="uri">Uri</param>
|
||||
/// <returns>DateTime</returns>
|
||||
public static DateTime GetLastModified(Uri uri)
|
||||
{
|
||||
try
|
||||
{
|
||||
HttpWebRequest webRequest = CreateWebRequest(uri);
|
||||
webRequest.Method = HTTPMethod.HEAD.ToString();
|
||||
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
|
||||
{
|
||||
LOG.DebugFormat("RSS feed was updated at {0}", webResponse.LastModified);
|
||||
return webResponse.LastModified;
|
||||
}
|
||||
}
|
||||
catch (Exception wE)
|
||||
{
|
||||
LOG.WarnFormat("Problem requesting HTTP - HEAD on uri {0}", uri);
|
||||
LOG.Warn(wE.Message);
|
||||
// Pretend it is old
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This interface can be used to pass binary information around, like byte[] or Image
|
||||
/// </summary>
|
||||
public interface IBinaryContainer
|
||||
{
|
||||
void WriteFormDataToStream(string boundary, string name, Stream formDataStream);
|
||||
|
||||
void WriteToStream(Stream formDataStream);
|
||||
|
||||
string ToBase64String(Base64FormattingOptions formattingOptions);
|
||||
|
||||
byte[] ToByteArray();
|
||||
|
||||
void Upload(HttpWebRequest webRequest);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A container to supply files to a Multi-part form data upload
|
||||
/// </summary>
|
||||
public class ByteContainer : IBinaryContainer
|
||||
{
|
||||
private readonly byte[] _file;
|
||||
private readonly string _fileName;
|
||||
private readonly string _contentType;
|
||||
private readonly int _fileSize;
|
||||
|
||||
public ByteContainer(byte[] file) : this(file, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ByteContainer(byte[] file, string filename) : this(file, filename, null)
|
||||
{
|
||||
}
|
||||
|
||||
public ByteContainer(byte[] file, string filename, string contenttype) : this(file, filename, contenttype, 0)
|
||||
{
|
||||
}
|
||||
|
||||
public ByteContainer(byte[] file, string filename, string contenttype, int filesize)
|
||||
{
|
||||
_file = file;
|
||||
_fileName = filename;
|
||||
_contentType = contenttype;
|
||||
_fileSize = filesize == 0 ? file.Length : filesize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a Base64String from the byte[]
|
||||
/// </summary>
|
||||
/// <returns>string</returns>
|
||||
public string ToBase64String(Base64FormattingOptions formattingOptions)
|
||||
{
|
||||
return Convert.ToBase64String(_file, 0, _fileSize, formattingOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the initial byte-array which was supplied when creating the FileParameter
|
||||
/// </summary>
|
||||
/// <returns>byte[]</returns>
|
||||
public byte[] ToByteArray()
|
||||
{
|
||||
return _file;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data directly to the HttpWebRequest response stream
|
||||
/// </summary>
|
||||
/// <param name="boundary">Separator</param>
|
||||
/// <param name="name">name</param>
|
||||
/// <param name="formDataStream">Stream to write to</param>
|
||||
public void WriteFormDataToStream(string boundary, string name, Stream formDataStream)
|
||||
{
|
||||
// Add just the first part of this param, since we will write the file data directly to the Stream
|
||||
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
|
||||
boundary,
|
||||
name,
|
||||
_fileName ?? name,
|
||||
_contentType ?? "application/octet-stream");
|
||||
|
||||
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
|
||||
|
||||
// Write the file data directly to the Stream, rather than serializing it to a string.
|
||||
formDataStream.Write(_file, 0, _fileSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A plain "write data to stream"
|
||||
/// </summary>
|
||||
/// <param name="dataStream">Stream to write to</param>
|
||||
public void WriteToStream(Stream dataStream)
|
||||
{
|
||||
// Write the file data directly to the Stream, rather than serializing it to a string.
|
||||
dataStream.Write(_file, 0, _fileSize);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload the file to the webrequest
|
||||
/// </summary>
|
||||
/// <param name="webRequest"></param>
|
||||
public void Upload(HttpWebRequest webRequest)
|
||||
{
|
||||
webRequest.ContentType = _contentType;
|
||||
webRequest.ContentLength = _fileSize;
|
||||
using (var requestStream = webRequest.GetRequestStream())
|
||||
{
|
||||
WriteToStream(requestStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A container to supply images to a Multi-part form data upload
|
||||
/// </summary>
|
||||
public class BitmapContainer : IBinaryContainer
|
||||
{
|
||||
private readonly Bitmap _bitmap;
|
||||
private readonly SurfaceOutputSettings _outputSettings;
|
||||
private readonly string _fileName;
|
||||
|
||||
public BitmapContainer(Bitmap bitmap, SurfaceOutputSettings outputSettings, string filename)
|
||||
{
|
||||
_bitmap = bitmap;
|
||||
_outputSettings = outputSettings;
|
||||
_fileName = filename;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a Base64String from the image by saving it to a memory stream and converting it.
|
||||
/// Should be avoided if possible, as this uses a lot of memory.
|
||||
/// </summary>
|
||||
/// <returns>string</returns>
|
||||
public string ToBase64String(Base64FormattingOptions formattingOptions)
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings);
|
||||
return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a byte[] from the image by saving it to a memory stream.
|
||||
/// Should be avoided if possible, as this uses a lot of memory.
|
||||
/// </summary>
|
||||
/// <returns>byte[]</returns>
|
||||
public byte[] ToByteArray()
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
ImageOutput.SaveToStream(_bitmap, null, stream, _outputSettings);
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data directly to the HttpWebRequest response stream
|
||||
/// </summary>
|
||||
/// <param name="boundary">Separator</param>
|
||||
/// <param name="name">Name of the thing/file</param>
|
||||
/// <param name="formDataStream">Stream to write to</param>
|
||||
public void WriteFormDataToStream(string boundary, string name, Stream formDataStream)
|
||||
{
|
||||
// Add just the first part of this param, since we will write the file data directly to the Stream
|
||||
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
|
||||
boundary,
|
||||
name,
|
||||
_fileName ?? name,
|
||||
"image/" + _outputSettings.Format);
|
||||
|
||||
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
|
||||
ImageOutput.SaveToStream(_bitmap, null, formDataStream, _outputSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A plain "write data to stream"
|
||||
/// </summary>
|
||||
/// <param name="dataStream"></param>
|
||||
public void WriteToStream(Stream dataStream)
|
||||
{
|
||||
// Write the file data directly to the Stream, rather than serializing it to a string.
|
||||
ImageOutput.SaveToStream(_bitmap, null, dataStream, _outputSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload the image to the webrequest
|
||||
/// </summary>
|
||||
/// <param name="webRequest"></param>
|
||||
public void Upload(HttpWebRequest webRequest)
|
||||
{
|
||||
webRequest.ContentType = "image/" + _outputSettings.Format;
|
||||
using (var requestStream = webRequest.GetRequestStream())
|
||||
{
|
||||
WriteToStream(requestStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A container to supply surfaces to a Multi-part form data upload
|
||||
/// </summary>
|
||||
public class SurfaceContainer : IBinaryContainer
|
||||
{
|
||||
private readonly ISurface _surface;
|
||||
private readonly SurfaceOutputSettings _outputSettings;
|
||||
private readonly string _fileName;
|
||||
|
||||
public SurfaceContainer(ISurface surface, SurfaceOutputSettings outputSettings, string filename)
|
||||
{
|
||||
_surface = surface;
|
||||
_outputSettings = outputSettings;
|
||||
_fileName = filename;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a Base64String from the Surface by saving it to a memory stream and converting it.
|
||||
/// Should be avoided if possible, as this uses a lot of memory.
|
||||
/// </summary>
|
||||
/// <returns>string</returns>
|
||||
public string ToBase64String(Base64FormattingOptions formattingOptions)
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
ImageOutput.SaveToStream(_surface, stream, _outputSettings);
|
||||
return Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length, formattingOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a byte[] from the image by saving it to a memory stream.
|
||||
/// Should be avoided if possible, as this uses a lot of memory.
|
||||
/// </summary>
|
||||
/// <returns>byte[]</returns>
|
||||
public byte[] ToByteArray()
|
||||
{
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
ImageOutput.SaveToStream(_surface, stream, _outputSettings);
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write Multipart Form Data directly to the HttpWebRequest response stream
|
||||
/// </summary>
|
||||
/// <param name="boundary">Multipart separator</param>
|
||||
/// <param name="name">Name of the thing</param>
|
||||
/// <param name="formDataStream">Stream to write to</param>
|
||||
public void WriteFormDataToStream(string boundary, string name, Stream formDataStream)
|
||||
{
|
||||
// Add just the first part of this param, since we will write the file data directly to the Stream
|
||||
string header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n",
|
||||
boundary,
|
||||
name,
|
||||
_fileName ?? name,
|
||||
"image/" + _outputSettings.Format);
|
||||
|
||||
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, Encoding.UTF8.GetByteCount(header));
|
||||
ImageOutput.SaveToStream(_surface, formDataStream, _outputSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A plain "write data to stream"
|
||||
/// </summary>
|
||||
/// <param name="dataStream"></param>
|
||||
public void WriteToStream(Stream dataStream)
|
||||
{
|
||||
// Write the file data directly to the Stream, rather than serializing it to a string.
|
||||
ImageOutput.SaveToStream(_surface, dataStream, _outputSettings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload the Surface as image to the webrequest
|
||||
/// </summary>
|
||||
/// <param name="webRequest"></param>
|
||||
public void Upload(HttpWebRequest webRequest)
|
||||
{
|
||||
webRequest.ContentType = "image/" + _outputSettings.Format.ToString();
|
||||
using (var requestStream = webRequest.GetRequestStream())
|
||||
{
|
||||
WriteToStream(requestStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2016 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on GitHub: https://github.com/greenshot
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions to help with querying the Operating System
|
||||
/// </summary>
|
||||
public static class OperatingSystemExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Test if the current OS is Windows 10
|
||||
/// </summary>
|
||||
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
|
||||
/// <returns>true if we are running on Windows 10</returns>
|
||||
public static bool IsWindows10(this OperatingSystem operatingSystem)
|
||||
{
|
||||
return operatingSystem.Version.Major == 10;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if the current OS is Windows 8(.1)
|
||||
/// </summary>
|
||||
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
|
||||
/// <returns>true if we are running on Windows 8(.1)</returns>
|
||||
public static bool IsWindows8(this OperatingSystem operatingSystem)
|
||||
{
|
||||
return operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 2;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if the current OS is Windows 8 or later
|
||||
/// </summary>
|
||||
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
|
||||
/// <returns>true if we are running on Windows 8 or later</returns>
|
||||
public static bool IsWindows8OrLater(this OperatingSystem operatingSystem)
|
||||
{
|
||||
return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 2) || operatingSystem.Version.Major >= 6;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if the current OS is Windows 7 or later
|
||||
/// </summary>
|
||||
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
|
||||
/// <returns>true if we are running on Windows 7 or later</returns>
|
||||
public static bool IsWindows7OrLater(this OperatingSystem operatingSystem)
|
||||
{
|
||||
return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 1) || operatingSystem.Version.Major >= 6;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if the current OS is Windows Vista or later
|
||||
/// </summary>
|
||||
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
|
||||
/// <returns>true if we are running on Windows Vista or later</returns>
|
||||
public static bool IsWindowsVistaOrLater(this OperatingSystem operatingSystem)
|
||||
{
|
||||
return operatingSystem.Version.Major >= 6;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if the current OS is Windows XP or later
|
||||
/// </summary>
|
||||
/// <param name="operatingSystem">OperatingSystem from Environment.OSVersion</param>
|
||||
/// <returns>true if we are running on Windows XP or later</returns>
|
||||
public static bool IsWindowsXpOrLater(this OperatingSystem operatingSystem)
|
||||
{
|
||||
// Windows 2000 is Major 5 minor 0
|
||||
return Environment.OSVersion.Version.Major > 5 || (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,295 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.IniFile;
|
||||
using Greenshot.Plugin;
|
||||
using GreenshotPlugin.UnmanagedHelpers;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PluginUtils.
|
||||
/// </summary>
|
||||
public static class PluginUtils
|
||||
{
|
||||
private static readonly CoreConfiguration conf = IniConfig.GetIniSection<CoreConfiguration>();
|
||||
private const string PATH_KEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\";
|
||||
private static readonly IDictionary<string, Image> exeIconCache = new Dictionary<string, Image>();
|
||||
|
||||
static PluginUtils()
|
||||
{
|
||||
conf.PropertyChanged += OnIconSizeChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Simple global property to get the Greenshot host
|
||||
/// </summary>
|
||||
public static IGreenshotHost Host
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear icon cache
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void OnIconSizeChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == "IconSize")
|
||||
{
|
||||
List<Image> cachedImages = new List<Image>();
|
||||
lock (exeIconCache)
|
||||
{
|
||||
foreach (string key in exeIconCache.Keys)
|
||||
{
|
||||
cachedImages.Add(exeIconCache[key]);
|
||||
}
|
||||
exeIconCache.Clear();
|
||||
}
|
||||
foreach (Image cachedImage in cachedImages)
|
||||
{
|
||||
if (cachedImage != null)
|
||||
{
|
||||
cachedImage.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the path of an executable
|
||||
/// </summary>
|
||||
/// <param name="exeName">e.g. cmd.exe</param>
|
||||
/// <returns>Path to file</returns>
|
||||
public static string GetExePath(string exeName)
|
||||
{
|
||||
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(PATH_KEY + exeName, false))
|
||||
{
|
||||
if (key != null)
|
||||
{
|
||||
// "" is the default key, which should point to the requested location
|
||||
return (string)key.GetValue("");
|
||||
}
|
||||
}
|
||||
foreach (string pathEntry in (Environment.GetEnvironmentVariable("PATH") ?? "").Split(';'))
|
||||
{
|
||||
try
|
||||
{
|
||||
string path = pathEntry.Trim();
|
||||
if (!String.IsNullOrEmpty(path) && File.Exists(path = Path.Combine(path, exeName)))
|
||||
{
|
||||
return Path.GetFullPath(path);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
LOG.WarnFormat("Problem with path entry '{0}'.", pathEntry);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get icon for executable, from the cache
|
||||
/// </summary>
|
||||
/// <param name="path">path to the exe or dll</param>
|
||||
/// <param name="index">index of the icon</param>
|
||||
/// <returns>Bitmap with the icon or null if something happended</returns>
|
||||
public static Image GetCachedExeIcon(string path, int index)
|
||||
{
|
||||
string cacheKey = string.Format("{0}:{1}", path, index);
|
||||
Image returnValue;
|
||||
lock (exeIconCache)
|
||||
{
|
||||
if (!exeIconCache.TryGetValue(cacheKey, out returnValue))
|
||||
{
|
||||
lock (exeIconCache)
|
||||
{
|
||||
if (!exeIconCache.TryGetValue(cacheKey, out returnValue))
|
||||
{
|
||||
returnValue = GetExeIcon(path, index);
|
||||
if (returnValue != null)
|
||||
{
|
||||
exeIconCache.Add(cacheKey, returnValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get icon for executable
|
||||
/// </summary>
|
||||
/// <param name="path">path to the exe or dll</param>
|
||||
/// <param name="index">index of the icon</param>
|
||||
/// <returns>Bitmap with the icon or null if something happended</returns>
|
||||
private static Bitmap GetExeIcon(string path, int index)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
using (Icon appIcon = ImageHelper.ExtractAssociatedIcon(path, index, conf.UseLargeIcons))
|
||||
{
|
||||
if (appIcon != null)
|
||||
{
|
||||
return appIcon.ToBitmap();
|
||||
}
|
||||
}
|
||||
using (Icon appIcon = Shell32.GetFileIcon(path, conf.UseLargeIcons ? Shell32.IconSize.Large : Shell32.IconSize.Small, false))
|
||||
{
|
||||
if (appIcon != null)
|
||||
{
|
||||
return appIcon.ToBitmap();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exIcon)
|
||||
{
|
||||
LOG.Error("error retrieving icon: ", exIcon);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to add a MenuItem to the File MenuItem of an ImageEditor
|
||||
/// </summary>
|
||||
/// <param name="image">Image to display in the menu</param>
|
||||
/// <param name="text">Text to display in the menu</param>
|
||||
/// <param name="tag">The TAG value</param>
|
||||
/// <param name="shortcutKeys">Keys which can be used as shortcut</param>
|
||||
/// <param name="handler">The onclick handler</param>
|
||||
public static void AddToFileMenu(IImageEditor imageEditor, Image image, string text, object tag, Keys? shortcutKeys, EventHandler handler)
|
||||
{
|
||||
ToolStripMenuItem item = new ToolStripMenuItem();
|
||||
item.Image = image;
|
||||
item.Text = text;
|
||||
item.Tag = tag;
|
||||
if (shortcutKeys.HasValue)
|
||||
{
|
||||
item.ShortcutKeys = shortcutKeys.Value;
|
||||
}
|
||||
item.Click += handler;
|
||||
AddToFileMenu(imageEditor, item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to add a MenuItem to the File MenuItem of an ImageEditor
|
||||
/// </summary>
|
||||
/// <param name="imageEditor"></param>
|
||||
/// <param name="item"></param>
|
||||
public static void AddToFileMenu(IImageEditor imageEditor, ToolStripMenuItem item)
|
||||
{
|
||||
ToolStripMenuItem toolStripMenuItem = imageEditor.GetFileMenuItem();
|
||||
bool added = false;
|
||||
for (int i = 0; i < toolStripMenuItem.DropDownItems.Count; i++)
|
||||
{
|
||||
if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator))
|
||||
{
|
||||
toolStripMenuItem.DropDownItems.Insert(i, item);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!added)
|
||||
{
|
||||
toolStripMenuItem.DropDownItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to add a MenuItem to the Plugin MenuItem of an ImageEditor
|
||||
/// </summary>
|
||||
/// <param name="imageEditor"></param>
|
||||
/// <param name="item"></param>
|
||||
public static void AddToPluginMenu(IImageEditor imageEditor, ToolStripMenuItem item)
|
||||
{
|
||||
ToolStripMenuItem toolStripMenuItem = imageEditor.GetPluginMenuItem();
|
||||
bool added = false;
|
||||
for (int i = 0; i < toolStripMenuItem.DropDownItems.Count; i++)
|
||||
{
|
||||
if (toolStripMenuItem.DropDownItems[i].GetType() == typeof(ToolStripSeparator))
|
||||
{
|
||||
toolStripMenuItem.DropDownItems.Insert(i, item);
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!added)
|
||||
{
|
||||
toolStripMenuItem.DropDownItems.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to add a plugin MenuItem to the Greenshot context menu
|
||||
/// </summary>
|
||||
/// <param name="imageEditor"></param>
|
||||
/// <param name="item"></param>
|
||||
public static void AddToContextMenu(IGreenshotHost host, ToolStripMenuItem item)
|
||||
{
|
||||
// Here we can hang ourselves to the main context menu!
|
||||
ContextMenuStrip contextMenu = host.MainMenu;
|
||||
bool addedItem = false;
|
||||
|
||||
// Try to find a separator, so we insert ourselves after it
|
||||
for (int i = 0; i < contextMenu.Items.Count; i++)
|
||||
{
|
||||
if (contextMenu.Items[i].GetType() == typeof(ToolStripSeparator))
|
||||
{
|
||||
// Check if we need to add a new separator, which is done if the first found has a Tag with the value "PluginsAreAddedBefore"
|
||||
if ("PluginsAreAddedBefore".Equals(contextMenu.Items[i].Tag))
|
||||
{
|
||||
ToolStripSeparator separator = new ToolStripSeparator();
|
||||
separator.Tag = "PluginsAreAddedAfter";
|
||||
separator.Size = new Size(305, 6);
|
||||
contextMenu.Items.Insert(i, separator);
|
||||
}
|
||||
else if (!"PluginsAreAddedAfter".Equals(contextMenu.Items[i].Tag))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
contextMenu.Items.Insert(i + 1, item);
|
||||
addedItem = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we didn't insert the item, we just add it...
|
||||
if (!addedItem)
|
||||
{
|
||||
contextMenu.Items.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,770 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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 readonly int colorCount;
|
||||
|
||||
private Int32[] reds;
|
||||
private Int32[] greens;
|
||||
private Int32[] blues;
|
||||
private Int32[] sums;
|
||||
|
||||
private readonly Int64[,,] weights;
|
||||
private readonly Int64[,,] momentsRed;
|
||||
private readonly Int64[,,] momentsGreen;
|
||||
private readonly Int64[,,] momentsBlue;
|
||||
private readonly Single[,,] moments;
|
||||
|
||||
private byte[] tag;
|
||||
|
||||
private readonly WuColorCube[] cubes;
|
||||
private readonly 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 = (Single)halfRed * halfRed + (Single)halfGreen * halfGreen + (Single)halfBlue * halfBlue;
|
||||
Single temp = halfDistance / halfWeight;
|
||||
|
||||
halfRed = wholeRed - halfRed;
|
||||
halfGreen = wholeGreen - halfGreen;
|
||||
halfBlue = wholeBlue - halfBlue;
|
||||
halfWeight = wholeWeight - halfWeight;
|
||||
|
||||
if (halfWeight != 0)
|
||||
{
|
||||
halfDistance = (Single)halfRed * halfRed + (Single)halfGreen * halfGreen + (Single)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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,190 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace GreenshotPlugin.Core
|
||||
{
|
||||
public static class StringExtensions
|
||||
{
|
||||
private const string RGBIV = "dlgjowejgogkklwj";
|
||||
private const string KEY = "lsjvkwhvwujkagfauguwcsjgu2wueuff";
|
||||
|
||||
/// <summary>
|
||||
/// Format a string with the specified object
|
||||
/// </summary>
|
||||
/// <param name="format">String with formatting, like {name}</param>
|
||||
/// <param name="source">Object used for the formatting</param>
|
||||
/// <returns>Formatted string</returns>
|
||||
public static string FormatWith(this string format, object source)
|
||||
{
|
||||
return FormatWith(format, null, source);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format the string "format" with the source
|
||||
/// </summary>
|
||||
/// <param name="format"></param>
|
||||
/// <param name="provider"></param>
|
||||
/// <param name="source">object with properties, if a property has the type IDictionary string,string it can used these parameters too</param>
|
||||
/// <returns>Formatted string</returns>
|
||||
public static string FormatWith(this string format, IFormatProvider provider, object source)
|
||||
{
|
||||
if (format == null)
|
||||
{
|
||||
throw new ArgumentNullException("format");
|
||||
}
|
||||
|
||||
IDictionary<string, object> properties = new Dictionary<string, object>();
|
||||
foreach (var propertyInfo in source.GetType().GetProperties())
|
||||
{
|
||||
if (propertyInfo.CanRead && propertyInfo.CanWrite)
|
||||
{
|
||||
object value = propertyInfo.GetValue(source, null);
|
||||
if (propertyInfo.PropertyType != typeof(IDictionary<string, string>))
|
||||
{
|
||||
properties.Add(propertyInfo.Name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
IDictionary<string, string> dictionary = (IDictionary<string, string>)value;
|
||||
foreach (var propertyKey in dictionary.Keys)
|
||||
{
|
||||
properties.Add(propertyKey, dictionary[propertyKey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Regex r = new Regex(@"(?<start>\{)+(?<property>[\w\.\[\]]+)(?<format>:[^}]+)?(?<end>\})+", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
|
||||
|
||||
List<object> values = new List<object>();
|
||||
string rewrittenFormat = r.Replace(format, delegate (Match m)
|
||||
{
|
||||
Group startGroup = m.Groups["start"];
|
||||
Group propertyGroup = m.Groups["property"];
|
||||
Group formatGroup = m.Groups["format"];
|
||||
Group endGroup = m.Groups["end"];
|
||||
|
||||
object value;
|
||||
if (properties.TryGetValue(propertyGroup.Value, out value))
|
||||
{
|
||||
values.Add(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
values.Add(source);
|
||||
}
|
||||
return new string('{', startGroup.Captures.Count) + (values.Count - 1) + formatGroup.Value + new string('}', endGroup.Captures.Count);
|
||||
});
|
||||
|
||||
return string.Format(provider, rewrittenFormat, values.ToArray());
|
||||
}
|
||||
|
||||
/// <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);
|
||||
using (CryptoStream cs = new CryptoStream(ms, rijn.CreateEncryptor(key, rgbIV), CryptoStreamMode.Write))
|
||||
{
|
||||
cs.Write(clearTextBytes, 0, clearTextBytes.Length);
|
||||
cs.FlushFinalBlock();
|
||||
|
||||
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);
|
||||
|
||||
using (CryptoStream cs = new CryptoStream(ms, rijn.CreateDecryptor(key, rgbIV), CryptoStreamMode.Write))
|
||||
{
|
||||
cs.Write(encryptedTextBytes, 0, encryptedTextBytes.Length);
|
||||
cs.FlushFinalBlock();
|
||||
returnValue = Encoding.ASCII.GetString(ms.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LOG.ErrorFormat("Error decrypting {0}, error: ", EncryptedText, ex.Message);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read "streamextensions" :)
|
||||
/// </summary>
|
||||
/// <param name="input">Stream</param>
|
||||
/// <param name="output">Stream</param>
|
||||
public static void CopyTo(this Stream input, Stream output)
|
||||
{
|
||||
byte[] buffer = new byte[16 * 1024]; // Fairly arbitrary size
|
||||
int bytesRead;
|
||||
|
||||
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
|
||||
{
|
||||
output.Write(buffer, 0, bytesRead);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,901 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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
|
||||
{
|
||||
public string Title
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string Filename
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public DateTime DateTime
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public float DpiX
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public float DpiY
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
private readonly 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);
|
||||
}
|
||||
}
|
||||
|
||||
public CaptureMode CaptureMode
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
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 : ICapture
|
||||
{
|
||||
private List<ICaptureElement> _elements = new List<ICaptureElement>();
|
||||
|
||||
private Rectangle _screenBounds = Rectangle.Empty;
|
||||
/// <summary>
|
||||
/// Get/Set the Screenbounds
|
||||
/// </summary>
|
||||
public Rectangle ScreenBounds
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_screenBounds == Rectangle.Empty)
|
||||
{
|
||||
_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;
|
||||
/// <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
|
||||
// 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);
|
||||
}
|
||||
|
||||
// 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() == obj.GetType())
|
||||
{
|
||||
CaptureElement other = obj as CaptureElement;
|
||||
if (other != null && 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 readonly CoreConfiguration Configuration = 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)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
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. This implementation
|
||||
/// can conveniently be used when the cursor location is needed to deal with a fullscreen bitmap.
|
||||
/// </summary>
|
||||
/// <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(User32.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 = User32.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="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 (Configuration.NoDWMCaptureForProduct != null && Configuration.NoDWMCaptureForProduct.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
string productName = process.MainModule.FileVersionInfo.ProductName;
|
||||
if (productName != null && Configuration.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="process">Process owning the window</param>
|
||||
/// <returns>true if it's allowed</returns>
|
||||
public static bool IsGdiAllowed(Process process)
|
||||
{
|
||||
if (process != null)
|
||||
{
|
||||
if (Configuration.NoGDICaptureForProduct != null && Configuration.NoGDICaptureForProduct.Count > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
string productName = process.MainModule.FileVersionInfo.ProductName;
|
||||
if (productName != null && Configuration.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();
|
||||
}
|
||||
Image capturedImage = null;
|
||||
// If the CaptureHandler has a handle use this, otherwise use the CaptureRectangle here
|
||||
if (CaptureHandler.CaptureScreenRectangle != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
capturedImage = CaptureHandler.CaptureScreenRectangle(captureBounds);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
// If no capture, use the normal screen capture
|
||||
if (capturedImage == null)
|
||||
{
|
||||
capturedImage = CaptureRectangle(captureBounds);
|
||||
}
|
||||
capture.Image = capturedImage;
|
||||
capture.Location = captureBounds.Location;
|
||||
return capture.Image == null ? null : capture;
|
||||
}
|
||||
|
||||
/// <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 CaptureRectangleFromDesktopScreen(ICapture capture, Rectangle captureBounds)
|
||||
{
|
||||
if (capture == null)
|
||||
{
|
||||
capture = new Capture();
|
||||
}
|
||||
capture.Image = CaptureRectangle(captureBounds);
|
||||
capture.Location = captureBounds.Location;
|
||||
return capture.Image == null ? null : 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
// select the bitmap object and store the old handle
|
||||
using (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;
|
||||
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 = Image.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 = Image.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!");
|
||||
if (exception != null)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return returnBitmap;
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,160 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Do not use the base, just override so we have our own defaults
|
||||
/// </summary>
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
|
||||
AddField(GetType(), FieldType.ARROWHEADS, 2);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
|
||||
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 (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);
|
||||
using (Matrix matrix = new Matrix())
|
||||
{
|
||||
Rectangle drawingBounds = Rectangle.Round(path.GetBounds(matrix, pen));
|
||||
drawingBounds.Inflate(2, 2);
|
||||
return drawingBounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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))
|
||||
{
|
||||
return;
|
||||
}
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,673 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Drawing.Fields;
|
||||
using Greenshot.Memento;
|
||||
using Greenshot.Plugin;
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using GreenshotPlugin.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Threading;
|
||||
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 readonly ComponentResourceManager editorFormResources = new ComponentResourceManager(typeof(ImageEditorForm));
|
||||
|
||||
public Guid ParentID
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public DrawableContainerList()
|
||||
{
|
||||
}
|
||||
|
||||
public DrawableContainerList(Guid parentID)
|
||||
{
|
||||
ParentID = parentID;
|
||||
}
|
||||
|
||||
public EditStatus Status
|
||||
{
|
||||
get
|
||||
{
|
||||
return this[Count - 1].Status;
|
||||
}
|
||||
set
|
||||
{
|
||||
foreach (var 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 (var dc in this)
|
||||
{
|
||||
ret &= dc.Selected;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
set
|
||||
{
|
||||
foreach (var 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
|
||||
{
|
||||
ParentID = value.ID;
|
||||
foreach (var drawableContainer in this)
|
||||
{
|
||||
var dc = (DrawableContainer)drawableContainer;
|
||||
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>
|
||||
/// Apply matrix to all elements
|
||||
/// </summary>
|
||||
public void Transform(Matrix matrix)
|
||||
{
|
||||
// Track modifications
|
||||
bool modified = false;
|
||||
Invalidate();
|
||||
foreach (var dc in this)
|
||||
{
|
||||
dc.Transform(matrix);
|
||||
modified = true;
|
||||
}
|
||||
// Invalidate after
|
||||
Invalidate();
|
||||
// If we moved something, tell the surface it's modified!
|
||||
if (modified)
|
||||
{
|
||||
Parent.Modified = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <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 (var 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 (var dc in this)
|
||||
{
|
||||
dc.HideGrippers();
|
||||
dc.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the grippers of all elements in the list.
|
||||
/// </summary>
|
||||
public void ShowGrippers()
|
||||
{
|
||||
foreach (var 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 (var 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 (var drawableContainer in this)
|
||||
{
|
||||
var dc = (DrawableContainer)drawableContainer;
|
||||
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 (var 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 (var 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 to the bitmap related Graphics object</param>
|
||||
/// <param name="bitmap">Bitmap to draw</param>
|
||||
/// <param name="renderMode">the rendermode in which the element is to be drawn</param>
|
||||
/// <param name="clipRectangle"></param>
|
||||
public void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle)
|
||||
{
|
||||
foreach (var drawableContainer in this)
|
||||
{
|
||||
var dc = (DrawableContainer)drawableContainer;
|
||||
if (dc.DrawingBounds.IntersectsWith(clipRectangle))
|
||||
{
|
||||
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 (var drawableContainer in this)
|
||||
{
|
||||
var dc = (DrawableContainer)drawableContainer;
|
||||
dc.HandleFieldChanged(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalidate the bounds of all the DC's in this list
|
||||
/// </summary>
|
||||
public void Invalidate()
|
||||
{
|
||||
foreach (var 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 (var 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--)
|
||||
{
|
||||
var dc = this[i];
|
||||
if (!elements.Contains(dc))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
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)
|
||||
{
|
||||
var dcs = ToArray();
|
||||
for (int i = 0; i < dcs.Length; i++)
|
||||
{
|
||||
var dc = dcs[i];
|
||||
if (!elements.Contains(dc))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
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 (var 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++)
|
||||
{
|
||||
var dc = this[i];
|
||||
if (!elements.Contains(dc))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
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)
|
||||
{
|
||||
var dcs = ToArray();
|
||||
for (int i = dcs.Length - 1; i >= 0; i--)
|
||||
{
|
||||
var dc = dcs[i];
|
||||
if (!elements.Contains(dc))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
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)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var 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>
|
||||
/// <param name="surface"></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 (var drawableContainer in this)
|
||||
{
|
||||
var container = (DrawableContainer)drawableContainer;
|
||||
containersToDelete.Add(container);
|
||||
}
|
||||
foreach (var 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 (var drawableContainer in this)
|
||||
{
|
||||
var container = (DrawableContainer)drawableContainer;
|
||||
containersToDelete.Add(container);
|
||||
}
|
||||
foreach (DrawableContainer container in containersToDelete)
|
||||
{
|
||||
surface.RemoveElement(container, true);
|
||||
}
|
||||
};
|
||||
menu.Items.Add(item);
|
||||
|
||||
// Reset
|
||||
bool canReset = false;
|
||||
foreach (var drawableContainer in this)
|
||||
{
|
||||
var container = (DrawableContainer)drawableContainer;
|
||||
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 (var drawableContainer in this)
|
||||
{
|
||||
var container = (DrawableContainer)drawableContainer;
|
||||
if (!container.HasDefaultSize)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Size defaultSize = container.DefaultSize;
|
||||
container.Invalidate();
|
||||
container.MakeBoundsChangeUndoable(false);
|
||||
container.Width = defaultSize.Width;
|
||||
container.Height = defaultSize.Height;
|
||||
container.Invalidate();
|
||||
}
|
||||
};
|
||||
menu.Items.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ShowContextMenu(MouseEventArgs e, Surface surface)
|
||||
{
|
||||
bool hasMenu = false;
|
||||
foreach (var drawableContainer in this)
|
||||
{
|
||||
var container = (DrawableContainer)drawableContainer;
|
||||
if (!container.HasContextMenu)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
|
||||
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);
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
DrawEllipse(rect, graphics, renderMode, lineThickness, lineColor, fillColor, shadow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This allows another container to draw an ellipse
|
||||
/// </summary>
|
||||
/// <param name="caller"></param>
|
||||
/// <param name="rect"></param>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="renderMode"></param>
|
||||
/// <param name="lineThickness"></param>
|
||||
/// <param name="lineColor"></param>
|
||||
/// <param name="fillColor"></param>
|
||||
/// <param name="shadow"></param>
|
||||
public static void DrawEllipse(Rectangle rect, Graphics graphics, RenderMode renderMode, int lineThickness, Color lineColor, Color fillColor, bool shadow)
|
||||
{
|
||||
bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor);
|
||||
// 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(rect.Left + currentStep, rect.Top + currentStep, rect.Width, rect.Height);
|
||||
graphics.DrawEllipse(shadowPen, shadowRect);
|
||||
currentStep++;
|
||||
alpha = alpha - basealpha / steps;
|
||||
}
|
||||
}
|
||||
}
|
||||
//draw the original shape
|
||||
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)
|
||||
{
|
||||
return EllipseContains(this, x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allow the code to be used externally
|
||||
/// </summary>
|
||||
/// <param name="caller"></param>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public static bool EllipseContains(DrawableContainer caller, int x, int y)
|
||||
{
|
||||
double xDistanceFromCenter = x - (caller.Left + caller.Width / 2);
|
||||
double yDistanceFromCenter = y - (caller.Top + caller.Height / 2);
|
||||
// ellipse: x^2/a^2 + y^2/b^2 = 1
|
||||
return Math.Pow(xDistanceFromCenter, 2) / Math.Pow(caller.Width / 2, 2) + Math.Pow(yDistanceFromCenter, 2) / Math.Pow(caller.Height / 2, 2) < 1;
|
||||
}
|
||||
|
||||
public override bool ClickableAt(int x, int y)
|
||||
{
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 10;
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
return EllipseClickableAt(rect, lineThickness, fillColor, x, y);
|
||||
}
|
||||
|
||||
public static bool EllipseClickableAt(Rectangle rect, int lineThickness, Color fillColor, int x, int y)
|
||||
{
|
||||
// If we clicked inside the rectangle and it's visible we are clickable at.
|
||||
if (!Color.Transparent.Equals(fillColor))
|
||||
{
|
||||
if (rect.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,199 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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 readonly 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 two Collections 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 readonly List<Field> fields = new List<Field>();
|
||||
|
||||
[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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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 readonly 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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 object convert(object o)
|
||||
{
|
||||
if (o == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (o is T1)
|
||||
{
|
||||
return convert((T1)o);
|
||||
}
|
||||
if (o is T2)
|
||||
{
|
||||
return convert((T2)o);
|
||||
}
|
||||
throw new ArgumentException("Cannot handle argument of type " + o.GetType());
|
||||
}
|
||||
|
||||
protected abstract T2 convert(T1 o);
|
||||
|
||||
protected abstract T1 convert(T2 o);
|
||||
}
|
||||
}
|
|
@ -1,177 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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 readonly INotifyPropertyChanged _controlObject;
|
||||
private readonly INotifyPropertyChanged _fieldObject;
|
||||
private readonly string _controlPropertyName;
|
||||
private readonly string _fieldPropertyName;
|
||||
private bool _updatingControl = false;
|
||||
private bool _updatingField = false;
|
||||
private IBindingConverter _converter;
|
||||
private readonly 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="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>
|
||||
public BidirectionalBinding(INotifyPropertyChanged controlObject, string controlPropertyName, INotifyPropertyChanged fieldObject, string fieldPropertyName)
|
||||
{
|
||||
_controlObject = controlObject;
|
||||
_fieldObject = fieldObject;
|
||||
_controlPropertyName = controlPropertyName;
|
||||
_fieldPropertyName = fieldPropertyName;
|
||||
|
||||
_controlObject.PropertyChanged += ControlPropertyChanged;
|
||||
_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 synchronized 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)
|
||||
{
|
||||
_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 synchronization 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)
|
||||
{
|
||||
_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 synchronized value to the correct target format and back</param>
|
||||
/// <param name="validator">validator to intercept synchronization 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)
|
||||
{
|
||||
_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 static 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; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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);
|
||||
}
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,151 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,216 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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 readonly List<IDrawableContainer> boundContainers;
|
||||
private bool internalUpdateRunning;
|
||||
|
||||
private static readonly 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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);
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 0);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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, 15);
|
||||
AddField(GetType(), FieldType.PREVIEW_QUALITY, 1.0d);
|
||||
}
|
||||
|
||||
public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode)
|
||||
{
|
||||
int blurRadius = GetFieldValueAsInt(FieldType.BLUR_RADIUS);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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);
|
||||
using (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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using GreenshotPlugin.Core;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace Greenshot.Drawing.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of GrayscaleFilter.
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
public class GrayscaleFilter : AbstractFilter
|
||||
{
|
||||
public GrayscaleFilter(DrawableContainer parent) : base(parent)
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
ColorMatrix grayscaleMatrix = new ColorMatrix(new[] {
|
||||
new[] {.3f, .3f, .3f, 0, 0},
|
||||
new[] {.59f, .59f, .59f, 0, 0},
|
||||
new[] {.11f, .11f, .11f, 0, 0},
|
||||
new float[] {0, 0, 0, 1, 0},
|
||||
new float[] {0, 0, 0, 0, 1}
|
||||
});
|
||||
using (ImageAttributes ia = new ImageAttributes())
|
||||
{
|
||||
ia.SetColorMatrix(grayscaleMatrix);
|
||||
graphics.DrawImage(applyBitmap, applyRect, applyRect.X, applyRect.Y, applyRect.Width, applyRect.Height, GraphicsUnit.Pixel, ia);
|
||||
}
|
||||
graphics.Restore(state);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
|
||||
namespace Greenshot.Drawing.Filters
|
||||
{
|
||||
[Serializable()]
|
||||
public class HighlightFilter : AbstractFilter
|
||||
{
|
||||
public HighlightFilter(DrawableContainer parent) : base(parent)
|
||||
{
|
||||
AddField(GetType(), FieldType.FILL_COLOR, Color.Yellow);
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
using (IFastBitmap fastBitmap = FastBitmap.CreateCloneOf(applyBitmap, applyRect))
|
||||
{
|
||||
Color highlightColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
for (int y = fastBitmap.Top; y < fastBitmap.Bottom; y++)
|
||||
{
|
||||
for (int x = fastBitmap.Left; x < fastBitmap.Right; x++)
|
||||
{
|
||||
Color color = fastBitmap.GetColorAt(x, y);
|
||||
color = Color.FromArgb(color.A, Math.Min(highlightColor.R, color.R), Math.Min(highlightColor.G, color.G), Math.Min(highlightColor.B, color.B));
|
||||
fastBitmap.SetColorAt(x, y, color);
|
||||
}
|
||||
}
|
||||
fastBitmap.DrawTo(graphics, applyRect.Location);
|
||||
}
|
||||
graphics.Restore(state);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Drawing.Fields;
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Greenshot.Drawing.Filters
|
||||
{
|
||||
public interface IFilter : INotifyPropertyChanged, IFieldHolder
|
||||
{
|
||||
DrawableContainer Parent { get; set; }
|
||||
|
||||
void Apply(Graphics graphics, Bitmap bmp, Rectangle rect, RenderMode renderMode);
|
||||
|
||||
DrawableContainer GetParent();
|
||||
|
||||
bool Invert { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
|
||||
namespace Greenshot.Drawing.Filters
|
||||
{
|
||||
[Serializable]
|
||||
public class MagnifierFilter : AbstractFilter
|
||||
{
|
||||
public MagnifierFilter(DrawableContainer parent) : base(parent)
|
||||
{
|
||||
AddField(GetType(), FieldType.MAGNIFICATION_FACTOR, 2);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
int magnificationFactor = GetFieldValueAsInt(FieldType.MAGNIFICATION_FACTOR);
|
||||
GraphicsState state = graphics.Save();
|
||||
if (Invert)
|
||||
{
|
||||
graphics.SetClip(applyRect);
|
||||
graphics.ExcludeClip(rect);
|
||||
}
|
||||
graphics.SmoothingMode = SmoothingMode.None;
|
||||
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||
int halfWidth = rect.Width / 2;
|
||||
int halfHeight = rect.Height / 2;
|
||||
int newWidth = rect.Width / magnificationFactor;
|
||||
int newHeight = rect.Height / magnificationFactor;
|
||||
Rectangle source = new Rectangle(rect.X + halfWidth - newWidth / 2, rect.Y + halfHeight - newHeight / 2, newWidth, newHeight);
|
||||
graphics.DrawImage(applyBitmap, rect, source, GraphicsUnit.Pixel);
|
||||
graphics.Restore(state);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Drawing.Fields;
|
||||
using Greenshot.Helpers;
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using GreenshotPlugin.Core;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Greenshot.Drawing.Filters
|
||||
{
|
||||
[Serializable()]
|
||||
public class PixelizationFilter : AbstractFilter
|
||||
{
|
||||
public PixelizationFilter(DrawableContainer parent) : base(parent)
|
||||
{
|
||||
AddField(GetType(), FieldType.PIXEL_SIZE, 7);
|
||||
}
|
||||
|
||||
public override void Apply(Graphics graphics, Bitmap applyBitmap, Rectangle rect, RenderMode renderMode)
|
||||
{
|
||||
int pixelSize = GetFieldValueAsInt(FieldType.PIXEL_SIZE);
|
||||
ImageHelper.CreateIntersectRectangle(applyBitmap.Size, rect, Invert);
|
||||
if (pixelSize <= 1 || rect.Width == 0 || rect.Height == 0)
|
||||
{
|
||||
// Nothing to do
|
||||
return;
|
||||
}
|
||||
if (rect.Width < pixelSize)
|
||||
{
|
||||
pixelSize = rect.Width;
|
||||
}
|
||||
if (rect.Height < pixelSize)
|
||||
{
|
||||
pixelSize = rect.Height;
|
||||
}
|
||||
using (IFastBitmap dest = FastBitmap.CreateCloneOf(applyBitmap, rect))
|
||||
{
|
||||
using (IFastBitmap src = FastBitmap.Create(applyBitmap, rect))
|
||||
{
|
||||
List<Color> colors = new List<Color>();
|
||||
int halbPixelSize = pixelSize / 2;
|
||||
for (int y = src.Top - halbPixelSize; y < src.Bottom + halbPixelSize; y = y + pixelSize)
|
||||
{
|
||||
for (int x = src.Left - halbPixelSize; x <= src.Right + halbPixelSize; x = x + pixelSize)
|
||||
{
|
||||
colors.Clear();
|
||||
for (int yy = y; yy < y + pixelSize; yy++)
|
||||
{
|
||||
if (yy >= src.Top && yy < src.Bottom)
|
||||
{
|
||||
for (int xx = x; xx < x + pixelSize; xx++)
|
||||
{
|
||||
if (xx >= src.Left && xx < src.Right)
|
||||
{
|
||||
colors.Add(src.GetColorAt(xx, yy));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Color currentAvgColor = Colors.Mix(colors);
|
||||
for (int yy = y; yy <= y + pixelSize; yy++)
|
||||
{
|
||||
if (yy >= src.Top && yy < src.Bottom)
|
||||
{
|
||||
for (int xx = x; xx <= x + pixelSize; xx++)
|
||||
{
|
||||
if (xx >= src.Left && xx < src.Right)
|
||||
{
|
||||
dest.SetColorAt(xx, yy, currentAvgColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dest.DrawTo(graphics, rect.Location);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,324 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Drawing.Fields;
|
||||
using Greenshot.Helpers;
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of PathContainer.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class FreehandContainer : DrawableContainer
|
||||
{
|
||||
private static readonly float[] POINT_OFFSET = new float[] { 0.5f, 0.25f, 0.75f };
|
||||
|
||||
[NonSerialized]
|
||||
private GraphicsPath freehandPath = new GraphicsPath();
|
||||
private Rectangle myBounds = Rectangle.Empty;
|
||||
private Point lastMouse = Point.Empty;
|
||||
private readonly List<Point> capturePoints = new List<Point>();
|
||||
private bool isRecalculated;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
public FreehandContainer(Surface parent) : base(parent)
|
||||
{
|
||||
Init();
|
||||
Width = parent.Width;
|
||||
Height = parent.Height;
|
||||
Top = 0;
|
||||
Left = 0;
|
||||
}
|
||||
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 3);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
|
||||
}
|
||||
|
||||
protected void Init()
|
||||
{
|
||||
if (_grippers != null)
|
||||
{
|
||||
for (int i = 0; i < _grippers.Length; i++)
|
||||
{
|
||||
_grippers[i].Enabled = false;
|
||||
_grippers[i].Visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Transform(Matrix matrix)
|
||||
{
|
||||
Point[] points = capturePoints.ToArray();
|
||||
|
||||
matrix.TransformPoints(points);
|
||||
capturePoints.Clear();
|
||||
capturePoints.AddRange(points);
|
||||
RecalculatePath();
|
||||
}
|
||||
|
||||
[OnDeserialized]
|
||||
private void OnDeserialized(StreamingContext context)
|
||||
{
|
||||
InitGrippers();
|
||||
DoLayout();
|
||||
Init();
|
||||
RecalculatePath();
|
||||
}
|
||||
|
||||
/// <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)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (disposing)
|
||||
{
|
||||
if (freehandPath != null)
|
||||
{
|
||||
freehandPath.Dispose();
|
||||
}
|
||||
}
|
||||
freehandPath = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called from Surface (the parent) when the drawing begins (mouse-down)
|
||||
/// </summary>
|
||||
/// <returns>true if the surface doesn't need to handle the event</returns>
|
||||
public override bool HandleMouseDown(int mouseX, int mouseY)
|
||||
{
|
||||
lastMouse = new Point(mouseX, mouseY);
|
||||
capturePoints.Add(lastMouse);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called from Surface (the parent) if a mouse move is made while drawing
|
||||
/// </summary>
|
||||
/// <returns>true if the surface doesn't need to handle the event</returns>
|
||||
public override bool HandleMouseMove(int mouseX, int mouseY)
|
||||
{
|
||||
Point previousPoint = capturePoints[capturePoints.Count - 1];
|
||||
|
||||
if (GeometryHelper.Distance2D(previousPoint.X, previousPoint.Y, mouseX, mouseY) >= 2 * EditorConfig.FreehandSensitivity)
|
||||
{
|
||||
capturePoints.Add(new Point(mouseX, mouseY));
|
||||
}
|
||||
if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) >= EditorConfig.FreehandSensitivity)
|
||||
{
|
||||
//path.AddCurve(new Point[]{lastMouse, new Point(mouseX, mouseY)});
|
||||
freehandPath.AddLine(lastMouse, new Point(mouseX, mouseY));
|
||||
lastMouse = new Point(mouseX, mouseY);
|
||||
// Only re-calculate the bounds & redraw when we added something to the path
|
||||
myBounds = Rectangle.Round(freehandPath.GetBounds());
|
||||
Invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the surface finishes drawing the element
|
||||
/// </summary>
|
||||
public override void HandleMouseUp(int mouseX, int mouseY)
|
||||
{
|
||||
// Make sure we don't loose the ending point
|
||||
if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) >= EditorConfig.FreehandSensitivity)
|
||||
{
|
||||
capturePoints.Add(new Point(mouseX, mouseY));
|
||||
}
|
||||
RecalculatePath();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Here we recalculate the freehand path by smoothing out the lines with Beziers.
|
||||
/// </summary>
|
||||
private void RecalculatePath()
|
||||
{
|
||||
isRecalculated = true;
|
||||
// Dispose the previous path, if we have one
|
||||
if (freehandPath != null)
|
||||
{
|
||||
freehandPath.Dispose();
|
||||
}
|
||||
freehandPath = new GraphicsPath();
|
||||
|
||||
// Here we can put some cleanup... like losing all the uninteresting points.
|
||||
if (capturePoints.Count >= 3)
|
||||
{
|
||||
int index = 0;
|
||||
while ((capturePoints.Count - 1) % 3 != 0)
|
||||
{
|
||||
// duplicate points, first at 50% than 25% than 75%
|
||||
capturePoints.Insert((int)(capturePoints.Count * POINT_OFFSET[index]), capturePoints[(int)(capturePoints.Count * POINT_OFFSET[index++])]);
|
||||
}
|
||||
freehandPath.AddBeziers(capturePoints.ToArray());
|
||||
}
|
||||
else if (capturePoints.Count == 2)
|
||||
{
|
||||
freehandPath.AddLine(capturePoints[0], capturePoints[1]);
|
||||
}
|
||||
|
||||
// Recalculate the bounds
|
||||
myBounds = Rectangle.Round(freehandPath.GetBounds());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Do the drawing of the freehand "stroke"
|
||||
/// </summary>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="renderMode"></param>
|
||||
public override void Draw(Graphics graphics, RenderMode renderMode)
|
||||
{
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
using (Pen pen = new Pen(lineColor))
|
||||
{
|
||||
pen.Width = lineThickness;
|
||||
if (pen.Width > 0)
|
||||
{
|
||||
// Make sure the lines are nicely rounded
|
||||
pen.EndCap = LineCap.Round;
|
||||
pen.StartCap = LineCap.Round;
|
||||
pen.LineJoin = LineJoin.Round;
|
||||
|
||||
// Move to where we need to draw
|
||||
graphics.TranslateTransform(Left, Top);
|
||||
if (isRecalculated && Selected && renderMode == RenderMode.EDIT)
|
||||
{
|
||||
DrawSelectionBorder(graphics, pen);
|
||||
}
|
||||
graphics.DrawPath(pen, freehandPath);
|
||||
// Move back, otherwise everything is shifted
|
||||
graphics.TranslateTransform(-Left, -Top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw a selectionborder around the freehand path
|
||||
/// </summary>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="linePen"></param>
|
||||
protected void DrawSelectionBorder(Graphics graphics, Pen linePen)
|
||||
{
|
||||
using (Pen selectionPen = (Pen)linePen.Clone())
|
||||
{
|
||||
using (GraphicsPath selectionPath = (GraphicsPath)freehandPath.Clone())
|
||||
{
|
||||
selectionPen.Width += 5;
|
||||
selectionPen.Color = Color.FromArgb(120, Color.LightSeaGreen);
|
||||
graphics.DrawPath(selectionPen, selectionPath);
|
||||
selectionPath.Widen(selectionPen);
|
||||
selectionPen.DashPattern = new float[] { 2, 2 };
|
||||
selectionPen.Color = Color.LightSeaGreen;
|
||||
selectionPen.Width = 1;
|
||||
graphics.DrawPath(selectionPen, selectionPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the bounds in which we have something drawn, plus safety margin, these are not the normal bounds...
|
||||
/// </summary>
|
||||
public override Rectangle DrawingBounds
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!myBounds.IsEmpty)
|
||||
{
|
||||
int lineThickness = Math.Max(10, GetFieldValueAsInt(FieldType.LINE_THICKNESS));
|
||||
int safetymargin = 10;
|
||||
return new Rectangle(myBounds.Left + Left - (safetymargin + lineThickness), myBounds.Top + Top - (safetymargin + lineThickness), myBounds.Width + 2 * (lineThickness + safetymargin), myBounds.Height + 2 * (lineThickness + safetymargin));
|
||||
}
|
||||
return new Rectangle(0, 0, _parent.Width, _parent.Height);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FreehandContainer are regarded equal if they are of the same type and their paths are equal.
|
||||
/// </summary>
|
||||
/// <param name="obj"></param>
|
||||
/// <returns></returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
bool ret = false;
|
||||
if (obj != null && GetType().Equals(obj.GetType()))
|
||||
{
|
||||
FreehandContainer other = obj as FreehandContainer;
|
||||
if (freehandPath.Equals(other.freehandPath))
|
||||
{
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return freehandPath.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is overriden to prevent the grippers to be modified.
|
||||
/// Might not be the best way...
|
||||
/// </summary>
|
||||
protected override void DoLayout()
|
||||
{
|
||||
}
|
||||
|
||||
public override void ShowGrippers()
|
||||
{
|
||||
ResumeLayout();
|
||||
}
|
||||
|
||||
public override bool ClickableAt(int x, int y)
|
||||
{
|
||||
bool returnValue = base.ClickableAt(x, y);
|
||||
if (returnValue)
|
||||
{
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
using (Pen pen = new Pen(Color.White))
|
||||
{
|
||||
pen.Width = lineThickness + 10;
|
||||
returnValue = freehandPath.IsOutlineVisible(x - Left, y - Top, pen);
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Grippers are the dragable edges of our containers
|
||||
/// </summary>
|
||||
public class Gripper : Label
|
||||
{
|
||||
/// <summary>
|
||||
/// Constants for anchor/gripper position:
|
||||
/// 0 1 2
|
||||
/// 7 3
|
||||
/// 6 5 4
|
||||
/// </summary>
|
||||
public const int POSITION_TOP_LEFT = 0;
|
||||
public const int POSITION_TOP_CENTER = 1;
|
||||
public const int POSITION_TOP_RIGHT = 2;
|
||||
public const int POSITION_MIDDLE_RIGHT = 3;
|
||||
public const int POSITION_BOTTOM_RIGHT = 4;
|
||||
public const int POSITION_BOTTOM_CENTER = 5;
|
||||
public const int POSITION_BOTTOM_LEFT = 6;
|
||||
public const int POSITION_MIDDLE_LEFT = 7;
|
||||
|
||||
public const int GripperSize = 7;
|
||||
|
||||
public int Position
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Gripper()
|
||||
{
|
||||
Width = GripperSize;
|
||||
Height = GripperSize;
|
||||
BackColor = Color.White;
|
||||
BorderStyle = BorderStyle.FixedSingle;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Drawing.Fields;
|
||||
using Greenshot.Drawing.Filters;
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of ObfuscateContainer.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class HighlightContainer : FilterContainer
|
||||
{
|
||||
public HighlightContainer(Surface parent) : base(parent)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use settings from base, extend with our own field
|
||||
/// </summary>
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
base.InitializeFields();
|
||||
AddField(GetType(), FieldType.PREPARED_FILTER_HIGHLIGHT, PreparedFilter.TEXT_HIGHTLIGHT);
|
||||
}
|
||||
|
||||
[OnDeserialized]
|
||||
private void OnDeserialized(StreamingContext context)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
FieldChanged += HighlightContainer_OnFieldChanged;
|
||||
ConfigurePreparedFilters();
|
||||
}
|
||||
|
||||
protected void HighlightContainer_OnFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
if (!sender.Equals(this))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (e.Field.FieldType == FieldType.PREPARED_FILTER_HIGHLIGHT)
|
||||
{
|
||||
ConfigurePreparedFilters();
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigurePreparedFilters()
|
||||
{
|
||||
PreparedFilter preset = (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT);
|
||||
while (Filters.Count > 0)
|
||||
{
|
||||
Remove(Filters[0]);
|
||||
}
|
||||
switch (preset)
|
||||
{
|
||||
case PreparedFilter.TEXT_HIGHTLIGHT:
|
||||
Add(new HighlightFilter(this));
|
||||
break;
|
||||
case PreparedFilter.AREA_HIGHLIGHT:
|
||||
AbstractFilter bf = new BrightnessFilter(this);
|
||||
bf.Invert = true;
|
||||
Add(bf);
|
||||
bf = new BlurFilter(this);
|
||||
bf.Invert = true;
|
||||
Add(bf);
|
||||
break;
|
||||
case PreparedFilter.GRAYSCALE:
|
||||
AbstractFilter f = new GrayscaleFilter(this);
|
||||
f.Invert = true;
|
||||
Add(f);
|
||||
break;
|
||||
case PreparedFilter.MAGNIFICATION:
|
||||
Add(new MagnifierFilter(this));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using GreenshotPlugin;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.IO;
|
||||
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of IconContainer.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class IconContainer : DrawableContainer, IIconContainer
|
||||
{
|
||||
protected Icon icon;
|
||||
|
||||
public IconContainer(Surface parent) : base(parent)
|
||||
{
|
||||
}
|
||||
|
||||
public IconContainer(Surface parent, string filename) : base(parent)
|
||||
{
|
||||
Load(filename);
|
||||
}
|
||||
|
||||
public Icon Icon
|
||||
{
|
||||
set
|
||||
{
|
||||
if (icon != null)
|
||||
{
|
||||
icon.Dispose();
|
||||
}
|
||||
icon = (Icon)value.Clone();
|
||||
Width = value.Width;
|
||||
Height = value.Height;
|
||||
}
|
||||
get
|
||||
{
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This Dispose is called from the Dispose and the Destructor.
|
||||
* When disposing==true all non-managed resources should be freed too!
|
||||
*/
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (icon != null)
|
||||
{
|
||||
icon.Dispose();
|
||||
}
|
||||
}
|
||||
icon = null;
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
public void Load(string filename)
|
||||
{
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
using (Icon fileIcon = new Icon(filename))
|
||||
{
|
||||
Icon = fileIcon;
|
||||
LOG.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(Graphics graphics, RenderMode rm)
|
||||
{
|
||||
if (icon != null)
|
||||
{
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
graphics.CompositingQuality = CompositingQuality.Default;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
graphics.DrawIcon(icon, Bounds);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HasDefaultSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override Size DefaultSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return icon.Size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,267 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Core;
|
||||
using Greenshot.Drawing.Fields;
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using GreenshotPlugin;
|
||||
using GreenshotPlugin.Core;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.IO;
|
||||
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of BitmapContainer.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ImageContainer : DrawableContainer, IImageContainer
|
||||
{
|
||||
private Image image;
|
||||
|
||||
/// <summary>
|
||||
/// This is the shadow version of the bitmap, rendered once to save performance
|
||||
/// Do not serialize, as the shadow is recreated from the original bitmap if it's not available
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
private Image _shadowBitmap;
|
||||
|
||||
/// <summary>
|
||||
/// This is the offset for the shadow version of the bitmap
|
||||
/// Do not serialize, as the offset is recreated
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
private Point _shadowOffset = new Point(-1, -1);
|
||||
|
||||
public ImageContainer(Surface parent, string filename) : this(parent)
|
||||
{
|
||||
Load(filename);
|
||||
}
|
||||
|
||||
public ImageContainer(Surface parent) : base(parent)
|
||||
{
|
||||
FieldChanged += BitmapContainer_OnFieldChanged;
|
||||
}
|
||||
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
AddField(GetType(), FieldType.SHADOW, false);
|
||||
}
|
||||
|
||||
protected void BitmapContainer_OnFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
if (sender.Equals(this))
|
||||
{
|
||||
if (e.Field.FieldType == FieldType.SHADOW)
|
||||
{
|
||||
ChangeShadowField();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeShadowField()
|
||||
{
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
if (shadow)
|
||||
{
|
||||
CheckShadow(true);
|
||||
Width = _shadowBitmap.Width;
|
||||
Height = _shadowBitmap.Height;
|
||||
Left = Left - _shadowOffset.X;
|
||||
Top = Top - _shadowOffset.Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
Width = image.Width;
|
||||
Height = image.Height;
|
||||
if (_shadowBitmap != null)
|
||||
{
|
||||
Left = Left + _shadowOffset.X;
|
||||
Top = Top + _shadowOffset.Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Image Image
|
||||
{
|
||||
set
|
||||
{
|
||||
// Remove all current bitmaps
|
||||
DisposeImage();
|
||||
DisposeShadow();
|
||||
image = ImageHelper.Clone(value);
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
CheckShadow(shadow);
|
||||
if (!shadow)
|
||||
{
|
||||
Width = image.Width;
|
||||
Height = image.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
Width = _shadowBitmap.Width;
|
||||
Height = _shadowBitmap.Height;
|
||||
Left = Left - _shadowOffset.X;
|
||||
Top = Top - _shadowOffset.Y;
|
||||
}
|
||||
}
|
||||
get
|
||||
{
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The bulk of the clean-up code is implemented in Dispose(bool)
|
||||
/// 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)
|
||||
{
|
||||
DisposeImage();
|
||||
DisposeShadow();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void DisposeImage()
|
||||
{
|
||||
if (image != null)
|
||||
{
|
||||
image.Dispose();
|
||||
}
|
||||
image = null;
|
||||
}
|
||||
|
||||
private void DisposeShadow()
|
||||
{
|
||||
if (_shadowBitmap != null)
|
||||
{
|
||||
_shadowBitmap.Dispose();
|
||||
}
|
||||
_shadowBitmap = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the content is also transformed.
|
||||
/// </summary>
|
||||
/// <param name="matrix"></param>
|
||||
public override void Transform(Matrix matrix)
|
||||
{
|
||||
int rotateAngle = CalculateAngle(matrix);
|
||||
// we currently assume only one transformation has been made.
|
||||
if (rotateAngle != 0)
|
||||
{
|
||||
LOG.DebugFormat("Rotating element with {0} degrees.", rotateAngle);
|
||||
DisposeShadow();
|
||||
using (var tmpMatrix = new Matrix())
|
||||
{
|
||||
using (Image tmpImage = image)
|
||||
{
|
||||
image = ImageHelper.ApplyEffect(image, new RotateEffect(rotateAngle), tmpMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
base.Transform(matrix);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
public void Load(string filename)
|
||||
{
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
// Always make sure ImageHelper.LoadBitmap results are disposed some time,
|
||||
// as we close the bitmap internally, we need to do it afterwards
|
||||
using (Image tmpImage = ImageHelper.LoadImage(filename))
|
||||
{
|
||||
Image = tmpImage;
|
||||
}
|
||||
LOG.Debug("Loaded file: " + filename + " with resolution: " + Height + "," + Width);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This checks if a shadow is already generated
|
||||
/// </summary>
|
||||
/// <param name="shadow"></param>
|
||||
private void CheckShadow(bool shadow)
|
||||
{
|
||||
if (shadow && _shadowBitmap == null)
|
||||
{
|
||||
using (var matrix = new Matrix())
|
||||
{
|
||||
_shadowBitmap = ImageHelper.ApplyEffect(image, new DropShadowEffect(), matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw the actual container to the graphics object
|
||||
/// </summary>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="rm"></param>
|
||||
public override void Draw(Graphics graphics, RenderMode rm)
|
||||
{
|
||||
if (image != null)
|
||||
{
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
|
||||
if (shadow)
|
||||
{
|
||||
CheckShadow(true);
|
||||
graphics.DrawImage(_shadowBitmap, Bounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics.DrawImage(image, Bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HasDefaultSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override Size DefaultSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return image.Size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of LineContainer.
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
public class LineContainer : DrawableContainer
|
||||
{
|
||||
public static readonly int MAX_CLICK_DISTANCE_TOLERANCE = 10;
|
||||
|
||||
public LineContainer(Surface parent) : base(parent)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
|
||||
AddField(GetType(), FieldType.SHADOW, true);
|
||||
}
|
||||
|
||||
[OnDeserialized()]
|
||||
private void OnDeserialized(StreamingContext context)
|
||||
{
|
||||
InitGrippers();
|
||||
DoLayout();
|
||||
Init();
|
||||
}
|
||||
|
||||
protected void Init()
|
||||
{
|
||||
if (_grippers != null)
|
||||
{
|
||||
foreach (int index in new[] { 1, 2, 3, 5, 6, 7 })
|
||||
{
|
||||
_grippers[index].Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Draw(Graphics graphics, RenderMode rm)
|
||||
{
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBilinear;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
|
||||
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))
|
||||
{
|
||||
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))
|
||||
{
|
||||
graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ClickableAt(int x, int y)
|
||||
{
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS) + 5;
|
||||
if (lineThickness > 0)
|
||||
{
|
||||
using (Pen pen = new Pen(Color.White))
|
||||
{
|
||||
pen.Width = lineThickness;
|
||||
using (GraphicsPath path = new GraphicsPath())
|
||||
{
|
||||
path.AddLine(Left, Top, Left + Width, Top + Height);
|
||||
return path.IsOutlineVisible(x, y, pen);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override ScaleHelper.IDoubleProcessor GetAngleRoundProcessor()
|
||||
{
|
||||
return ScaleHelper.LineAngleRoundBehavior.Instance;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Drawing.Fields;
|
||||
using Greenshot.Drawing.Filters;
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of ObfuscateContainer.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class ObfuscateContainer : FilterContainer
|
||||
{
|
||||
public ObfuscateContainer(Surface parent) : base(parent)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
base.InitializeFields();
|
||||
AddField(GetType(), FieldType.PREPARED_FILTER_OBFUSCATE, PreparedFilter.PIXELIZE);
|
||||
}
|
||||
|
||||
[OnDeserialized]
|
||||
private void OnDeserialized(StreamingContext context)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
FieldChanged += ObfuscateContainer_OnFieldChanged;
|
||||
ConfigurePreparedFilters();
|
||||
}
|
||||
|
||||
protected void ObfuscateContainer_OnFieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
if (sender.Equals(this))
|
||||
{
|
||||
if (e.Field.FieldType == FieldType.PREPARED_FILTER_OBFUSCATE)
|
||||
{
|
||||
ConfigurePreparedFilters();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigurePreparedFilters()
|
||||
{
|
||||
PreparedFilter preset = (PreparedFilter)GetFieldValue(FieldType.PREPARED_FILTER_OBFUSCATE);
|
||||
while (Filters.Count > 0)
|
||||
{
|
||||
Remove(Filters[0]);
|
||||
}
|
||||
switch (preset)
|
||||
{
|
||||
case PreparedFilter.BLUR:
|
||||
Add(new BlurFilter(this));
|
||||
break;
|
||||
case PreparedFilter.PIXELIZE:
|
||||
Add(new PixelizationFilter(this));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <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>
|
||||
/// Represents a rectangular shape on the Surface
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class RectangleContainer : DrawableContainer
|
||||
{
|
||||
public RectangleContainer(Surface parent) : base(parent)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
|
||||
AddField(GetType(), FieldType.FILL_COLOR, Color.Transparent);
|
||||
AddField(GetType(), FieldType.SHADOW, true);
|
||||
}
|
||||
|
||||
public override void Draw(Graphics graphics, RenderMode rm)
|
||||
{
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
|
||||
DrawRectangle(rect, graphics, rm, lineThickness, lineColor, fillColor, shadow);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method can also be used from other containers, if the right values are passed!
|
||||
/// </summary>
|
||||
/// <param name="rect"></param>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="rm"></param>
|
||||
/// <param name="lineThickness"></param>
|
||||
/// <param name="lineColor"></param>
|
||||
/// <param name="fillColor"></param>
|
||||
/// <param name="shadow"></param>
|
||||
public static void DrawRectangle(Rectangle rect, Graphics graphics, RenderMode rm, int lineThickness, Color lineColor, Color fillColor, bool shadow)
|
||||
{
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||
|
||||
bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor);
|
||||
if (shadow && (lineVisible || Colors.IsVisible(fillColor)))
|
||||
{
|
||||
//draw shadow first
|
||||
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(
|
||||
rect.Left + currentStep,
|
||||
rect.Top + currentStep,
|
||||
rect.Width,
|
||||
rect.Height);
|
||||
graphics.DrawRectangle(shadowPen, shadowRect);
|
||||
currentStep++;
|
||||
alpha = alpha - basealpha / steps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Colors.IsVisible(fillColor))
|
||||
{
|
||||
using (Brush brush = new SolidBrush(fillColor))
|
||||
{
|
||||
graphics.FillRectangle(brush, rect);
|
||||
}
|
||||
}
|
||||
|
||||
graphics.SmoothingMode = SmoothingMode.HighSpeed;
|
||||
if (lineVisible)
|
||||
{
|
||||
using (Pen pen = new Pen(lineColor, lineThickness))
|
||||
{
|
||||
graphics.DrawRectangle(pen, rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return RectangleClickableAt(rect, lineThickness, fillColor, x, y);
|
||||
}
|
||||
|
||||
public static bool RectangleClickableAt(Rectangle rect, int lineThickness, Color fillColor, int x, int y)
|
||||
{
|
||||
// If we clicked inside the rectangle and it's visible we are clickable at.
|
||||
if (!Color.Transparent.Equals(fillColor))
|
||||
{
|
||||
if (rect.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.AddRectangle(rect);
|
||||
return path.IsOutlineVisible(x, y, pen);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,388 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This 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;
|
||||
using System.Drawing.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Description of SpeechbubbleContainer.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class SpeechbubbleContainer : TextContainer
|
||||
{
|
||||
private Point _initialGripperPoint;
|
||||
|
||||
#region TargetGripper serializing code
|
||||
|
||||
// Only used for serializing the TargetGripper location
|
||||
private Point _storedTargetGripperLocation;
|
||||
|
||||
/// <summary>
|
||||
/// Store the current location of the target gripper
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
[OnSerializing]
|
||||
private void SetValuesOnSerializing(StreamingContext context)
|
||||
{
|
||||
if (TargetGripper != null)
|
||||
{
|
||||
_storedTargetGripperLocation = TargetGripper.Location;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restore the target gripper
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
[OnDeserialized]
|
||||
private void SetValuesOnDeserialized(StreamingContext context)
|
||||
{
|
||||
InitTargetGripper(Color.Yellow, _storedTargetGripperLocation);
|
||||
}
|
||||
|
||||
#endregion TargetGripper serializing code
|
||||
|
||||
public SpeechbubbleContainer(Surface parent)
|
||||
: base(parent)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We set our own field values
|
||||
/// </summary>
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
|
||||
AddField(GetType(), FieldType.SHADOW, false);
|
||||
AddField(GetType(), FieldType.FONT_ITALIC, false);
|
||||
AddField(GetType(), FieldType.FONT_BOLD, false);
|
||||
AddField(GetType(), FieldType.FILL_COLOR, Color.White);
|
||||
AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name);
|
||||
AddField(GetType(), FieldType.FONT_SIZE, 20f);
|
||||
AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, StringAlignment.Center);
|
||||
AddField(GetType(), FieldType.TEXT_VERTICAL_ALIGNMENT, StringAlignment.Center);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called from Surface (the _parent) when the drawing begins (mouse-down)
|
||||
/// </summary>
|
||||
/// <returns>true if the surface doesn't need to handle the event</returns>
|
||||
public override bool HandleMouseDown(int mouseX, int mouseY)
|
||||
{
|
||||
if (TargetGripper == null)
|
||||
{
|
||||
_initialGripperPoint = new Point(mouseX, mouseY);
|
||||
InitTargetGripper(Color.Yellow, new Point(mouseX, mouseY));
|
||||
}
|
||||
return base.HandleMouseDown(mouseX, mouseY);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overriding the HandleMouseMove will help us to make sure the tail is always visible.
|
||||
/// Should fix BUG-1682
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns>base.HandleMouseMove</returns>
|
||||
public override bool HandleMouseMove(int x, int y)
|
||||
{
|
||||
bool returnValue = base.HandleMouseMove(x, y);
|
||||
|
||||
bool leftAligned = _boundsAfterResize.Right - _boundsAfterResize.Left >= 0;
|
||||
bool topAligned = _boundsAfterResize.Bottom - _boundsAfterResize.Top >= 0;
|
||||
|
||||
int xOffset = leftAligned ? -20 : 20;
|
||||
int yOffset = topAligned ? -20 : 20;
|
||||
|
||||
Point newGripperLocation = _initialGripperPoint;
|
||||
newGripperLocation.Offset(xOffset, yOffset);
|
||||
|
||||
if (TargetGripper.Location != newGripperLocation)
|
||||
{
|
||||
Invalidate();
|
||||
TargetGripperMove(newGripperLocation.X, newGripperLocation.Y);
|
||||
Invalidate();
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The DrawingBound should be so close as possible to the shape, so we don't invalidate to much.
|
||||
/// </summary>
|
||||
public override Rectangle DrawingBounds
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Status != EditStatus.UNDRAWN)
|
||||
{
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
using (Pen pen = new Pen(lineColor, lineThickness))
|
||||
{
|
||||
int inflateValue = lineThickness + 2 + (shadow ? 6 : 0);
|
||||
using (GraphicsPath tailPath = CreateTail())
|
||||
{
|
||||
return Rectangle.Inflate(Rectangle.Union(Rectangle.Round(tailPath.GetBounds(new Matrix(), pen)), GuiRectangle.GetGuiRectangle(Left, Top, Width, Height)), inflateValue, inflateValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Rectangle.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create the bubble GraphicsPath, so we can also calculate the bounds
|
||||
/// </summary>
|
||||
/// <param name="lineThickness"></param>
|
||||
/// <returns></returns>
|
||||
private GraphicsPath CreateBubble(int lineThickness)
|
||||
{
|
||||
GraphicsPath bubble = new GraphicsPath();
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
|
||||
Rectangle bubbleRect = GuiRectangle.GetGuiRectangle(0, 0, rect.Width, rect.Height);
|
||||
// adapt corner radius to small rectangle dimensions
|
||||
int smallerSideLength = Math.Min(bubbleRect.Width, bubbleRect.Height);
|
||||
int cornerRadius = Math.Min(30, smallerSideLength / 2 - lineThickness);
|
||||
if (cornerRadius > 0)
|
||||
{
|
||||
bubble.AddArc(bubbleRect.X, bubbleRect.Y, cornerRadius, cornerRadius, 180, 90);
|
||||
bubble.AddArc(bubbleRect.X + bubbleRect.Width - cornerRadius, bubbleRect.Y, cornerRadius, cornerRadius, 270, 90);
|
||||
bubble.AddArc(bubbleRect.X + bubbleRect.Width - cornerRadius, bubbleRect.Y + bubbleRect.Height - cornerRadius, cornerRadius, cornerRadius, 0, 90);
|
||||
bubble.AddArc(bubbleRect.X, bubbleRect.Y + bubbleRect.Height - cornerRadius, cornerRadius, cornerRadius, 90, 90);
|
||||
}
|
||||
else
|
||||
{
|
||||
bubble.AddRectangle(bubbleRect);
|
||||
}
|
||||
bubble.CloseAllFigures();
|
||||
using (Matrix bubbleMatrix = new Matrix())
|
||||
{
|
||||
bubbleMatrix.Translate(rect.Left, rect.Top);
|
||||
bubble.Transform(bubbleMatrix);
|
||||
}
|
||||
return bubble;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to create the tail of the bubble, so we can also calculate the bounds
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private GraphicsPath CreateTail()
|
||||
{
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
|
||||
int tailLength = GeometryHelper.Distance2D(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2, TargetGripper.Left, TargetGripper.Top);
|
||||
int tailWidth = (Math.Abs(rect.Width) + Math.Abs(rect.Height)) / 20;
|
||||
|
||||
// This should fix a problem with the tail being to wide
|
||||
tailWidth = Math.Min(Math.Abs(rect.Width) / 2, tailWidth);
|
||||
tailWidth = Math.Min(Math.Abs(rect.Height) / 2, tailWidth);
|
||||
|
||||
GraphicsPath tail = new GraphicsPath();
|
||||
tail.AddLine(-tailWidth, 0, tailWidth, 0);
|
||||
tail.AddLine(tailWidth, 0, 0, -tailLength);
|
||||
tail.CloseFigure();
|
||||
|
||||
int tailAngle = 90 + (int)GeometryHelper.Angle2D(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2, TargetGripper.Left, TargetGripper.Top);
|
||||
|
||||
using (Matrix tailMatrix = new Matrix())
|
||||
{
|
||||
tailMatrix.Translate(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
|
||||
tailMatrix.Rotate(tailAngle);
|
||||
tail.Transform(tailMatrix);
|
||||
}
|
||||
|
||||
return tail;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is to draw the actual container
|
||||
/// </summary>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="renderMode"></param>
|
||||
public override void Draw(Graphics graphics, RenderMode renderMode)
|
||||
{
|
||||
if (TargetGripper == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
|
||||
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
|
||||
bool lineVisible = lineThickness > 0 && Colors.IsVisible(lineColor);
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
|
||||
if (Selected && renderMode == RenderMode.EDIT)
|
||||
{
|
||||
DrawSelectionBorder(graphics, rect);
|
||||
}
|
||||
|
||||
GraphicsPath bubble = CreateBubble(lineThickness);
|
||||
|
||||
GraphicsPath tail = CreateTail();
|
||||
|
||||
//draw shadow first
|
||||
if (shadow && (lineVisible || Colors.IsVisible(fillColor)))
|
||||
{
|
||||
const int basealpha = 100;
|
||||
int alpha = basealpha;
|
||||
const int steps = 5;
|
||||
int currentStep = lineVisible ? 1 : 0;
|
||||
using (Matrix shadowMatrix = new Matrix())
|
||||
using (GraphicsPath bubbleClone = (GraphicsPath)bubble.Clone())
|
||||
using (GraphicsPath tailClone = (GraphicsPath)tail.Clone())
|
||||
{
|
||||
shadowMatrix.Translate(1, 1);
|
||||
while (currentStep <= steps)
|
||||
{
|
||||
using (Pen shadowPen = new Pen(Color.FromArgb(alpha, 100, 100, 100)))
|
||||
{
|
||||
shadowPen.Width = lineVisible ? lineThickness : 1;
|
||||
tailClone.Transform(shadowMatrix);
|
||||
graphics.DrawPath(shadowPen, tailClone);
|
||||
bubbleClone.Transform(shadowMatrix);
|
||||
graphics.DrawPath(shadowPen, bubbleClone);
|
||||
}
|
||||
currentStep++;
|
||||
alpha = alpha - basealpha / steps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GraphicsState state = graphics.Save();
|
||||
// draw the tail border where the bubble is not visible
|
||||
using (Region clipRegion = new Region(bubble))
|
||||
{
|
||||
graphics.SetClip(clipRegion, CombineMode.Exclude);
|
||||
using (Pen pen = new Pen(lineColor, lineThickness))
|
||||
{
|
||||
graphics.DrawPath(pen, tail);
|
||||
}
|
||||
}
|
||||
graphics.Restore(state);
|
||||
|
||||
if (Colors.IsVisible(fillColor))
|
||||
{
|
||||
//draw the bubbleshape
|
||||
state = graphics.Save();
|
||||
using (Brush brush = new SolidBrush(fillColor))
|
||||
{
|
||||
graphics.FillPath(brush, bubble);
|
||||
}
|
||||
graphics.Restore(state);
|
||||
}
|
||||
|
||||
if (lineVisible)
|
||||
{
|
||||
//draw the bubble border
|
||||
state = graphics.Save();
|
||||
// Draw bubble where the Tail is not visible.
|
||||
using (Region clipRegion = new Region(tail))
|
||||
{
|
||||
graphics.SetClip(clipRegion, CombineMode.Exclude);
|
||||
using (Pen pen = new Pen(lineColor, lineThickness))
|
||||
{
|
||||
//pen.EndCap = pen.StartCap = LineCap.Round;
|
||||
graphics.DrawPath(pen, bubble);
|
||||
}
|
||||
}
|
||||
graphics.Restore(state);
|
||||
}
|
||||
|
||||
if (Colors.IsVisible(fillColor))
|
||||
{
|
||||
// Draw the tail border
|
||||
state = graphics.Save();
|
||||
using (Brush brush = new SolidBrush(fillColor))
|
||||
{
|
||||
graphics.FillPath(brush, tail);
|
||||
}
|
||||
graphics.Restore(state);
|
||||
}
|
||||
|
||||
// cleanup the paths
|
||||
bubble.Dispose();
|
||||
tail.Dispose();
|
||||
|
||||
// Draw the text
|
||||
DrawText(graphics, rect, lineThickness, lineColor, shadow, StringFormat, Text, Font);
|
||||
}
|
||||
|
||||
public override bool Contains(int x, int y)
|
||||
{
|
||||
if (base.Contains(x, y))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Point clickedPoint = new Point(x, y);
|
||||
if (Status != EditStatus.UNDRAWN)
|
||||
{
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
using (Pen pen = new Pen(lineColor, lineThickness))
|
||||
{
|
||||
using (GraphicsPath bubblePath = CreateBubble(lineThickness))
|
||||
{
|
||||
bubblePath.Widen(pen);
|
||||
if (bubblePath.IsVisible(clickedPoint))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
using (GraphicsPath tailPath = CreateTail())
|
||||
{
|
||||
tailPath.Widen(pen);
|
||||
if (tailPath.IsVisible(clickedPoint))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ClickableAt(int x, int y)
|
||||
{
|
||||
return Contains(x, y);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,246 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2012 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This 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;
|
||||
using System.Drawing.Text;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// This is an enumerated label, every single StepLabelContainer shows the number of the order it was created.
|
||||
/// To make sure that deleting recalculates, we check the location before every draw.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class StepLabelContainer : DrawableContainer
|
||||
{
|
||||
[NonSerialized]
|
||||
private StringFormat _stringFormat = new StringFormat();
|
||||
|
||||
private readonly bool _drawAsRectangle = false;
|
||||
|
||||
private float fontSize = 16;
|
||||
|
||||
public StepLabelContainer(Surface parent) : base(parent)
|
||||
{
|
||||
parent.AddStepLabel(this);
|
||||
InitContent();
|
||||
}
|
||||
|
||||
#region Number serializing
|
||||
|
||||
// Used to store the number of this label, so when deserializing it can be placed back to the StepLabels list in the right location
|
||||
private int _number;
|
||||
public int Number
|
||||
{
|
||||
get
|
||||
{
|
||||
return _number;
|
||||
}
|
||||
set
|
||||
{
|
||||
_number = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the counter before serializing
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
[OnSerializing]
|
||||
private void SetValuesOnSerializing(StreamingContext context)
|
||||
{
|
||||
if (Parent != null)
|
||||
{
|
||||
Number = ((Surface)Parent).CountStepLabels(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Number serializing
|
||||
|
||||
/// <summary>
|
||||
/// Restore values that don't serialize
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
[OnDeserialized]
|
||||
private void SetValuesOnDeserialized(StreamingContext context)
|
||||
{
|
||||
_stringFormat = new StringFormat();
|
||||
_stringFormat.Alignment = StringAlignment.Center;
|
||||
_stringFormat.LineAlignment = StringAlignment.Center;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add the StepLabel to the parent
|
||||
/// </summary>
|
||||
/// <param name="newParent"></param>
|
||||
protected override void SwitchParent(Surface newParent)
|
||||
{
|
||||
if (Parent != null)
|
||||
{
|
||||
((Surface)Parent).RemoveStepLabel(this);
|
||||
}
|
||||
base.SwitchParent(newParent);
|
||||
if (newParent != null)
|
||||
{
|
||||
((Surface)Parent).AddStepLabel(this);
|
||||
}
|
||||
}
|
||||
|
||||
public override Size DefaultSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return new Size(30, 30);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool InitContent()
|
||||
{
|
||||
_defaultEditMode = EditStatus.IDLE;
|
||||
_stringFormat.Alignment = StringAlignment.Center;
|
||||
_stringFormat.LineAlignment = StringAlignment.Center;
|
||||
|
||||
// Set defaults
|
||||
Width = DefaultSize.Width;
|
||||
Height = DefaultSize.Height;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This makes it possible for the label to be placed exactly in the middle of the pointer.
|
||||
/// </summary>
|
||||
public override bool HandleMouseDown(int mouseX, int mouseY)
|
||||
{
|
||||
return base.HandleMouseDown(mouseX - Width / 2, mouseY - Height / 2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We set our own field values
|
||||
/// </summary>
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
AddField(GetType(), FieldType.FILL_COLOR, DefaultLineColor);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, Color.White);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure this element is no longer referenced from the surface
|
||||
/// </summary>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (!disposing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
((Surface)Parent).RemoveStepLabel(this);
|
||||
if (_stringFormat != null)
|
||||
{
|
||||
_stringFormat.Dispose();
|
||||
_stringFormat = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HandleMouseMove(int x, int y)
|
||||
{
|
||||
Invalidate();
|
||||
Left = x - Width / 2;
|
||||
Top = y - Height / 2;
|
||||
Invalidate();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the size of the font is scaled
|
||||
/// </summary>
|
||||
/// <param name="matrix"></param>
|
||||
public override void Transform(Matrix matrix)
|
||||
{
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
int widthBefore = rect.Width;
|
||||
int heightBefore = rect.Height;
|
||||
|
||||
// Transform this container
|
||||
base.Transform(matrix);
|
||||
rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
|
||||
int widthAfter = rect.Width;
|
||||
int heightAfter = rect.Height;
|
||||
float factor = ((float)widthAfter / widthBefore + (float)heightAfter / heightBefore) / 2;
|
||||
|
||||
fontSize *= factor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override the parent, calculate the label number, than draw
|
||||
/// </summary>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="rm"></param>
|
||||
public override void Draw(Graphics graphics, RenderMode rm)
|
||||
{
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||
graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
|
||||
string text = ((Surface)Parent).CountStepLabels(this).ToString();
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
if (_drawAsRectangle)
|
||||
{
|
||||
RectangleContainer.DrawRectangle(rect, graphics, rm, 0, Color.Transparent, fillColor, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EllipseContainer.DrawEllipse(rect, graphics, rm, 0, Color.Transparent, fillColor, false);
|
||||
}
|
||||
using (FontFamily fam = new FontFamily(FontFamily.GenericSansSerif.Name))
|
||||
{
|
||||
using (Font _font = new Font(fam, fontSize, FontStyle.Bold, GraphicsUnit.Pixel))
|
||||
{
|
||||
TextContainer.DrawText(graphics, rect, 0, lineColor, false, _stringFormat, text, _font);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ClickableAt(int x, int y)
|
||||
{
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
if (_drawAsRectangle)
|
||||
{
|
||||
return RectangleContainer.RectangleClickableAt(rect, 0, fillColor, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
return EllipseContainer.EllipseClickableAt(rect, 0, fillColor, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,547 +0,0 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Drawing.Fields;
|
||||
using Greenshot.Helpers;
|
||||
using Greenshot.Memento;
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Drawing.Text;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a textbox (extends RectangleContainer for border/background support
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class TextContainer : RectangleContainer, ITextContainer
|
||||
{
|
||||
// If makeUndoable is true the next text-change will make the change undoable.
|
||||
// This is set to true AFTER the first change is made, as there is already a "add element" on the undo stack
|
||||
private bool makeUndoable;
|
||||
[NonSerialized]
|
||||
private Font _font;
|
||||
public Font Font
|
||||
{
|
||||
get
|
||||
{
|
||||
return _font;
|
||||
}
|
||||
}
|
||||
|
||||
[NonSerialized]
|
||||
private TextBox _textBox;
|
||||
|
||||
/// <summary>
|
||||
/// The StringFormat object is not serializable!!
|
||||
/// </summary>
|
||||
[NonSerialized]
|
||||
private StringFormat _stringFormat = new StringFormat();
|
||||
public StringFormat StringFormat
|
||||
{
|
||||
get
|
||||
{
|
||||
return _stringFormat;
|
||||
}
|
||||
}
|
||||
private string text;
|
||||
// there is a binding on the following property!
|
||||
public string Text
|
||||
{
|
||||
get { return text; }
|
||||
set { ChangeText(value, true); }
|
||||
}
|
||||
|
||||
internal void ChangeText(string newText, bool allowUndoable)
|
||||
{
|
||||
if ((text == null && newText != null) || (text != null && !string.Equals(text, newText)))
|
||||
{
|
||||
if (makeUndoable && allowUndoable)
|
||||
{
|
||||
makeUndoable = false;
|
||||
_parent.MakeUndoable(new TextChangeMemento(this), false);
|
||||
}
|
||||
text = newText;
|
||||
OnPropertyChanged("Text");
|
||||
}
|
||||
}
|
||||
|
||||
public TextContainer(Surface parent) : base(parent)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
protected override void InitializeFields()
|
||||
{
|
||||
AddField(GetType(), FieldType.LINE_THICKNESS, 2);
|
||||
AddField(GetType(), FieldType.LINE_COLOR, DefaultLineColor);
|
||||
AddField(GetType(), FieldType.SHADOW, false);
|
||||
AddField(GetType(), FieldType.FONT_ITALIC, false);
|
||||
AddField(GetType(), FieldType.FONT_BOLD, false);
|
||||
AddField(GetType(), FieldType.FILL_COLOR, Color.White);
|
||||
AddField(GetType(), FieldType.FONT_FAMILY, FontFamily.GenericSansSerif.Name);
|
||||
AddField(GetType(), FieldType.FONT_SIZE, 20f);
|
||||
AddField(GetType(), FieldType.TEXT_HORIZONTAL_ALIGNMENT, StringAlignment.Center);
|
||||
AddField(GetType(), FieldType.TEXT_VERTICAL_ALIGNMENT, StringAlignment.Center);
|
||||
}
|
||||
|
||||
[OnDeserialized]
|
||||
private void OnDeserialized(StreamingContext context)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_font != null)
|
||||
{
|
||||
_font.Dispose();
|
||||
_font = null;
|
||||
}
|
||||
if (_stringFormat != null)
|
||||
{
|
||||
_stringFormat.Dispose();
|
||||
_stringFormat = null;
|
||||
}
|
||||
if (_textBox != null)
|
||||
{
|
||||
_textBox.Dispose();
|
||||
_textBox = null;
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
private void Init()
|
||||
{
|
||||
_stringFormat = new StringFormat
|
||||
{
|
||||
Trimming = StringTrimming.EllipsisWord
|
||||
};
|
||||
|
||||
CreateTextBox();
|
||||
|
||||
UpdateFormat();
|
||||
UpdateTextBoxFormat();
|
||||
|
||||
PropertyChanged += TextContainer_PropertyChanged;
|
||||
FieldChanged += TextContainer_FieldChanged;
|
||||
}
|
||||
|
||||
public override void Invalidate()
|
||||
{
|
||||
base.Invalidate();
|
||||
if (_textBox != null && _textBox.Visible)
|
||||
{
|
||||
_textBox.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void FitToText()
|
||||
{
|
||||
Size textSize = TextRenderer.MeasureText(text, _font);
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Width = textSize.Width + lineThickness;
|
||||
Height = textSize.Height + lineThickness;
|
||||
}
|
||||
|
||||
private void TextContainer_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (_textBox.Visible)
|
||||
{
|
||||
_textBox.Invalidate();
|
||||
}
|
||||
|
||||
UpdateTextBoxPosition();
|
||||
UpdateTextBoxFormat();
|
||||
if (e.PropertyName.Equals("Selected"))
|
||||
{
|
||||
if (!Selected && _textBox.Visible)
|
||||
{
|
||||
HideTextBox();
|
||||
}
|
||||
else if (Selected && Status == EditStatus.DRAWING)
|
||||
{
|
||||
ShowTextBox();
|
||||
}
|
||||
else if (Selected && Status == EditStatus.IDLE && _textBox.Visible)
|
||||
{
|
||||
// Fix (workaround) for BUG-1698
|
||||
_parent.KeysLocked = true;
|
||||
}
|
||||
}
|
||||
if (_textBox.Visible)
|
||||
{
|
||||
_textBox.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
private void TextContainer_FieldChanged(object sender, FieldChangedEventArgs e)
|
||||
{
|
||||
if (_textBox.Visible)
|
||||
{
|
||||
_textBox.Invalidate();
|
||||
}
|
||||
// Only dispose the font, and re-create it, when a font field has changed.
|
||||
if (e.Field.FieldType.Name.StartsWith("FONT"))
|
||||
{
|
||||
if (_font != null)
|
||||
{
|
||||
_font.Dispose();
|
||||
_font = null;
|
||||
}
|
||||
UpdateFormat();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateAlignment();
|
||||
}
|
||||
UpdateTextBoxFormat();
|
||||
|
||||
if (_textBox != null && _textBox.Visible)
|
||||
{
|
||||
_textBox.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnDoubleClick()
|
||||
{
|
||||
ShowTextBox();
|
||||
}
|
||||
|
||||
private void CreateTextBox()
|
||||
{
|
||||
_textBox = new TextBox
|
||||
{
|
||||
ImeMode = ImeMode.On,
|
||||
Multiline = true,
|
||||
AcceptsTab = true,
|
||||
AcceptsReturn = true,
|
||||
BorderStyle = BorderStyle.None,
|
||||
Visible = false
|
||||
};
|
||||
|
||||
_textBox.DataBindings.Add("Text", this, "Text", false, DataSourceUpdateMode.OnPropertyChanged);
|
||||
_textBox.LostFocus += textBox_LostFocus;
|
||||
_textBox.KeyDown += textBox_KeyDown;
|
||||
}
|
||||
|
||||
private void ShowTextBox()
|
||||
{
|
||||
_parent.KeysLocked = true;
|
||||
_parent.Controls.Add(_textBox);
|
||||
EnsureTextBoxContrast();
|
||||
_textBox.Show();
|
||||
_textBox.Focus();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes textbox background dark if text color is very bright
|
||||
/// </summary>
|
||||
private void EnsureTextBoxContrast()
|
||||
{
|
||||
Color lc = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
if (lc.R > 203 && lc.G > 203 && lc.B > 203)
|
||||
{
|
||||
_textBox.BackColor = Color.FromArgb(51, 51, 51);
|
||||
}
|
||||
else
|
||||
{
|
||||
_textBox.BackColor = Color.White;
|
||||
}
|
||||
}
|
||||
|
||||
private void HideTextBox()
|
||||
{
|
||||
_parent.Focus();
|
||||
_textBox.Hide();
|
||||
_parent.KeysLocked = false;
|
||||
_parent.Controls.Remove(_textBox);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Make sure the size of the font is scaled
|
||||
/// </summary>
|
||||
/// <param name="matrix"></param>
|
||||
public override void Transform(Matrix matrix)
|
||||
{
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
int pixelsBefore = rect.Width * rect.Height;
|
||||
|
||||
// Transform this container
|
||||
base.Transform(matrix);
|
||||
rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
|
||||
int pixelsAfter = rect.Width * rect.Height;
|
||||
float factor = pixelsAfter / (float)pixelsBefore;
|
||||
|
||||
float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE);
|
||||
fontSize *= factor;
|
||||
SetFieldValue(FieldType.FONT_SIZE, fontSize);
|
||||
UpdateFormat();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate the Font-Formal so we can draw correctly
|
||||
/// </summary>
|
||||
protected void UpdateFormat()
|
||||
{
|
||||
string fontFamily = GetFieldValueAsString(FieldType.FONT_FAMILY);
|
||||
bool fontBold = GetFieldValueAsBool(FieldType.FONT_BOLD);
|
||||
bool fontItalic = GetFieldValueAsBool(FieldType.FONT_ITALIC);
|
||||
float fontSize = GetFieldValueAsFloat(FieldType.FONT_SIZE);
|
||||
try
|
||||
{
|
||||
FontStyle fs = FontStyle.Regular;
|
||||
|
||||
bool hasStyle = false;
|
||||
using (FontFamily fam = new FontFamily(fontFamily))
|
||||
{
|
||||
bool boldAvailable = fam.IsStyleAvailable(FontStyle.Bold);
|
||||
if (fontBold && boldAvailable)
|
||||
{
|
||||
fs |= FontStyle.Bold;
|
||||
hasStyle = true;
|
||||
}
|
||||
|
||||
bool italicAvailable = fam.IsStyleAvailable(FontStyle.Italic);
|
||||
if (fontItalic && italicAvailable)
|
||||
{
|
||||
fs |= FontStyle.Italic;
|
||||
hasStyle = true;
|
||||
}
|
||||
|
||||
if (!hasStyle)
|
||||
{
|
||||
bool regularAvailable = fam.IsStyleAvailable(FontStyle.Regular);
|
||||
if (regularAvailable)
|
||||
{
|
||||
fs = FontStyle.Regular;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (boldAvailable)
|
||||
{
|
||||
fs = FontStyle.Bold;
|
||||
}
|
||||
else if (italicAvailable)
|
||||
{
|
||||
fs = FontStyle.Italic;
|
||||
}
|
||||
}
|
||||
}
|
||||
_font?.Dispose();
|
||||
_font = new Font(fam, fontSize, fs, GraphicsUnit.Pixel);
|
||||
_textBox.Font = _font;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ex.Data.Add("fontFamily", fontFamily);
|
||||
ex.Data.Add("fontBold", fontBold);
|
||||
ex.Data.Add("fontItalic", fontItalic);
|
||||
ex.Data.Add("fontSize", fontSize);
|
||||
throw;
|
||||
}
|
||||
|
||||
UpdateAlignment();
|
||||
}
|
||||
|
||||
private void UpdateAlignment()
|
||||
{
|
||||
_stringFormat.Alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT);
|
||||
_stringFormat.LineAlignment = (StringAlignment)GetFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will create the textbox exactly to the inner size of the element
|
||||
/// is a bit of a hack, but for now it seems to work...
|
||||
/// </summary>
|
||||
private void UpdateTextBoxPosition()
|
||||
{
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
|
||||
int lineWidth = (int)Math.Floor(lineThickness / 2d);
|
||||
int correction = (lineThickness + 1) % 2;
|
||||
if (lineThickness <= 1)
|
||||
{
|
||||
lineWidth = 1;
|
||||
correction = -1;
|
||||
}
|
||||
Rectangle absRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
_textBox.Left = absRectangle.Left + lineWidth;
|
||||
_textBox.Top = absRectangle.Top + lineWidth;
|
||||
if (lineThickness <= 1)
|
||||
{
|
||||
lineWidth = 0;
|
||||
}
|
||||
_textBox.Width = absRectangle.Width - 2 * lineWidth + correction;
|
||||
_textBox.Height = absRectangle.Height - 2 * lineWidth + correction;
|
||||
}
|
||||
|
||||
public override void ApplyBounds(RectangleF newBounds)
|
||||
{
|
||||
base.ApplyBounds(newBounds);
|
||||
UpdateTextBoxPosition();
|
||||
}
|
||||
|
||||
private void UpdateTextBoxFormat()
|
||||
{
|
||||
if (_textBox == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
StringAlignment alignment = (StringAlignment)GetFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT);
|
||||
switch (alignment)
|
||||
{
|
||||
case StringAlignment.Near:
|
||||
_textBox.TextAlign = HorizontalAlignment.Left;
|
||||
break;
|
||||
case StringAlignment.Far:
|
||||
_textBox.TextAlign = HorizontalAlignment.Right;
|
||||
break;
|
||||
case StringAlignment.Center:
|
||||
_textBox.TextAlign = HorizontalAlignment.Center;
|
||||
break;
|
||||
}
|
||||
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
_textBox.ForeColor = lineColor;
|
||||
}
|
||||
|
||||
private void textBox_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
// ESC and Enter/Return (w/o Shift) hide text editor
|
||||
if (e.KeyCode == Keys.Escape || ((e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter) && e.Modifiers == Keys.None))
|
||||
{
|
||||
HideTextBox();
|
||||
e.SuppressKeyPress = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void textBox_LostFocus(object sender, EventArgs e)
|
||||
{
|
||||
// next change will be made undoable
|
||||
makeUndoable = true;
|
||||
HideTextBox();
|
||||
}
|
||||
|
||||
public override void Draw(Graphics graphics, RenderMode rm)
|
||||
{
|
||||
base.Draw(graphics, rm);
|
||||
|
||||
graphics.SmoothingMode = SmoothingMode.HighQuality;
|
||||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
graphics.CompositingQuality = CompositingQuality.HighQuality;
|
||||
graphics.PixelOffsetMode = PixelOffsetMode.None;
|
||||
graphics.TextRenderingHint = TextRenderingHint.SystemDefault;
|
||||
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
if (Selected && rm == RenderMode.EDIT)
|
||||
{
|
||||
DrawSelectionBorder(graphics, rect);
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// we only draw the shadow if there is no background
|
||||
bool shadow = GetFieldValueAsBool(FieldType.SHADOW);
|
||||
Color fillColor = GetFieldValueAsColor(FieldType.FILL_COLOR);
|
||||
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
|
||||
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
|
||||
bool drawShadow = shadow && (fillColor == Color.Transparent || fillColor == Color.Empty);
|
||||
|
||||
DrawText(graphics, rect, lineThickness, lineColor, drawShadow, _stringFormat, text, _font);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method can be used from other containers
|
||||
/// </summary>
|
||||
/// <param name="graphics"></param>
|
||||
/// <param name="drawingRectange"></param>
|
||||
/// <param name="lineThickness"></param>
|
||||
/// <param name="fontColor"></param>
|
||||
/// <param name="drawShadow"></param>
|
||||
/// <param name="stringFormat"></param>
|
||||
/// <param name="text"></param>
|
||||
/// <param name="font"></param>
|
||||
public static void DrawText(Graphics graphics, Rectangle drawingRectange, int lineThickness, Color fontColor, bool drawShadow, StringFormat stringFormat, string text, Font font)
|
||||
{
|
||||
int textOffset = lineThickness > 0 ? (int)Math.Ceiling(lineThickness / 2d) : 0;
|
||||
// draw shadow before anything else
|
||||
if (drawShadow)
|
||||
{
|
||||
int basealpha = 100;
|
||||
int alpha = basealpha;
|
||||
int steps = 5;
|
||||
int currentStep = 1;
|
||||
while (currentStep <= steps)
|
||||
{
|
||||
int offset = currentStep;
|
||||
Rectangle shadowRect = GuiRectangle.GetGuiRectangle(drawingRectange.Left + offset, drawingRectange.Top + offset, drawingRectange.Width, drawingRectange.Height);
|
||||
if (lineThickness > 0)
|
||||
{
|
||||
shadowRect.Inflate(-textOffset, -textOffset);
|
||||
}
|
||||
using (Brush fontBrush = new SolidBrush(Color.FromArgb(alpha, 100, 100, 100)))
|
||||
{
|
||||
graphics.DrawString(text, font, fontBrush, shadowRect, stringFormat);
|
||||
currentStep++;
|
||||
alpha = alpha - basealpha / steps;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lineThickness > 0)
|
||||
{
|
||||
drawingRectange.Inflate(-textOffset, -textOffset);
|
||||
}
|
||||
using (Brush fontBrush = new SolidBrush(fontColor))
|
||||
{
|
||||
if (stringFormat != null)
|
||||
{
|
||||
graphics.DrawString(text, font, fontBrush, drawingRectange, stringFormat);
|
||||
}
|
||||
else
|
||||
{
|
||||
graphics.DrawString(text, font, fontBrush, drawingRectange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ClickableAt(int x, int y)
|
||||
{
|
||||
Rectangle r = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
r.Inflate(5, 5);
|
||||
return r.Contains(x, y);
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue