greenshot/Greenshot/Drawing/Fields/AbstractFieldHolder.cs

201 lines
5.7 KiB
C#

/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.Serialization;
using Greenshot.Configuration;
using GreenshotPlugin.IniFile;
using log4net;
using GreenshotPlugin.Interfaces.Drawing;
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 ILog LOG = LogManager.GetLogger(typeof(AbstractFieldHolder));
private static readonly EditorConfiguration EditorConfig = IniConfig.GetIniSection<EditorConfiguration>();
[NonSerialized]
private readonly IDictionary<IField, PropertyChangedEventHandler> _handlers = new Dictionary<IField, PropertyChangedEventHandler>();
/// <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 IDictionary<IFieldType, IField> _fieldsByType = new Dictionary<IFieldType, IField>();
private readonly IList<IField> fields = new List<IField>();
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
_fieldsByType = new Dictionary<IFieldType, IField>();
// listen to changing properties
foreach (var field in fields)
{
field.PropertyChanged += delegate {
_fieldChanged?.Invoke(this, new FieldChangedEventArgs(field));
};
_fieldsByType[field.FieldType] = field;
}
}
public void AddField(Type requestingType, IFieldType fieldType, object fieldValue)
{
AddField(EditorConfig.CreateField(requestingType, fieldType, fieldValue));
}
public virtual void AddField(IField field)
{
fields.Add(field);
if (_fieldsByType == null)
{
return;
}
if (_fieldsByType.ContainsKey(field.FieldType))
{
if (LOG.IsDebugEnabled)
{
LOG.DebugFormat("A field with of type '{0}' already exists in this {1}, will overwrite.", field.FieldType, GetType());
}
}
_fieldsByType[field.FieldType] = field;
_handlers[field] = (sender, args) =>
{
_fieldChanged?.Invoke(this, new FieldChangedEventArgs(field));
};
field.PropertyChanged += _handlers[field];
}
public void RemoveField(IField field)
{
fields.Remove(field);
_fieldsByType.Remove(field.FieldType);
field.PropertyChanged -= _handlers[field];
_handlers.Remove(field);
}
public IList<IField> GetFields()
{
return fields;
}
public IField GetField(IFieldType fieldType)
{
try
{
return _fieldsByType[fieldType];
}
catch (KeyNotFoundException e)
{
throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e);
}
}
public object GetFieldValue(IFieldType fieldType)
{
return GetField(fieldType)?.Value;
}
public string GetFieldValueAsString(IFieldType fieldType)
{
return Convert.ToString(GetFieldValue(fieldType));
}
public int GetFieldValueAsInt(IFieldType fieldType)
{
return Convert.ToInt32(GetFieldValue(fieldType));
}
public decimal GetFieldValueAsDecimal(IFieldType fieldType)
{
return Convert.ToDecimal(GetFieldValue(fieldType));
}
public double GetFieldValueAsDouble(IFieldType fieldType)
{
return Convert.ToDouble(GetFieldValue(fieldType));
}
public float GetFieldValueAsFloat(IFieldType fieldType)
{
return Convert.ToSingle(GetFieldValue(fieldType));
}
public bool GetFieldValueAsBool(IFieldType fieldType)
{
return Convert.ToBoolean(GetFieldValue(fieldType));
}
public Color GetFieldValueAsColor(IFieldType fieldType, Color defaultColor = default)
{
return (Color)(GetFieldValue(fieldType) ?? defaultColor);
}
public bool HasField(IFieldType fieldType)
{
return _fieldsByType.ContainsKey(fieldType);
}
public bool HasFieldValue(IFieldType fieldType)
{
return HasField(fieldType) && _fieldsByType[fieldType].HasValue;
}
public void SetFieldValue(IFieldType fieldType, object value)
{
try
{
_fieldsByType[fieldType].Value = value;
}
catch (KeyNotFoundException e)
{
throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e);
}
}
protected void OnFieldChanged(object sender, FieldChangedEventArgs e)
{
_fieldChanged?.Invoke(sender, e);
}
}
}